static ssize_t apds990x_set_lux_thresh(struct apds990x_chip *chip, u32 *target, const char *buf) { unsigned long thresh; int ret; ret = kstrtoul(buf, 0, &thresh); if (ret) return ret; if (thresh > APDS_RANGE) return -EINVAL; mutex_lock(&chip->mutex); *target = thresh; /* * Don't update values in HW if we are still waiting for * first interrupt to come after device handle open call. */ if (!chip->lux_wait_fresh_res) apds990x_refresh_athres(chip); mutex_unlock(&chip->mutex); return ret; }
/* Called always with mutex locked */ static int apds990x_calc_again(struct apds990x_chip *chip) { int curr_again = chip->again_meas; int next_again = chip->again_meas; int ret = 0; /* Calculate suitable als gain */ if (chip->lux_clear == chip->a_max_result) next_again -= 2; /* ALS saturated. Decrease gain by 2 steps */ else if (chip->lux_clear > chip->a_max_result / 2) next_again--; else if (chip->lux_clear < APDS_LUX_GAIN_LO_LIMIT_STRICT) next_again += 2; /* Too dark. Increase gain by 2 steps */ else if (chip->lux_clear < APDS_LUX_GAIN_LO_LIMIT) next_again++; /* Limit gain to available range */ if (next_again < 0) next_again = 0; else if (next_again > APDS990X_MAX_AGAIN) next_again = APDS990X_MAX_AGAIN; /* Let's check can we trust the measured result */ if (chip->lux_clear == chip->a_max_result) /* Result can be totally garbage due to saturation */ ret = -ERANGE; else if (next_again != curr_again && chip->lux_clear < APDS_LUX_GAIN_LO_LIMIT_STRICT) /* * Gain is changed and measurement result is very small. * Result can be totally garbage due to underflow */ ret = -ERANGE; chip->again_next = next_again; apds990x_write_byte(chip, APDS990X_CONTROL, (chip->pdrive << 6) | (chip->pdiode << 4) | (chip->pgain << 2) | (chip->again_next << 0)); /* * Error means bad result -> re-measurement is needed. The forced * refresh uses fastest possible persistence setting to get result * as soon as possible. */ if (ret < 0) apds990x_force_a_refresh(chip); else apds990x_refresh_athres(chip); return ret; }