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

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

Merge "driver: input: sensors: SMI130 early buffer implemented"

parents 2322d15f cfd9484c
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -126,4 +126,12 @@ depends on SENSORS_SMI_ACC4XY
	help
	 If you say yes here, you get support for Bosch Sensortec's
	 sensor driver of SMI_ACC4XY with mag sensor support.

config ENABLE_SMI_ACC_GYRO_BUFFERING
	bool "Enable accel & gyro  boot time sensor sample buffering"
	depends on SMI130
	help
	 Say Y here if you want to buffer boot time sensor
	 samples for ASM330 accelerometer and gyroscope

endif
+276 −0
Original line number Diff line number Diff line
@@ -1528,6 +1528,16 @@ struct bosch_sensor_data {
	};
};

#ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING
#define SMI_ACC_MAXSAMPLE        4000
#define G_MAX                    23920640
struct smi_acc_sample {
	int xyz[3];
	unsigned int tsec;
	unsigned long long tnsec;
};
#endif

struct smi130_accacc {
	s16 x;
	s16 y;
@@ -1590,6 +1600,16 @@ struct smi130_acc_data {
	struct timer_list	tap_timer;
	int tap_time_period;
#endif
#ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING
	bool read_acc_boot_sample;
	int acc_bufsample_cnt;
	bool acc_buffer_smi130_samples;
	struct kmem_cache *smi_acc_cachepool;
	struct smi_acc_sample *smi130_acc_samplist[SMI_ACC_MAXSAMPLE];
	int max_buffer_time;
	struct input_dev *accbuf_dev;
	int report_evt_cnt;
#endif
};

#ifdef CONFIG_HAS_EARLYSUSPEND
@@ -4044,6 +4064,23 @@ static int smi130_acc_read_temperature(struct i2c_client *client,
	return comres;
}

#ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING
static inline int smi130_check_acc_early_buff_enable_flag(
		struct smi130_acc_data *client_data)
{
	if (client_data->acc_buffer_smi130_samples == true)
		return 1;
	else
		return 0;
}
#else
static inline int smi130_check_acc_early_buff_enable_flag(
		struct smi130_acc_data *client_data)
{
	return 0;
}
#endif

static ssize_t smi130_acc_enable_int_store(struct device *dev,
		struct device_attribute *attr,
		const char *buf, size_t count)
@@ -5365,6 +5402,10 @@ static ssize_t smi130_acc_range_store(struct device *dev,
	struct i2c_client *client = to_i2c_client(dev);
	struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);

	error = smi130_check_acc_early_buff_enable_flag(smi130_acc);
	if (error)
		return count;

	error = kstrtoul(buf, 10, &data);
	if (error)
		return error;
@@ -5397,6 +5438,10 @@ static ssize_t smi130_acc_bandwidth_store(struct device *dev,
	struct i2c_client *client = to_i2c_client(dev);
	struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);

	error = smi130_check_acc_early_buff_enable_flag(smi130_acc);
	if (error)
		return count;

	error = kstrtoul(buf, 10, &data);
	if (error)
		return error;
@@ -5436,6 +5481,10 @@ static ssize_t smi130_acc_mode_store(struct device *dev,
	struct i2c_client *client = to_i2c_client(dev);
	struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);

	error = smi130_check_acc_early_buff_enable_flag(smi130_acc);
	if (error)
		return count;

	error = kstrtoul(buf, 10, &data);
	if (error)
		return error;
@@ -6432,10 +6481,97 @@ static void smi130_acc_tap_timeout_handle(unsigned long data)
}
#endif

#ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING
static int smi_acc_read_bootsampl(struct smi130_acc_data *client_data,
		unsigned long enable_read)
{
	int i = 0;

	if (enable_read) {
		client_data->acc_buffer_smi130_samples = false;
		for (i = 0; i < client_data->acc_bufsample_cnt; i++) {
			if (client_data->debug_level & 0x08)
				PINFO("acc=%d,x=%d,y=%d,z=%d,sec=%d,ns=%lld\n",
				i, client_data->smi130_acc_samplist[i]->xyz[0],
				client_data->smi130_acc_samplist[i]->xyz[1],
				client_data->smi130_acc_samplist[i]->xyz[2],
				client_data->smi130_acc_samplist[i]->tsec,
				client_data->smi130_acc_samplist[i]->tnsec);
			input_report_abs(client_data->accbuf_dev, ABS_X,
				client_data->smi130_acc_samplist[i]->xyz[0]);
			input_report_abs(client_data->accbuf_dev, ABS_Y,
				client_data->smi130_acc_samplist[i]->xyz[1]);
			input_report_abs(client_data->accbuf_dev, ABS_Z,
				client_data->smi130_acc_samplist[i]->xyz[2]);
			input_report_abs(client_data->accbuf_dev, ABS_RX,
				client_data->smi130_acc_samplist[i]->tsec);
			input_report_abs(client_data->accbuf_dev, ABS_RY,
				client_data->smi130_acc_samplist[i]->tnsec);
			input_sync(client_data->accbuf_dev);
		}
	} else {
		/* clean up */
		if (client_data->acc_bufsample_cnt != 0) {
			for (i = 0; i < SMI_ACC_MAXSAMPLE; i++)
				kmem_cache_free(client_data->smi_acc_cachepool,
					client_data->smi130_acc_samplist[i]);
			kmem_cache_destroy(client_data->smi_acc_cachepool);
			client_data->acc_bufsample_cnt = 0;
		}

	}
	/*SYN_CONFIG indicates end of data*/
	input_event(client_data->accbuf_dev, EV_SYN, SYN_CONFIG, 0xFFFFFFFF);
	input_sync(client_data->accbuf_dev);
	if (client_data->debug_level & 0x08)
		PINFO("End of acc samples bufsample_cnt=%d\n",
				client_data->acc_bufsample_cnt);
	return 0;
}
static ssize_t read_acc_boot_sample_show(struct device *dev,
		struct device_attribute *attr,
		char *buf)
{
	struct i2c_client *client = to_i2c_client(dev);
	struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);

	return snprintf(buf, 16, "%u\n",
			smi130_acc->read_acc_boot_sample);
}

static ssize_t read_acc_boot_sample_store(struct device *dev,
		struct device_attribute *attr,
		const char *buf, size_t count)
{
	int err;
	struct i2c_client *client = to_i2c_client(dev);
	struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
	unsigned long enable = 0;

	err = kstrtoul(buf, 10, &enable);
	if (err)
		return err;
	if (enable > 1) {
		PERR("Invalid value of input, input=%ld\n", enable);
		return -EINVAL;
	}
	err = smi_acc_read_bootsampl(smi130_acc, enable);
	if (err)
		return err;

	smi130_acc->read_acc_boot_sample = enable;
	return count;
}
#endif

static DEVICE_ATTR(range, S_IRUGO | S_IWUSR,
		smi130_acc_range_show, smi130_acc_range_store);
static DEVICE_ATTR(bandwidth, S_IRUGO | S_IWUSR,
		smi130_acc_bandwidth_show, smi130_acc_bandwidth_store);
#ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING
static DEVICE_ATTR(read_acc_boot_sample, 0644,
		read_acc_boot_sample_show, read_acc_boot_sample_store);
#endif
static DEVICE_ATTR(op_mode, S_IRUGO | S_IWUSR,
		smi130_acc_mode_show, smi130_acc_mode_store);
static DEVICE_ATTR(value, S_IRUSR,
@@ -6555,6 +6691,9 @@ static DEVICE_ATTR(en_double_tap, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
static struct attribute *smi130_acc_attributes[] = {
	&dev_attr_range.attr,
	&dev_attr_bandwidth.attr,
#ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING
	&dev_attr_read_acc_boot_sample.attr,
#endif
	&dev_attr_op_mode.attr,
	&dev_attr_value.attr,
	&dev_attr_value_cache.attr,
@@ -6752,6 +6891,136 @@ static void smi130_acc_slope_interrupt_handle(struct smi130_acc_data *smi130_acc
	}
}
#endif
#ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING
static void store_acc_boot_sample(struct smi130_acc_data *client_data,
				int x, int y, int z, struct timespec ts)
{
	if (false == client_data->acc_buffer_smi130_samples)
		return;
	if (ts.tv_sec <  client_data->max_buffer_time) {
		if (client_data->acc_bufsample_cnt < SMI_ACC_MAXSAMPLE) {
			client_data->smi130_acc_samplist[client_data->
				acc_bufsample_cnt]->xyz[0] = x;
			client_data->smi130_acc_samplist[client_data->
				acc_bufsample_cnt]->xyz[1] = y;
			client_data->smi130_acc_samplist[client_data->
				acc_bufsample_cnt]->xyz[2] = z;
			client_data->smi130_acc_samplist[client_data->
				acc_bufsample_cnt]->tsec = ts.tv_sec;
			client_data->smi130_acc_samplist[client_data->
				acc_bufsample_cnt]->tnsec = ts.tv_nsec;
			client_data->acc_bufsample_cnt++;
		}
	} else {
		PINFO("End of ACC buffering %d\n",
				client_data->acc_bufsample_cnt);
		client_data->acc_buffer_smi130_samples = false;
	}
}
#else
static void store_acc_boot_sample(struct smi130_acc_data *client_data,
		int x, int y, int z, struct timespec ts)
{
}
#endif

#ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING
static int smi130_acc_early_buff_init(struct i2c_client *client,
			struct smi130_acc_data *client_data)
{
	int i = 0, err = 0;

	client_data->acc_bufsample_cnt = 0;
	client_data->report_evt_cnt = 5;
	client_data->max_buffer_time = 40;

	client_data->smi_acc_cachepool = kmem_cache_create("acc_sensor_sample",
			sizeof(struct smi_acc_sample),
			0,
			SLAB_HWCACHE_ALIGN, NULL);
	if (!client_data->smi_acc_cachepool) {
		PERR("smi_acc_cachepool cache create failed\n");
		err = -ENOMEM;
		goto clean_exit1;
	}
	for (i = 0; i < SMI_ACC_MAXSAMPLE; i++) {
		client_data->smi130_acc_samplist[i] =
			kmem_cache_alloc(client_data->smi_acc_cachepool,
					GFP_KERNEL);
		if (!client_data->smi130_acc_samplist[i]) {
			err = -ENOMEM;
			goto clean_exit2;
		}
	}

	client_data->accbuf_dev = input_allocate_device();
	if (!client_data->accbuf_dev) {
		err = -ENOMEM;
		PERR("input device allocation failed\n");
		goto clean_exit3;
	}
	client_data->accbuf_dev->name = "smi130_accbuf";
	client_data->accbuf_dev->id.bustype = BUS_I2C;
	input_set_events_per_packet(client_data->accbuf_dev,
			client_data->report_evt_cnt * SMI_ACC_MAXSAMPLE);
	set_bit(EV_ABS, client_data->accbuf_dev->evbit);
	input_set_abs_params(client_data->accbuf_dev, ABS_X,
			-G_MAX, G_MAX, 0, 0);
	input_set_abs_params(client_data->accbuf_dev, ABS_Y,
			-G_MAX, G_MAX, 0, 0);
	input_set_abs_params(client_data->accbuf_dev, ABS_Z,
			-G_MAX, G_MAX, 0, 0);
	input_set_abs_params(client_data->accbuf_dev, ABS_RX,
			-G_MAX, G_MAX, 0, 0);
	input_set_abs_params(client_data->accbuf_dev, ABS_RY,
			-G_MAX, G_MAX, 0, 0);
	err = input_register_device(client_data->accbuf_dev);
	if (err) {
		PERR("unable to register input device %s\n",
				client_data->accbuf_dev->name);
		goto clean_exit3;
	}

	client_data->acc_buffer_smi130_samples = true;

	smi130_acc_set_mode(client, SMI_ACC2X2_MODE_NORMAL, 1);
	smi130_acc_set_bandwidth(client, SMI_ACC2X2_BW_62_50HZ);
	smi130_acc_set_range(client, SMI_ACC2X2_RANGE_2G);

	return 1;

clean_exit3:
	input_free_device(client_data->accbuf_dev);
clean_exit2:
	for (i = 0; i < SMI_ACC_MAXSAMPLE; i++)
		kmem_cache_free(client_data->smi_acc_cachepool,
				client_data->smi130_acc_samplist[i]);
clean_exit1:
	kmem_cache_destroy(client_data->smi_acc_cachepool);
	return 0;
}

static void smi130_acc_input_cleanup(struct smi130_acc_data *client_data)
{
	int i = 0;

	input_unregister_device(client_data->accbuf_dev);
	input_free_device(client_data->accbuf_dev);
	for (i = 0; i < SMI_ACC_MAXSAMPLE; i++)
		kmem_cache_free(client_data->smi_acc_cachepool,
				client_data->smi130_acc_samplist[i]);
	kmem_cache_destroy(client_data->smi_acc_cachepool);
}
#else
static int smi130_acc_early_buff_init(struct i2c_client *client,
			struct smi130_acc_data *client_data)
{
	return 1;
}
static void smi130_acc_input_cleanup(struct smi130_acc_data *client_data)
{
}
#endif

static void smi130_acc_irq_work_func(struct work_struct *work)
{
@@ -6800,6 +7069,7 @@ static void smi130_acc_irq_work_func(struct work_struct *work)
		smi130_acc->value = acc;
		mutex_unlock(&smi130_acc->value_mutex);
	}
	store_acc_boot_sample(smi130_acc, acc.x, acc.y, acc.z, ts);
#endif

	smi130_acc_get_interruptstatus1(smi130_acc->smi130_acc_client, &status);
@@ -7268,6 +7538,11 @@ static int smi130_acc_probe(struct i2c_client *client,
	PDEBUG("data->IRQ = %d", data->IRQ);
	err = request_irq(data->IRQ, smi130_acc_irq_handler, IRQF_TRIGGER_RISING,
			"smi130_acc", data);

	err = smi130_acc_early_buff_init(client, data);
	if (!err)
		goto exit;

	PINFO("SMI130_ACC driver probe successfully");

	return 0;
@@ -7379,6 +7654,7 @@ static int smi130_acc_remove(struct i2c_client *client)
	if (NULL == data)
		return 0;

	smi130_acc_input_cleanup(data);
	smi130_acc_set_enable(&client->dev, 0);
#ifdef CONFIG_HAS_EARLYSUSPEND
	unregister_early_suspend(&data->early_suspend);
+306 −3
Original line number Diff line number Diff line
@@ -249,6 +249,16 @@ struct bosch_sensor_data {
	};
};

#ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING
#define SMI_GYRO_MAXSAMPLE       4000
#define G_MAX                    23920640
struct smi_gyro_sample {
	int xyz[3];
	unsigned int tsec;
	unsigned long long tnsec;
};
#endif

struct smi_gyro_client_data {
	struct smi130_gyro_t device;
	struct i2c_client *client;
@@ -281,6 +291,16 @@ struct smi_gyro_client_data {
	uint8_t gpio_pin;
	int16_t IRQ;
	struct work_struct irq_work;
#ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING
	bool read_gyro_boot_sample;
	int gyro_bufsample_cnt;
	bool gyro_buffer_smi130_samples;
	struct kmem_cache *smi_gyro_cachepool;
	struct smi_gyro_sample *smi130_gyro_samplist[SMI_GYRO_MAXSAMPLE];
	int max_buffer_time;
	struct input_dev *gyrobuf_dev;
	int report_evt_cnt;
#endif
};

static struct i2c_client *smi_gyro_client;
@@ -831,6 +851,23 @@ static ssize_t smi_gyro_show_chip_id(struct device *dev,
	return snprintf(buf, 16, "%d\n", SENSOR_CHIP_ID_SMI_GYRO);
}

#ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING
static inline int smi130_check_gyro_early_buff_enable_flag(
		struct smi_gyro_client_data *client_data)
{
	if (client_data->gyro_buffer_smi130_samples == true)
		return 1;
	else
		return 0;
}
#else
static inline int smi130_check_gyro_early_buff_enable_flag(
		struct smi_gyro_client_data *client_data)
{
	return 0;
}
#endif

static ssize_t smi_gyro_show_op_mode(struct device *dev,
		struct device_attribute *attr, char *buf)
{
@@ -858,6 +895,10 @@ static ssize_t smi_gyro_store_op_mode(struct device *dev,

	long op_mode;

	err = smi130_check_gyro_early_buff_enable_flag(client_data);
	if (err)
		return count;

	err = kstrtoul(buf, 10, &op_mode);
	if (err)
		return err;
@@ -911,6 +952,13 @@ static ssize_t smi_gyro_store_range(struct device *dev,
{
	int err;
	unsigned long range;
	struct input_dev *input = to_input_dev(dev);
	struct smi_gyro_client_data *client_data = input_get_drvdata(input);

	err = smi130_check_gyro_early_buff_enable_flag(client_data);
	if (err)
		return count;

	err = kstrtoul(buf, 10, &range);
	if (err)
		return err;
@@ -952,6 +1000,11 @@ static ssize_t smi_gyro_store_bandwidth(struct device *dev,
	struct smi_gyro_client_data *client_data = input_get_drvdata(input);
	unsigned long bandwidth;
	u8 op_mode = 0xff;

	err = smi130_check_gyro_early_buff_enable_flag(client_data);
	if (err)
		return count;

	err = kstrtoul(buf, 10, &bandwidth);
	if (err)
		return err;
@@ -1445,8 +1498,96 @@ static ssize_t smi130_gyro_driver_version_show(struct device *dev
			DRIVER_VERSION);
	return ret;
}

#ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING
static int smi_gyro_read_bootsampl(struct smi_gyro_client_data *client_data,
		unsigned long enable_read)
{
	int i = 0;

	if (enable_read) {
		client_data->gyro_buffer_smi130_samples = false;
		for (i = 0; i < client_data->gyro_bufsample_cnt; i++) {
			if (client_data->debug_level & 0x08)
				PINFO("gyro=%d,x=%d,y=%d,z=%d,sec=%d,ns=%lld\n",
				i, client_data->smi130_gyro_samplist[i]->xyz[0],
				client_data->smi130_gyro_samplist[i]->xyz[1],
				client_data->smi130_gyro_samplist[i]->xyz[2],
				client_data->smi130_gyro_samplist[i]->tsec,
				client_data->smi130_gyro_samplist[i]->tnsec);
			input_report_abs(client_data->gyrobuf_dev, ABS_X,
				client_data->smi130_gyro_samplist[i]->xyz[0]);
			input_report_abs(client_data->gyrobuf_dev, ABS_Y,
				client_data->smi130_gyro_samplist[i]->xyz[1]);
			input_report_abs(client_data->gyrobuf_dev, ABS_Z,
				client_data->smi130_gyro_samplist[i]->xyz[2]);
			input_report_abs(client_data->gyrobuf_dev, ABS_RX,
				client_data->smi130_gyro_samplist[i]->tsec);
			input_report_abs(client_data->gyrobuf_dev, ABS_RY,
				client_data->smi130_gyro_samplist[i]->tnsec);
			input_sync(client_data->gyrobuf_dev);
		}
	} else {
		/* clean up */
		if (client_data->gyro_bufsample_cnt != 0) {
			for (i = 0; i < SMI_GYRO_MAXSAMPLE; i++)
				kmem_cache_free(client_data->smi_gyro_cachepool,
					client_data->smi130_gyro_samplist[i]);
			kmem_cache_destroy(client_data->smi_gyro_cachepool);
			client_data->gyro_bufsample_cnt = 0;
		}

	}
	/*SYN_CONFIG indicates end of data*/
	input_event(client_data->gyrobuf_dev, EV_SYN, SYN_CONFIG, 0xFFFFFFFF);
	input_sync(client_data->gyrobuf_dev);
	if (client_data->debug_level & 0x08)
		PINFO("End of gyro samples bufsample_cnt=%d\n",
				client_data->gyro_bufsample_cnt);
	return 0;
}
static ssize_t read_gyro_boot_sample_show(struct device *dev,
		struct device_attribute *attr,
		char *buf)
{
	struct input_dev *input = to_input_dev(dev);
	struct smi_gyro_client_data *client_data = input_get_drvdata(input);

	return snprintf(buf, 16, "%u\n",
			client_data->read_gyro_boot_sample);
}
static ssize_t read_gyro_boot_sample_store(struct device *dev,
		struct device_attribute *attr,
		const char *buf, size_t count)
{
	int err;
	struct input_dev *input = to_input_dev(dev);
	struct smi_gyro_client_data *client_data = input_get_drvdata(input);
	unsigned long enable = 0;

	err = kstrtoul(buf, 10, &enable);
	if (err)
		return err;
	if (enable > 1) {
		PERR("Invalid value of input, input=%ld\n", enable);
		return -EINVAL;
	}
	err = smi_gyro_read_bootsampl(client_data, enable);
	if (err)
		return err;
	client_data->read_gyro_boot_sample = enable;

	return count;
}
#endif


static DEVICE_ATTR(chip_id, S_IRUSR,
		smi_gyro_show_chip_id, NULL);
#ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING
static DEVICE_ATTR(read_gyro_boot_sample, 0644,
		read_gyro_boot_sample_show, read_gyro_boot_sample_store);
#endif
static DEVICE_ATTR(op_mode, S_IRUGO | S_IWUSR,
		smi_gyro_show_op_mode, smi_gyro_store_op_mode);
static DEVICE_ATTR(value, S_IRUSR,
@@ -1500,6 +1641,9 @@ static DEVICE_ATTR(fifo_tag, S_IRUGO | S_IWUSR,

static struct attribute *smi_gyro_attributes[] = {
	&dev_attr_chip_id.attr,
#ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING
	&dev_attr_read_gyro_boot_sample.attr,
#endif
	&dev_attr_op_mode.attr,
	&dev_attr_value.attr,
	&dev_attr_range.attr,
@@ -1574,6 +1718,159 @@ static void smi_gyro_input_destroy(struct smi_gyro_client_data *client_data)
	input_unregister_device(dev);
	input_free_device(dev);
}
#ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING
static void store_gyro_boot_sample(struct smi_gyro_client_data *client_data,
			int x, int y, int z, struct timespec ts)
{
	if (false == client_data->gyro_buffer_smi130_samples)
		return;
	if (ts.tv_sec <  client_data->max_buffer_time) {
		if (client_data->gyro_bufsample_cnt < SMI_GYRO_MAXSAMPLE) {
			client_data->smi130_gyro_samplist[client_data->
				gyro_bufsample_cnt]->xyz[0] = x;
			client_data->smi130_gyro_samplist[client_data->
				gyro_bufsample_cnt]->xyz[1] = y;
			client_data->smi130_gyro_samplist[client_data->
				gyro_bufsample_cnt]->xyz[2] = z;
			client_data->smi130_gyro_samplist[client_data->
				gyro_bufsample_cnt]->tsec = ts.tv_sec;
			client_data->smi130_gyro_samplist[client_data->
				gyro_bufsample_cnt]->tnsec = ts.tv_nsec;
			client_data->gyro_bufsample_cnt++;
		}
	} else {
		PINFO("End of GYRO buffering %d",
				client_data->gyro_bufsample_cnt);
		client_data->gyro_buffer_smi130_samples = false;
	}
}
#else
static void store_gyro_boot_sample(struct smi_gyro_client_data *client_data,
		int x, int y, int z, struct timespec ts)
{
}
#endif


#ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING
static int smi130_gyro_early_buff_init(struct smi_gyro_client_data *client_data)
{
	int i = 0, err = 0;

	client_data->gyro_bufsample_cnt = 0;
	client_data->report_evt_cnt = 5;
	client_data->max_buffer_time = 40;

	client_data->smi_gyro_cachepool = kmem_cache_create("gyro_sensor_sample"
			, sizeof(struct smi_gyro_sample), 0,
			SLAB_HWCACHE_ALIGN, NULL);
	if (!client_data->smi_gyro_cachepool) {
		PERR("smi_gyro_cachepool cache create failed\n");
		err = -ENOMEM;
		goto clean_exit1;
	}

	for (i = 0; i < SMI_GYRO_MAXSAMPLE; i++) {
		client_data->smi130_gyro_samplist[i] =
			kmem_cache_alloc(client_data->smi_gyro_cachepool,
					GFP_KERNEL);
		if (!client_data->smi130_gyro_samplist[i]) {
			err = -ENOMEM;
			goto clean_exit2;
		}
	}


	client_data->gyrobuf_dev = input_allocate_device();
	if (!client_data->gyrobuf_dev) {
		err = -ENOMEM;
		PERR("input device allocation failed\n");
		goto clean_exit3;
	}
	client_data->gyrobuf_dev->name = "smi130_gyrobuf";
	client_data->gyrobuf_dev->id.bustype = BUS_I2C;
	input_set_events_per_packet(client_data->gyrobuf_dev,
			client_data->report_evt_cnt * SMI_GYRO_MAXSAMPLE);
	set_bit(EV_ABS, client_data->gyrobuf_dev->evbit);
	input_set_abs_params(client_data->gyrobuf_dev, ABS_X,
			-G_MAX, G_MAX, 0, 0);
	input_set_abs_params(client_data->gyrobuf_dev, ABS_Y,
			-G_MAX, G_MAX, 0, 0);
	input_set_abs_params(client_data->gyrobuf_dev, ABS_Z,
			-G_MAX, G_MAX, 0, 0);
	input_set_abs_params(client_data->gyrobuf_dev, ABS_RX,
			-G_MAX, G_MAX, 0, 0);
	input_set_abs_params(client_data->gyrobuf_dev, ABS_RY,
			-G_MAX, G_MAX, 0, 0);
	err = input_register_device(client_data->gyrobuf_dev);
	if (err) {
		PERR("unable to register input device %s\n",
				client_data->gyrobuf_dev->name);
		goto clean_exit3;
	}

	client_data->gyro_buffer_smi130_samples = true;

	smi130_gyro_set_mode(SMI130_GYRO_MODE_NORMAL);
	smi130_gyro_delay(5);

	smi130_gyro_set_bw(5);
	smi130_gyro_delay(5);

	smi130_gyro_set_range_reg(4);
	smi130_gyro_delay(5);

	smi130_gyro_set_mode(SMI130_GYRO_MODE_NORMAL);
	smi130_gyro_delay(5);

	smi130_gyro_set_range_reg(4);
	smi130_gyro_delay(5);

	smi130_gyro_set_data_en(SMI130_GYRO_ENABLE);

	return 1;

clean_exit3:
	input_free_device(client_data->gyrobuf_dev);
clean_exit2:
	for (i = 0; i < SMI_GYRO_MAXSAMPLE; i++)
		kmem_cache_free(client_data->smi_gyro_cachepool,
				client_data->smi130_gyro_samplist[i]);
clean_exit1:
	kmem_cache_destroy(client_data->smi_gyro_cachepool);
	return 0;
}

static void smi130_gyro_input_cleanup(struct smi_gyro_client_data *client_data)
{
	int i = 0;

	input_unregister_device(client_data->gyrobuf_dev);
	input_free_device(client_data->gyrobuf_dev);
	for (i = 0; i < SMI_GYRO_MAXSAMPLE; i++)
		kmem_cache_free(client_data->smi_gyro_cachepool,
				client_data->smi130_gyro_samplist[i]);
	kmem_cache_destroy(client_data->smi_gyro_cachepool);
}

static int smi130_enable_int1(void)
{
	return smi130_gyro_set_data_en(SMI130_GYRO_DISABLE);
}
#else
static int smi130_gyro_early_buff_init(struct smi_gyro_client_data *client_data)
{
	return 1;
}
static void smi130_gyro_input_cleanup(struct smi_gyro_client_data *client_data)
{
}
static int smi130_enable_int1(void)
{
	return smi130_gyro_set_data_en(SMI130_GYRO_ENABLE);
}
#endif


#if defined(SMI130_GYRO_ENABLE_INT1) || defined(SMI130_GYRO_ENABLE_INT2)
static void smi130_gyro_irq_work_func(struct work_struct *work)
@@ -1598,7 +1895,8 @@ static void smi130_gyro_irq_work_func(struct work_struct *work)
	input_event(client_data->input, EV_MSC,
		MSC_SCAN, gyro_data.dataz);
	input_sync(client_data->input);

	store_gyro_boot_sample(client_data, gyro_data.datax,
			gyro_data.datay, gyro_data.dataz, ts);
}

static irqreturn_t smi_gyro_irq_handler(int irq, void *handle)
@@ -1727,7 +2025,7 @@ static int smi_gyro_probe(struct i2c_client *client, const struct i2c_device_id
	smi130_gyro_delay(5);
	err += smi130_gyro_set_int_data(SMI130_GYRO_INT1_DATA, SMI130_GYRO_ENABLE);
	smi130_gyro_delay(5);
	err += smi130_gyro_set_data_en(SMI130_GYRO_ENABLE);
	err += smi130_enable_int1();
	smi130_gyro_delay(5);
	/*default odr is 100HZ*/
	err += SMI_GYRO_CALL_API(set_bw)(7);
@@ -1786,6 +2084,11 @@ static int smi_gyro_probe(struct i2c_client *client, const struct i2c_device_id
	}
	INIT_WORK(&client_data->irq_work, smi130_gyro_irq_work_func);
#endif

	err = smi130_gyro_early_buff_init(client_data);
	if (!err)
		return err;

	PINFO("sensor %s probed successfully", SENSOR_NAME);

	dev_dbg(&client->dev,
@@ -1926,6 +2229,7 @@ static int smi_gyro_remove(struct i2c_client *client)
#ifdef CONFIG_HAS_EARLYSUSPEND
		unregister_early_suspend(&client_data->early_suspend_handler);
#endif
		smi130_gyro_input_cleanup(client_data);
		mutex_lock(&client_data->mutex_op_mode);
		SMI_GYRO_CALL_API(get_mode)(&op_mode);
		if (SMI_GYRO_VAL_NAME(MODE_NORMAL) == op_mode) {
@@ -1942,7 +2246,6 @@ static int smi_gyro_remove(struct i2c_client *client)
				&smi_gyro_attribute_group);
		smi_gyro_input_destroy(client_data);
		kfree(client_data);

		smi_gyro_client = NULL;
	}