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

Commit a0bba46a 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: change akm09911 measure mode to continuous"

parents f23eb71e 1039904b
Loading
Loading
Loading
Loading
+63 −79
Original line number Diff line number Diff line
@@ -49,7 +49,7 @@
#define AKM09911_VIO_MIN_UV	1750000
#define AKM09911_VIO_MAX_UV	1950000

#define STATUS_ERROR(st)		(((st)&0x09) != 0x01)
#define STATUS_ERROR(st)		(((st)&0x08) != 0x0)

/* Save last device state for power down */
struct akm_sensor_state {
@@ -83,11 +83,6 @@ struct akm_compass_data {
	struct mutex accel_mutex;
	int16_t accel_data[3];

	/* Positive value means the device is working.
	   0 or negative value means the device is not woking,
	   i.e. in power-down mode. */
	int8_t	is_busy;

	struct mutex	val_mutex;
	uint32_t		enable_flag;
	int64_t			delay[AKM_NUM_SENSORS];
@@ -219,12 +214,6 @@ static int AKECS_Set_CNTL(

	/***** lock *****/
	mutex_lock(&akm->sensor_mutex);
	/* Busy check */
	if (akm->is_busy > 0) {
		dev_err(&akm->i2c->dev,
				"%s: device is busy.", __func__);
		err = -EBUSY;
	} else {
	/* Set measure mode */
	buffer[0] = AKM_REG_MODE;
	buffer[1] = mode;
@@ -235,13 +224,10 @@ static int AKECS_Set_CNTL(
	} else {
		dev_vdbg(&akm->i2c->dev,
				"Mode is set to (%d).", mode);
			/* Set flag */
			akm->is_busy = 1;
		atomic_set(&akm->drdy, 0);
		/* wait at least 100us after changing mode */
		udelay(100);
	}
	}

	mutex_unlock(&akm->sensor_mutex);
	/***** unlock *****/
@@ -270,8 +256,6 @@ static int AKECS_Set_PowerDown(
		/* wait at least 100us after changing mode */
		udelay(100);
	}
	/* Clear status */
	akm->is_busy = 0;
	atomic_set(&akm->drdy, 0);

	mutex_unlock(&akm->sensor_mutex);
@@ -311,8 +295,6 @@ static int AKECS_Reset(
	}
	/* Device will be accessible 100 us after */
	udelay(100);
	/* Clear status */
	akm->is_busy = 0;
	atomic_set(&akm->drdy, 0);
	mutex_unlock(&akm->sensor_mutex);
	/***** unlock *****/
@@ -334,6 +316,10 @@ static int AKECS_SetMode(
	case AKM_MODE_SNG_MEASURE:
	case AKM_MODE_SELF_TEST:
	case AKM_MODE_FUSE_ACCESS:
	case AKM_MODE_CONTINUOUS_10HZ:
	case AKM_MODE_CONTINUOUS_20HZ:
	case AKM_MODE_CONTINUOUS_50HZ:
	case AKM_MODE_CONTINUOUS_100HZ:
		err = AKECS_Set_CNTL(akm, mode);
		break;
	case AKM_MODE_POWERDOWN:
@@ -450,9 +436,9 @@ static int AKECS_GetData_Poll(
	uint8_t buffer[AKM_SENSOR_DATA_SIZE];
	int err;

	/* Read status */
	/* Read data */
	buffer[0] = AKM_REG_STATUS;
	err = akm_i2c_rxdata(akm->i2c, buffer, 1);
	err = akm_i2c_rxdata(akm->i2c, buffer, AKM_SENSOR_DATA_SIZE);
	if (err < 0) {
		dev_err(&akm->i2c->dev, "%s failed.", __func__);
		return err;
@@ -460,25 +446,15 @@ static int AKECS_GetData_Poll(

	/* Check ST bit */
	if (!(AKM_DRDY_IS_HIGH(buffer[0])))
		return -EAGAIN;
		dev_dbg(&akm->i2c->dev, "DRDY is low. Use last value.\n");

	/* Read rest data */
	buffer[1] = AKM_REG_STATUS + 1;
	err = akm_i2c_rxdata(akm->i2c, &(buffer[1]), AKM_SENSOR_DATA_SIZE-1);
	if (err < 0) {
		dev_err(&akm->i2c->dev, "%s failed.", __func__);
		return err;
	}
	/* Data is over run is */
	if (AKM_DOR_IS_HIGH(buffer[0]))
		dev_dbg(&akm->i2c->dev, "Data over run!\n");

	memcpy(rbuf, buffer, size);
	atomic_set(&akm->drdy, 0);

	/***** lock *****/
	mutex_lock(&akm->sensor_mutex);
	akm->is_busy = 0;
	mutex_unlock(&akm->sensor_mutex);
	/***** unlock *****/

	return 0;
}

@@ -857,12 +833,25 @@ static void akm_compass_sysfs_update_status(
		en, atomic_read(&akm->active));
}

static inline uint8_t akm_select_frequency(int64_t delay_ns)
{
	if (delay_ns >= 100000000LL)
		return AKM_MODE_CONTINUOUS_10HZ;
	else if (delay_ns >= 50000000LL)
		return AKM_MODE_CONTINUOUS_20HZ;
	else if (delay_ns >= 20000000LL)
		return AKM_MODE_CONTINUOUS_50HZ;
	else
		return AKM_MODE_CONTINUOUS_100HZ;
}

static int akm_enable_set(struct sensors_classdev *sensors_cdev,
		unsigned int enable)
{
	int ret = 0;
	struct akm_compass_data *akm = container_of(sensors_cdev,
			struct akm_compass_data, cdev);
	uint8_t mode;

	mutex_lock(&akm->val_mutex);
	akm->enable_flag &= ~(1<<MAG_DATA_FLAG);
@@ -880,7 +869,8 @@ static int akm_enable_set(struct sensors_classdev *sensors_cdev,
		}

		if (akm->auto_report) {
			AKECS_SetMode(akm, AKM_MODE_SNG_MEASURE);
			mode = akm_select_frequency(akm->delay[MAG_DATA_FLAG]);
			AKECS_SetMode(akm, mode);
			if (akm->use_hrtimer)
				hrtimer_start(&akm->poll_timer,
					ns_to_ktime(akm->delay[MAG_DATA_FLAG]),
@@ -1013,12 +1003,19 @@ static int akm_poll_delay_set(struct sensors_classdev *sensors_cdev,
{
	struct akm_compass_data *akm = container_of(sensors_cdev,
			struct akm_compass_data, cdev);
	uint8_t mode;
	int ret;

	mutex_lock(&akm->val_mutex);

	akm->delay[MAG_DATA_FLAG] = delay_msec * 1000000;
	mutex_unlock(&akm->val_mutex);
	mode = akm_select_frequency(akm->delay[MAG_DATA_FLAG]);
	ret = AKECS_SetMode(akm, mode);
	if (ret < 0)
		dev_err(&akm->i2c->dev, "Failed to set to mode(%x)\n", mode);

	return 0;
	mutex_unlock(&akm->val_mutex);
	return ret;
}

static ssize_t akm_compass_sysfs_delay_show(
@@ -1450,7 +1447,6 @@ static irqreturn_t akm_compass_irq(int irq, void *handle)
	err = akm_i2c_rxdata(akm->i2c, buffer, AKM_SENSOR_DATA_SIZE);
	if (err < 0) {
		dev_err(&akm->i2c->dev, "IRQ I2C error.");
		akm->is_busy = 0;
		mutex_unlock(&akm->sensor_mutex);
		/***** unlock *****/

@@ -1461,7 +1457,6 @@ static irqreturn_t akm_compass_irq(int irq, void *handle)
		goto work_func_none;

	memcpy(akm->sense_data, buffer, AKM_SENSOR_DATA_SIZE);
	akm->is_busy = 0;

	mutex_unlock(&akm->sensor_mutex);
	/***** unlock *****/
@@ -1492,6 +1487,10 @@ static int akm_compass_suspend(struct device *dev)
			cancel_delayed_work_sync(&akm->dwork);
	}

	ret = AKECS_SetMode(akm, AKM_MODE_POWERDOWN);
	if (ret)
		dev_warn(&akm->i2c->dev, "Failed to set to POWERDOWN mode.\n");

	akm->state.power_on = akm->power_enabled;
	if (akm->state.power_on)
		akm_compass_power_set(akm, false);
@@ -1509,6 +1508,7 @@ static int akm_compass_resume(struct device *dev)
{
	struct akm_compass_data *akm = dev_get_drvdata(dev);
	int ret = 0;
	uint8_t mode;

	ret = pinctrl_select_state(akm->pinctrl, akm->pin_default);
	if (ret)
@@ -1521,13 +1521,14 @@ static int akm_compass_resume(struct device *dev)
			goto exit;
		}

		ret = AKECS_SetMode(akm, akm->state.mode);
		if (ret) {
			dev_err(dev, "Sensor state resume fail!\n");
		if (AKM_IS_MAG_DATA_ENABLED() && akm->auto_report) {
			mode = akm_select_frequency(akm->delay[MAG_DATA_FLAG]);
			ret = AKECS_SetMode(akm, mode);
			if (ret < 0) {
				dev_err(&akm->i2c->dev, "Failed to set to mode(%d)\n",
						mode);
				goto exit;
			}

		if (AKM_IS_MAG_DATA_ENABLED() && akm->auto_report) {
			if (akm->use_hrtimer)
				hrtimer_start(&akm->poll_timer,
					ns_to_ktime(akm->delay[MAG_DATA_FLAG]),
@@ -1779,27 +1780,15 @@ static int akm_report_data(struct akm_compass_data *akm)
	int ret;
	int mag_x, mag_y, mag_z;
	int tmp;
	int count = 10;

	do {
		/* The typical time for single measurement is 7.2ms */
	ret = AKECS_GetData_Poll(akm, dat_buf, AKM_SENSOR_DATA_SIZE);
		if (ret == -EAGAIN) {
			dev_dbg(&akm->i2c->dev, "Data not ready, delay 1ms\n");
			udelay(1000);
		}
	} while ((ret == -EAGAIN) && (--count));

	if (!count) {
		dev_err(&akm->i2c->dev, "Timeout get valid data.\n");
	if (ret) {
		dev_err(&akm->i2c->dev, "Get data failed.\n");
		return -EIO;

	}

	tmp = dat_buf[0] | dat_buf[8];
	if (STATUS_ERROR(tmp)) {
		dev_warn(&akm->i2c->dev, "Status error(0x%x). Reset...\n",
			       tmp);
	if (STATUS_ERROR(dat_buf[8])) {
		dev_warn(&akm->i2c->dev, "Status error. Reset...\n");
		AKECS_Reset(akm, 0);
		return -EIO;
	}
@@ -1895,10 +1884,6 @@ static void akm_dev_poll(struct work_struct *work)
	if (ret < 0)
		dev_warn(&akm->i2c->dev, "Failed to report data\n");

	ret = AKECS_SetMode(akm, AKM_MODE_SNG_MEASURE);
	if ((ret < 0) && (ret != -EBUSY))
		dev_warn(&akm->i2c->dev, "Failed to set mode\n");

	if (!akm->use_hrtimer)
		queue_delayed_work(akm->work_queue, &akm->dwork,
			(unsigned long)nsecs_to_jiffies64(
@@ -1954,7 +1939,6 @@ int akm_compass_probe(struct i2c_client *client, const struct i2c_device_id *id)
	atomic_set(&s_akm->active, 0);
	atomic_set(&s_akm->drdy, 0);

	s_akm->is_busy = 0;
	s_akm->enable_flag = 0;

	/* Set to 1G in Android coordination, AKSC format */
+9 −0
Original line number Diff line number Diff line
@@ -32,6 +32,10 @@
#define AK09911_MODE_SELF_TEST		0x10
#define AK09911_MODE_FUSE_ACCESS	0x1F
#define AK09911_MODE_POWERDOWN		0x00
#define AK09911_MODE_CONTINUOUS_10HZ	0x02 /* 10Hz */
#define AK09911_MODE_CONTINUOUS_20HZ	0x04 /* 20Hz */
#define AK09911_MODE_CONTINUOUS_50HZ	0x06 /* 50Hz */
#define AK09911_MODE_CONTINUOUS_100HZ	0x08 /* 100Hz */
#define AK09911_RESET_DATA			0x01

#define AK09911_REGS_SIZE		13
@@ -48,6 +52,7 @@
#define AKM_REG_STATUS			AK09911_REG_ST1
#define AKM_MEASURE_TIME_US		10000
#define AKM_DRDY_IS_HIGH(x)		((x) & 0x01)
#define AKM_DOR_IS_HIGH(x)		((x) & 0x02)
#define AKM_SENSOR_INFO_SIZE	2
#define AKM_SENSOR_CONF_SIZE	3
#define AKM_SENSOR_DATA_SIZE	9
@@ -62,6 +67,10 @@
#define AKM_MODE_SELF_TEST		AK09911_MODE_SELF_TEST
#define AKM_MODE_FUSE_ACCESS	AK09911_MODE_FUSE_ACCESS
#define AKM_MODE_POWERDOWN		AK09911_MODE_POWERDOWN
#define AKM_MODE_CONTINUOUS_10HZ	AK09911_MODE_CONTINUOUS_10HZ
#define AKM_MODE_CONTINUOUS_20HZ	AK09911_MODE_CONTINUOUS_20HZ
#define AKM_MODE_CONTINUOUS_50HZ	AK09911_MODE_CONTINUOUS_50HZ
#define AKM_MODE_CONTINUOUS_100HZ	AK09911_MODE_CONTINUOUS_100HZ
#define AKM_RESET_DATA			AK09911_RESET_DATA

#define ACC_DATA_FLAG		0