static bool isl29028_set_als_persist(struct i2c_client *client, bool is_enable, int persist) { int prox_perstant[] = {1, 4, 8, 16}; int i; int sel; bool st; if (is_enable) { for (i = 0; i < ARRAY_SIZE(prox_perstant) - 1; ++i) { if ((prox_perstant[i] <= persist) && persist < prox_perstant[i+1]) break; } sel = i; } if (is_enable) { dev_dbg(&client->dev, "Enabling als threshold interrupt\n"); st = isl29028_write_data(client, ISL29028_REG_ADD_INTERRUPT, sel, INTERRUPT_ALS_PERSIST_MASK, INTERRUPT_ALS_PERSIST_SH); if (st) st = isl29028_write_data(client, ISL29028_REG_ADD_INTERRUPT, INTERRUPT_ALS_FLAG_EN, INTERRUPT_ALS_FLAG_MASK, INTERRUPT_ALS_FLAG_SH); } else { st = isl29028_write_data(client, ISL29028_REG_ADD_INTERRUPT, INTERRUPT_ALS_FLAG_DIS, INTERRUPT_ALS_FLAG_MASK, INTERRUPT_ALS_FLAG_SH); } return st; }
static bool isl29028_set_proxim_period(struct i2c_client *client, bool is_enable, int period) { int prox_period[] = {0, 12, 50, 75, 100, 200, 400, 800}; int i; int sel; bool st; if (period < 12) sel = 7; else { for (i = 1; i < ARRAY_SIZE(prox_period) - 1; ++i) { if ((prox_period[i] <= period) && period < prox_period[i + 1]) break; } sel = 7 - i; } if (!is_enable) { dev_dbg(&client->dev, "Disabling proximity sensing\n"); st = isl29028_write_data(client, ISL29028_REG_ADD_CONFIGURE, 0, CONFIGURE_PROX_EN_MASK, CONFIGURE_PROX_EN_SH); } else { dev_dbg(&client->dev, "Enabling proximity sensing with period " "of %d ms sel %d period %d\n", prox_period[7 - sel], sel, period); st = isl29028_write_data(client, ISL29028_REG_ADD_CONFIGURE, sel, CONFIGURE_PROX_SLP_MASK, CONFIGURE_PROX_SLP_SH); if (st) st = isl29028_write_data(client, ISL29028_REG_ADD_CONFIGURE, 1, CONFIGURE_PROX_EN_MASK, CONFIGURE_PROX_EN_SH); } return st; }
static irqreturn_t threshold_isr(int irq, void *irq_data) { struct isl29028_chip *chip = (struct isl29028_chip *)irq_data; s32 int_reg; struct i2c_client *client = chip->client; int_reg = i2c_smbus_read_byte_data(client, ISL29028_REG_ADD_INTERRUPT); if (int_reg < 0) { dev_err(&client->dev, "Error in reading register %d, error %d\n", ISL29028_REG_ADD_INTERRUPT, int_reg); return IRQ_HANDLED; } if (int_reg & INTERRUPT_PROX_FLAG_MASK) { /* Write 0 to clear */ isl29028_write_data(client, ISL29028_REG_ADD_INTERRUPT, INTERRUPT_PROX_FLAG_DIS, INTERRUPT_PROX_FLAG_MASK, INTERRUPT_PROX_FLAG_SH); if (chip->is_proxim_int_waiting) complete(&chip->prox_completion); } if (int_reg & INTERRUPT_ALS_FLAG_MASK) { /* Write 0 to clear */ isl29028_write_data(client, ISL29028_REG_ADD_INTERRUPT, INTERRUPT_ALS_FLAG_DIS, INTERRUPT_ALS_FLAG_MASK, INTERRUPT_ALS_FLAG_SH); if (chip->is_als_int_waiting) complete(&chip->als_completion); } return IRQ_HANDLED; }
static bool isl29028_set_als_ir_mode(struct i2c_client *client, bool is_enable, bool is_als) { struct iio_dev *indio_dev = i2c_get_clientdata(client); struct isl29028_chip *chip = iio_priv(indio_dev); bool st; if (is_enable) { if (is_als) { dev_dbg(&client->dev, "Enabling ALS mode\n"); st = isl29028_write_data(client, ISL29028_REG_ADD_CONFIGURE, CONFIGURE_ALS_IR_MODE_ALS, CONFIGURE_ALS_IR_MODE_MASK, CONFIGURE_ALS_IR_MODE_SH); if (st) st = isl29028_write_data(client, ISL29028_REG_ADD_CONFIGURE, CONFIGURE_ALS_RANGE_HIGH_LUX, CONFIGURE_ALS_RANGE_MASK, CONFIGURE_ALS_RANGE_SH); if (st) st = isl29028_set_irals_high_threshold(client, chip->als_high_thres); if (st) st = isl29028_set_irals_low_threshold(client, chip->als_low_thres); } else { dev_dbg(&client->dev, "Enabling IR mode\n"); st = isl29028_write_data(client, ISL29028_REG_ADD_CONFIGURE, CONFIGURE_ALS_IR_MODE_IR, CONFIGURE_ALS_IR_MODE_MASK, CONFIGURE_ALS_IR_MODE_SH); if (st) st = isl29028_set_irals_high_threshold(client, chip->ir_high_thres); if (st) st = isl29028_set_irals_low_threshold(client, chip->ir_low_thres); } if (st) st = isl29028_write_data(client, ISL29028_REG_ADD_CONFIGURE, CONFIGURE_ALS_EN, CONFIGURE_ALS_EN_MASK, CONFIGURE_ALS_EN_SH); } else { st = isl29028_write_data(client, ISL29028_REG_ADD_CONFIGURE, CONFIGURE_ALS_DIS, CONFIGURE_ALS_EN_MASK, CONFIGURE_ALS_EN_SH); } return st; }
static int isl29028_chip_init(struct i2c_client *client) { struct iio_dev *indio_dev = i2c_get_clientdata(client); struct isl29028_chip *chip = iio_priv(indio_dev); int i; bool st; for (i = 0; i < ARRAY_SIZE(chip->reg_cache); i++) chip->reg_cache[i] = 0; chip->is_prox_enable = 0; chip->prox_low_thres = 0; chip->prox_high_thres = 0xFF; chip->prox_period = ISL29028_PROX_PERIOD; chip->prox_reading = 0; chip->als_low_thres = 0; chip->als_high_thres = 0xFFF; chip->als_range = 1; chip->als_reading = 0; chip->als_ir_mode = 0; chip->ir_high_thres = 0xFFF; chip->ir_low_thres = 0; chip->ir_reading = 0; chip->is_int_enable = false; chip->prox_persist = 1; chip->als_persist = 1; chip->is_proxim_int_waiting = false; chip->is_als_int_waiting = false; chip->shutdown_complete = 0; /* if regulator is not available, then proceed with i2c write or * if regulator is turned on then proceed with i2c write */ if (chip->isl_reg && !regulator_is_enabled(chip->isl_reg)) return 0; st = isl29028_write_data(client, ISL29028_REG_ADD_TEST1_MODE, 0x0, 0xFF, 0); if (st) st = isl29028_write_data(client, ISL29028_REG_ADD_TEST2_MODE, 0x0, 0xFF, 0); if (st) st = isl29028_write_data(client, ISL29028_REG_ADD_CONFIGURE, 0x0, 0xFF, 0); if (st) msleep(1); if (!st) { dev_err(&client->dev, "%s(): fails\n", __func__); return -ENODEV; } return 0; }
static int isl29028_chip_init(struct i2c_client *client) { struct isl29028_chip *chip = i2c_get_clientdata(client); int i; bool st; for (i = 0; i < ARRAY_SIZE(chip->reg_cache); i++) chip->reg_cache[i] = 0; chip->is_prox_enable = 0; chip->prox_low_thres = 0; chip->prox_high_thres = 0xFF; chip->prox_period = 0; chip->prox_reading = 0; chip->als_low_thres = 0; chip->als_high_thres = 0xFFF; chip->als_range = 1; chip->als_reading = 0; chip->als_ir_mode = 0; chip->ir_high_thres = 0xFFF; chip->ir_low_thres = 0; chip->ir_reading = 0; chip->is_int_enable = false; chip->prox_persist = 1; chip->als_persist = 1; chip->is_proxim_int_waiting = false; chip->is_als_int_waiting = false; st = isl29028_write_data(client, ISL29028_REG_ADD_TEST1_MODE, 0x0, 0xFF, 0); if (st) st = isl29028_write_data(client, ISL29028_REG_ADD_TEST2_MODE, 0x0, 0xFF, 0); if (st) st = isl29028_write_data(client, ISL29028_REG_ADD_CONFIGURE, 0x0, 0xFF, 0); if (st) msleep(1); if (!st) { dev_err(&client->dev, "%s(): fails\n", __func__); return -ENODEV; } return 0; }
static bool isl29028_set_irals_low_threshold(struct i2c_client *client, u32 als) { bool st; st = isl29028_write_data(client, ISL29028_REG_ADD_ALSIR_LH_THRES, (als >> 8) & 0xF, 0xF << ISL29028_REG_ADD_ALSIR_LH_THRES_L_SH, ISL29028_REG_ADD_ALSIR_LH_THRES_L_SH); if (st) st = isl29028_write_data(client, ISL29028_REG_ADD_ALSIR_LOW_THRES, als & 0xFF, 0xFF, 0); return st; }
static int isl29028_suspend(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct iio_dev *indio_dev = i2c_get_clientdata(client); struct isl29028_chip *chip = iio_priv(indio_dev); dev_dbg(&client->dev, "%s()\n", __func__); mutex_lock(&chip->lock); /* if regulator is available and regulator is enabled by isl29028 * then disable it */ if (chip->isl_reg && (chip->is_prox_enable || chip->als_ir_mode)) regulator_disable(chip->isl_reg); /* if regulator is still enabled, put the device into shutdown */ if (chip->isl_reg && regulator_is_enabled(chip->isl_reg)) isl29028_write_data(client, ISL29028_REG_ADD_CONFIGURE, 0x0, 0xFF, 0); mutex_unlock(&chip->lock); return 0; }
static bool isl29028_set_proxim_low_threshold(struct i2c_client *client, u8 th) { return isl29028_write_data(client, ISL29028_REG_ADD_PROX_LOW_THRES, th, 0xFF, 0); }