Пример #1
0
static int isl29018_read_sensor_input(struct isl29018_chip *chip, int mode)
{
	int status;
	unsigned int lsb;
	unsigned int msb;
	struct device *dev = regmap_get_device(chip->regmap);

	/* Set mode */
	status = regmap_write(chip->regmap, ISL29018_REG_ADD_COMMAND1,
			      mode << COMMMAND1_OPMODE_SHIFT);
	if (status) {
		dev_err(dev,
			"Error in setting operating mode err %d\n", status);
		return status;
	}
	msleep(CONVERSION_TIME_MS);
	status = regmap_read(chip->regmap, ISL29018_REG_ADD_DATA_LSB, &lsb);
	if (status < 0) {
		dev_err(dev,
			"Error in reading LSB DATA with err %d\n", status);
		return status;
	}

	status = regmap_read(chip->regmap, ISL29018_REG_ADD_DATA_MSB, &msb);
	if (status < 0) {
		dev_err(dev,
			"Error in reading MSB DATA with error %d\n", status);
		return status;
	}
	dev_vdbg(dev, "MSB 0x%x and LSB 0x%x\n", msb, lsb);

	return (msb << 8) | lsb;
}
Пример #2
0
/* Channel IO */
static int isl29028_write_raw(struct iio_dev *indio_dev,
			      struct iio_chan_spec const *chan,
			      int val, int val2, long mask)
{
	struct isl29028_chip *chip = iio_priv(indio_dev);
	struct device *dev = regmap_get_device(chip->regmap);
	int ret = -EINVAL;

	mutex_lock(&chip->lock);
	switch (chan->type) {
	case IIO_PROXIMITY:
		if (mask != IIO_CHAN_INFO_SAMP_FREQ) {
			dev_err(dev,
				"proximity: mask value 0x%08lx not supported\n",
				mask);
			break;
		}
		if (val < 1 || val > 100) {
			dev_err(dev,
				"Samp_freq %d is not in range[1:100]\n", val);
			break;
		}
		ret = isl29028_set_proxim_sampling(chip, val);
		if (ret < 0) {
			dev_err(dev,
				"Setting proximity samp_freq fail, err %d\n",
				ret);
			break;
		}
		chip->prox_sampling = val;
		break;

	case IIO_LIGHT:
		if (mask != IIO_CHAN_INFO_SCALE) {
			dev_err(dev,
				"light: mask value 0x%08lx not supported\n",
				mask);
			break;
		}
		if ((val != 125) && (val != 2000)) {
			dev_err(dev,
				"lux scale %d is invalid [125, 2000]\n", val);
			break;
		}
		ret = isl29028_set_als_scale(chip, val);
		if (ret < 0) {
			dev_err(dev,
				"Setting lux scale fail with error %d\n", ret);
			break;
		}
		chip->lux_scale = val;
		break;

	default:
		dev_err(dev, "Unsupported channel type\n");
		break;
	}
	mutex_unlock(&chip->lock);
	return ret;
}
Пример #3
0
static int isl29028_als_get(struct isl29028_chip *chip, int *als_data)
{
	struct device *dev = regmap_get_device(chip->regmap);
	int ret;
	int als_ir_data;

	if (chip->als_ir_mode != MODE_ALS) {
		ret = isl29028_set_als_ir_mode(chip, MODE_ALS);
		if (ret < 0) {
			dev_err(dev,
				"Error in enabling ALS mode err %d\n", ret);
			return ret;
		}
		chip->als_ir_mode = MODE_ALS;
	}

	ret = isl29028_read_als_ir(chip, &als_ir_data);
	if (ret < 0)
		return ret;

	/*
	 * convert als data count to lux.
	 * if lux_scale = 125,  lux = count * 0.031
	 * if lux_scale = 2000, lux = count * 0.49
	 */
	if (chip->lux_scale == 125)
		als_ir_data = (als_ir_data * 31) / 1000;
	else
		als_ir_data = (als_ir_data * 49) / 100;

	*als_data = als_ir_data;
	return 0;
}
Пример #4
0
static int isl29018_chip_init(struct isl29018_chip *chip)
{
	int status;
	struct device *dev = regmap_get_device(chip->regmap);

	if (chip->type == isl29035) {
		unsigned int id;

		status = regmap_read(chip->regmap, ISL29035_REG_DEVICE_ID, &id);
		if (status < 0) {
			dev_err(dev,
				"Error reading ID register with error %d\n",
				status);
			return status;
		}

		id = (id & ISL29035_DEVICE_ID_MASK) >> ISL29035_DEVICE_ID_SHIFT;

		if (id != ISL29035_DEVICE_ID)
			return -ENODEV;

		/* Clear brownout bit */
		status = regmap_update_bits(chip->regmap,
					    ISL29035_REG_DEVICE_ID,
					    ISL29035_BOUT_MASK, 0);
		if (status < 0)
			return status;
	}
Пример #5
0
static int isl29028_read_raw(struct iio_dev *indio_dev,
			     struct iio_chan_spec const *chan,
			     int *val, int *val2, long mask)
{
	struct isl29028_chip *chip = iio_priv(indio_dev);
	struct device *dev = regmap_get_device(chip->regmap);
	int ret = -EINVAL;

	mutex_lock(&chip->lock);
	switch (mask) {
	case IIO_CHAN_INFO_RAW:
	case IIO_CHAN_INFO_PROCESSED:
		switch (chan->type) {
		case IIO_LIGHT:
			ret = isl29028_als_get(chip, val);
			break;
		case IIO_INTENSITY:
			ret = isl29028_ir_get(chip, val);
			break;
		case IIO_PROXIMITY:
			ret = isl29028_proxim_get(chip, val);
			break;
		default:
			break;
		}
		if (ret < 0)
			break;
		ret = IIO_VAL_INT;
		break;

	case IIO_CHAN_INFO_SAMP_FREQ:
		if (chan->type != IIO_PROXIMITY)
			break;
		*val = chip->prox_sampling;
		ret = IIO_VAL_INT;
		break;

	case IIO_CHAN_INFO_SCALE:
		if (chan->type != IIO_LIGHT)
			break;
		*val = chip->lux_scale;
		ret = IIO_VAL_INT;
		break;

	default:
		dev_err(dev, "mask value 0x%08lx not supported\n", mask);
		break;
	}
	mutex_unlock(&chip->lock);
	return ret;
}
Пример #6
0
static int isl29028_read_proxim(struct isl29028_chip *chip, int *prox)
{
	struct device *dev = regmap_get_device(chip->regmap);
	unsigned int data;
	int ret;

	ret = regmap_read(chip->regmap, ISL29028_REG_PROX_DATA, &data);
	if (ret < 0) {
		dev_err(dev, "Error in reading register %d, error %d\n",
			ISL29028_REG_PROX_DATA, ret);
		return ret;
	}
	*prox = data;
	return 0;
}
Пример #7
0
static int isl29028_ir_get(struct isl29028_chip *chip, int *ir_data)
{
	struct device *dev = regmap_get_device(chip->regmap);
	int ret;

	if (chip->als_ir_mode != MODE_IR) {
		ret = isl29028_set_als_ir_mode(chip, MODE_IR);
		if (ret < 0) {
			dev_err(dev,
				"Error in enabling IR mode err %d\n", ret);
			return ret;
		}
		chip->als_ir_mode = MODE_IR;
	}
	return isl29028_read_als_ir(chip, ir_data);
}
Пример #8
0
static int isl29028_chip_init(struct isl29028_chip *chip)
{
	struct device *dev = regmap_get_device(chip->regmap);
	int ret;

	chip->enable_prox  = false;
	chip->prox_sampling = 20;
	chip->lux_scale = 2000;
	chip->als_ir_mode = MODE_NONE;

	ret = regmap_write(chip->regmap, ISL29028_REG_TEST1_MODE, 0x0);
	if (ret < 0) {
		dev_err(dev, "%s(): write to reg %d failed, err = %d\n",
			__func__, ISL29028_REG_TEST1_MODE, ret);
		return ret;
	}
	ret = regmap_write(chip->regmap, ISL29028_REG_TEST2_MODE, 0x0);
	if (ret < 0) {
		dev_err(dev, "%s(): write to reg %d failed, err = %d\n",
			__func__, ISL29028_REG_TEST2_MODE, ret);
		return ret;
	}

	ret = regmap_write(chip->regmap, ISL29028_REG_CONFIGURE, 0x0);
	if (ret < 0) {
		dev_err(dev, "%s(): write to reg %d failed, err = %d\n",
			__func__, ISL29028_REG_CONFIGURE, ret);
		return ret;
	}

	ret = isl29028_set_proxim_sampling(chip, chip->prox_sampling);
	if (ret < 0) {
		dev_err(dev, "setting the proximity, err = %d\n", ret);
		return ret;
	}

	ret = isl29028_set_als_scale(chip, chip->lux_scale);
	if (ret < 0)
		dev_err(dev, "setting als scale failed, err = %d\n", ret);
	return ret;
}
Пример #9
0
static int mma7455_drdy(struct mma7455_data *mma7455)
{
	struct device *dev = regmap_get_device(mma7455->regmap);
	unsigned int reg;
	int tries = 3;
	int ret;

	while (tries-- > 0) {
		ret = regmap_read(mma7455->regmap, MMA7455_REG_STATUS, &reg);
		if (ret)
			return ret;

		if (reg & MMA7455_STATUS_DRDY)
			return 0;

		msleep(20);
	}

	dev_warn(dev, "data not ready\n");

	return -EIO;
}
Пример #10
0
static int isl29018_read_proximity_ir(struct isl29018_chip *chip, int scheme,
				      int *near_ir)
{
	int status;
	int prox_data = -1;
	int ir_data = -1;
	struct device *dev = regmap_get_device(chip->regmap);

	/* Do proximity sensing with required scheme */
	status = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMANDII,
				    COMMANDII_SCHEME_MASK,
				    scheme << COMMANDII_SCHEME_SHIFT);
	if (status) {
		dev_err(dev, "Error in setting operating mode\n");
		return status;
	}

	prox_data = isl29018_read_sensor_input(chip,
					       COMMMAND1_OPMODE_PROX_ONCE);
	if (prox_data < 0)
		return prox_data;

	if (scheme == 1) {
		*near_ir = prox_data;
		return 0;
	}

	ir_data = isl29018_read_sensor_input(chip, COMMMAND1_OPMODE_IR_ONCE);

	if (ir_data < 0)
		return ir_data;

	if (prox_data >= ir_data)
		*near_ir = prox_data - ir_data;
	else
		*near_ir = 0;

	return 0;
}
Пример #11
0
static int isl29028_read_als_ir(struct isl29028_chip *chip, int *als_ir)
{
	struct device *dev = regmap_get_device(chip->regmap);
	unsigned int lsb;
	unsigned int msb;
	int ret;

	ret = regmap_read(chip->regmap, ISL29028_REG_ALSIR_L, &lsb);
	if (ret < 0) {
		dev_err(dev,
			"Error in reading register ALSIR_L err %d\n", ret);
		return ret;
	}

	ret = regmap_read(chip->regmap, ISL29028_REG_ALSIR_U, &msb);
	if (ret < 0) {
		dev_err(dev,
			"Error in reading register ALSIR_U err %d\n", ret);
		return ret;
	}

	*als_ir = ((msb & 0xF) << 8) | (lsb & 0xFF);
	return 0;
}
Пример #12
0
static int isl29018_chip_init(struct isl29018_chip *chip)
{
	int status;
	struct device *dev = regmap_get_device(chip->regmap);

	if (chip->type == isl29035) {
		status = isl29035_detect(chip);
		if (status < 0)
			return status;
	}

	/* Code added per Intersil Application Note 1534:
	 *     When VDD sinks to approximately 1.8V or below, some of
	 * the part's registers may change their state. When VDD
	 * recovers to 2.25V (or greater), the part may thus be in an
	 * unknown mode of operation. The user can return the part to
	 * a known mode of operation either by (a) setting VDD = 0V for
	 * 1 second or more and then powering back up with a slew rate
	 * of 0.5V/ms or greater, or (b) via I2C disable all ALS/PROX
	 * conversions, clear the test registers, and then rewrite all
	 * registers to the desired values.
	 * ...
	 * FOR ISL29011, ISL29018, ISL29021, ISL29023
	 * 1. Write 0x00 to register 0x08 (TEST)
	 * 2. Write 0x00 to register 0x00 (CMD1)
	 * 3. Rewrite all registers to the desired values
	 *
	 * ISL29018 Data Sheet (FN6619.1, Feb 11, 2010) essentially says
	 * the same thing EXCEPT the data sheet asks for a 1ms delay after
	 * writing the CMD1 register.
	 */
	status = regmap_write(chip->regmap, ISL29018_REG_TEST, 0x0);
	if (status < 0) {
		dev_err(dev, "Failed to clear isl29018 TEST reg.(%d)\n",
			status);
		return status;
	}

	/* See Intersil AN1534 comments above.
	 * "Operating Mode" (COMMAND1) register is reprogrammed when
	 * data is read from the device.
	 */
	status = regmap_write(chip->regmap, ISL29018_REG_ADD_COMMAND1, 0);
	if (status < 0) {
		dev_err(dev, "Failed to clear isl29018 CMD1 reg.(%d)\n",
			status);
		return status;
	}

	usleep_range(1000, 2000);	/* per data sheet, page 10 */

	/* set defaults */
	status = isl29018_set_scale(chip, chip->scale.scale,
				    chip->scale.uscale);
	if (status < 0) {
		dev_err(dev, "Init of isl29018 fails\n");
		return status;
	}

	status = isl29018_set_integration_time(chip,
			isl29018_int_utimes[chip->type][chip->int_time]);
	if (status < 0) {
		dev_err(dev, "Init of isl29018 fails\n");
		return status;
	}

	return 0;
}