/* *Readsandcalculatescurrentluxvalue. *Therawch0andch1valuesoftheambientlightsensedinthelast *integrationcyclearereadfromthedevice. *Timescalefactorarrayvaluesareadjustedbasedontheintegrationtime. *Therawvaluesaremultipliedbyascalefactor,anddevicegainisobtained *usinggainindex.Limitchecksaredonenext,thentheratioofamultiple *ofch1value,tothech0value,iscalculated.Thearrayals_device_lux[] *declaredaboveisthenscannedtofindthefirstratiovaluethatisjust *abovetheratiowejustcalculated.Thech0andch1multiplierconstantsin *thearrayarethenusedalongwiththetimescalefactorarrayvalues,to *calculatethelux.
*/ staticint tsl2583_get_lux(struct iio_dev *indio_dev)
{
u16 ch0, ch1; /* separated ch0/ch1 data from device */
u32 lux; /* raw lux calculated from device data */
u64 lux64;
u32 ratio;
u8 buf[5]; struct tsl2583_lux *p; struct tsl2583_chip *chip = iio_priv(indio_dev); int i, ret;
ret = i2c_smbus_read_byte_data(chip->client, TSL2583_CMD_REG); if (ret < 0) {
dev_err(&chip->client->dev, "%s: failed to read CMD_REG register\n",
__func__); goto done;
}
/* is data new & valid */ if (!(ret & TSL2583_STA_ADC_INTR)) {
dev_err(&chip->client->dev, "%s: data not valid; returning last value\n",
__func__);
ret = chip->als_cur_info.lux; /* return LAST VALUE */ goto done;
}
for (i = 0; i < 4; i++) { int reg = TSL2583_CMD_REG | (TSL2583_ALS_CHAN0LO + i);
ret = i2c_smbus_read_byte_data(chip->client, reg); if (ret < 0) {
dev_err(&chip->client->dev, "%s: failed to read register %x\n",
__func__, reg); goto done;
}
buf[i] = ret;
}
/* *Clearthependinginterruptstatusbitonthechiptoallowthenext *integrationcycletostart.Thishastobedoneeventhoughthis *drivercurrentlydoesnotsupportinterrupts.
*/
ret = i2c_smbus_write_byte(chip->client,
(TSL2583_CMD_REG | TSL2583_CMD_SPL_FN |
TSL2583_CMD_ALS_INT_CLR)); if (ret < 0) {
dev_err(&chip->client->dev, "%s: failed to clear the interrupt bit\n",
__func__); goto done; /* have no data, so return failure */
}
if ((ch0 >= chip->als_saturation) || (ch1 >= chip->als_saturation)) goto return_max;
if (!ch0) { /* *Thesensorappearstobeintotaldarknesssosetthe *calculatedluxto0andreturnearlytoavoidadivisionby *zerobelowwhencalculatingtheratio.
*/
ret = 0;
chip->als_cur_info.lux = 0; goto done;
}
/* calculate ratio */
ratio = (ch1 << 15) / ch0;
/* convert to unscaled lux using the pointer to the table */ for (p = (struct tsl2583_lux *)chip->als_settings.als_device_lux;
p->ratio != 0 && p->ratio < ratio; p++)
;
/* note: lux is 31 bit max at this point */ if (ch1lux > ch0lux) {
dev_dbg(&chip->client->dev, "%s: No Data - Returning 0\n",
__func__);
ret = 0;
chip->als_cur_info.lux = 0; goto done;
}
lux = ch0lux - ch1lux;
}
/* adjust for active time scale */ if (chip->als_time_scale == 0)
lux = 0; else
lux = (lux + (chip->als_time_scale >> 1)) /
chip->als_time_scale;
ret = i2c_smbus_read_byte_data(chip->client,
TSL2583_CMD_REG | TSL2583_CNTRL); if (ret < 0) {
dev_err(&chip->client->dev, "%s: failed to read from the CNTRL register\n",
__func__); return ret;
}
if ((ret & (TSL2583_CNTL_ADC_ENBL | TSL2583_CNTL_PWR_ON))
!= (TSL2583_CNTL_ADC_ENBL | TSL2583_CNTL_PWR_ON)) {
dev_err(&chip->client->dev, "%s: Device is not powered on and/or ADC is not enabled\n",
__func__); return -EINVAL;
} elseif ((ret & TSL2583_STA_ADC_VALID) != TSL2583_STA_ADC_VALID) {
dev_err(&chip->client->dev, "%s: The two ADC channels have not completed an integration cycle\n",
__func__); return -ENODATA;
}
lux_val = tsl2583_get_lux(indio_dev); if (lux_val < 0) {
dev_err(&chip->client->dev, "%s: failed to get lux\n",
__func__); return lux_val;
}
/* Avoid division by zero of lux_value later on */ if (lux_val == 0) {
dev_err(&chip->client->dev, "%s: lux_val of 0 will produce out of range trim_value\n",
__func__); return -ENODATA;
}
gain_trim_val = (unsignedint)(((chip->als_settings.als_cal_target)
* chip->als_settings.als_gain_trim) / lux_val); if ((gain_trim_val < 250) || (gain_trim_val > 4000)) {
dev_err(&chip->client->dev, "%s: trim_val of %d is not within the range [250, 4000]\n",
__func__, gain_trim_val); return -ENODATA;
}
/* determine als integration register */
als_count = DIV_ROUND_CLOSEST(chip->als_settings.als_time * 100, 270); if (!als_count)
als_count = 1; /* ensure at least one cycle */
/* convert back to time (encompasses overrides) */
als_time = DIV_ROUND_CLOSEST(als_count * 27, 10);
val = 256 - als_count;
ret = i2c_smbus_write_byte_data(chip->client,
TSL2583_CMD_REG | TSL2583_ALS_TIME,
val); if (ret < 0) {
dev_err(&chip->client->dev, "%s: failed to set the als time to %d\n",
__func__, val); return ret;
}
/* set chip struct re scaling and saturation */
chip->als_saturation = als_count * 922; /* 90% of full scale */
chip->als_time_scale = DIV_ROUND_CLOSEST(als_time, 50);
return ret;
}
staticint tsl2583_set_als_gain(struct tsl2583_chip *chip)
{ int ret;
/* Set the gain based on als_settings struct */
ret = i2c_smbus_write_byte_data(chip->client,
TSL2583_CMD_REG | TSL2583_GAIN,
chip->als_settings.als_gain); if (ret < 0)
dev_err(&chip->client->dev, "%s: failed to set the gain to %d\n", __func__,
chip->als_settings.als_gain);
return ret;
}
staticint tsl2583_set_power_state(struct tsl2583_chip *chip, u8 state)
{ int ret;
ret = i2c_smbus_write_byte_data(chip->client,
TSL2583_CMD_REG | TSL2583_CNTRL, state); if (ret < 0)
dev_err(&chip->client->dev, "%s: failed to set the power state to %d\n", __func__,
state);
/* *Wenowhaveanarrayofintsstartingatvalue[1],and *enumeratedbyvalue[0]. *Weexpecteachgroupofthreeintsisonetableentry, *andthelasttableentryisall0.
*/
n = value[0]; if ((n % 3) || n < 6 || n > max_ints) {
dev_err(dev, "%s: The number of entries in the lux table must be a multiple of 3 and within the range [6, %d]\n",
__func__, max_ints); goto done;
} if ((value[n - 2] | value[n - 1] | value[n]) != 0) {
dev_err(dev, "%s: The last 3 entries in the lux table must be zeros.\n",
__func__); goto done;
}
staticint tsl2583_set_pm_runtime_busy(struct tsl2583_chip *chip, bool on)
{ int ret;
if (on) {
ret = pm_runtime_resume_and_get(&chip->client->dev);
} else {
pm_runtime_mark_last_busy(&chip->client->dev);
ret = pm_runtime_put_autosuspend(&chip->client->dev);
}
return ret;
}
staticint tsl2583_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask)
{ struct tsl2583_chip *chip = iio_priv(indio_dev); int ret, pm_ret;
ret = tsl2583_set_pm_runtime_busy(chip, true); if (ret < 0) return ret;
mutex_lock(&chip->als_mutex);
ret = -EINVAL; switch (mask) { case IIO_CHAN_INFO_RAW: if (chan->type == IIO_LIGHT) {
ret = tsl2583_get_lux(indio_dev); if (ret < 0) goto read_done;
ret = IIO_VAL_INT;
} break; case IIO_CHAN_INFO_PROCESSED: if (chan->type == IIO_LIGHT) {
ret = tsl2583_get_lux(indio_dev); if (ret < 0) goto read_done;
*val = ret;
ret = IIO_VAL_INT;
} break; case IIO_CHAN_INFO_CALIBBIAS: if (chan->type == IIO_LIGHT) {
*val = chip->als_settings.als_gain_trim;
ret = IIO_VAL_INT;
} break; case IIO_CHAN_INFO_CALIBSCALE: if (chan->type == IIO_LIGHT) {
*val = gainadj[chip->als_settings.als_gain].mean;
ret = IIO_VAL_INT;
} break; case IIO_CHAN_INFO_INT_TIME: if (chan->type == IIO_LIGHT) {
*val = 0;
*val2 = chip->als_settings.als_time;
ret = IIO_VAL_INT_PLUS_MICRO;
} break; default: break;
}
read_done:
mutex_unlock(&chip->als_mutex);
if (ret < 0) {
tsl2583_set_pm_runtime_busy(chip, false); return ret;
}
staticint tsl2583_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask)
{ struct tsl2583_chip *chip = iio_priv(indio_dev); int ret;
ret = tsl2583_set_pm_runtime_busy(chip, true); if (ret < 0) return ret;
mutex_lock(&chip->als_mutex);
ret = -EINVAL; switch (mask) { case IIO_CHAN_INFO_CALIBBIAS: if (chan->type == IIO_LIGHT) {
chip->als_settings.als_gain_trim = val;
ret = 0;
} break; case IIO_CHAN_INFO_CALIBSCALE: if (chan->type == IIO_LIGHT) { unsignedint i;
for (i = 0; i < ARRAY_SIZE(gainadj); i++) { if (gainadj[i].mean == val) {
chip->als_settings.als_gain = i;
ret = tsl2583_set_als_gain(chip); break;
}
}
} break; case IIO_CHAN_INFO_INT_TIME: if (chan->type == IIO_LIGHT && !val && val2 >= 50 &&
val2 <= 650 && !(val2 % 50)) {
chip->als_settings.als_time = val2;
ret = tsl2583_set_als_time(chip);
} break; default: break;
}
mutex_unlock(&chip->als_mutex);
if (ret < 0) {
tsl2583_set_pm_runtime_busy(chip, false); return ret;
}
ret = tsl2583_set_pm_runtime_busy(chip, false); if (ret < 0) return ret;
ret = i2c_smbus_read_byte_data(clientp,
TSL2583_CMD_REG | TSL2583_CHIPID); if (ret < 0) {
dev_err(&clientp->dev, "%s: failed to read the chip ID register\n", __func__); return ret;
}
if ((ret & TSL2583_CHIP_ID_MASK) != TSL2583_CHIP_ID) {
dev_err(&clientp->dev, "%s: received an unknown chip ID %x\n",
__func__, ret); return -EINVAL;
}
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.16Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-10-01)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.