16d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan/* 26d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan * IIO driver for the light sensor ISL29028. 36d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan * ISL29028 is Concurrent Ambient Light and Proximity Sensor 46d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan * 56d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. 66d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan * 76d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan * This program is free software; you can redistribute it and/or modify it 86d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan * under the terms and conditions of the GNU General Public License, 96d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan * version 2, as published by the Free Software Foundation. 106d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan * 116d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan * This program is distributed in the hope it will be useful, but WITHOUT 126d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 136d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 146d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan * more details. 156d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan * 166d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan * You should have received a copy of the GNU General Public License 176d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan * along with this program. If not, see <http://www.gnu.org/licenses/>. 186d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan */ 196d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 206d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan#include <linux/module.h> 216d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan#include <linux/i2c.h> 226d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan#include <linux/err.h> 236d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan#include <linux/mutex.h> 246d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan#include <linux/delay.h> 256d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan#include <linux/slab.h> 266d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan#include <linux/regmap.h> 2706458e277eac2b8761b0a04d3c808d57be281a2eJonathan Cameron#include <linux/iio/iio.h> 2806458e277eac2b8761b0a04d3c808d57be281a2eJonathan Cameron#include <linux/iio/sysfs.h> 296d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 306d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan#define CONVERSION_TIME_MS 100 316d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 326d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan#define ISL29028_REG_CONFIGURE 0x01 336d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 346d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan#define CONFIGURE_ALS_IR_MODE_ALS 0 356d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan#define CONFIGURE_ALS_IR_MODE_IR BIT(0) 366d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan#define CONFIGURE_ALS_IR_MODE_MASK BIT(0) 376d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 386d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan#define CONFIGURE_ALS_RANGE_LOW_LUX 0 396d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan#define CONFIGURE_ALS_RANGE_HIGH_LUX BIT(1) 406d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan#define CONFIGURE_ALS_RANGE_MASK BIT(1) 416d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 426d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan#define CONFIGURE_ALS_DIS 0 436d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan#define CONFIGURE_ALS_EN BIT(2) 446d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan#define CONFIGURE_ALS_EN_MASK BIT(2) 456d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 466d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan#define CONFIGURE_PROX_DRIVE BIT(3) 476d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 486d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan#define CONFIGURE_PROX_SLP_SH 4 496d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan#define CONFIGURE_PROX_SLP_MASK (7 << CONFIGURE_PROX_SLP_SH) 506d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 516d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan#define CONFIGURE_PROX_EN BIT(7) 526d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan#define CONFIGURE_PROX_EN_MASK BIT(7) 536d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 546d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan#define ISL29028_REG_INTERRUPT 0x02 556d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 566d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan#define ISL29028_REG_PROX_DATA 0x08 576d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan#define ISL29028_REG_ALSIR_L 0x09 586d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan#define ISL29028_REG_ALSIR_U 0x0A 596d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 606d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan#define ISL29028_REG_TEST1_MODE 0x0E 616d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan#define ISL29028_REG_TEST2_MODE 0x0F 626d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 636d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan#define ISL29028_NUM_REGS (ISL29028_REG_TEST2_MODE + 1) 646d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 656d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewanganenum als_ir_mode { 666d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan MODE_NONE = 0, 676d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan MODE_ALS, 686d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan MODE_IR 696d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan}; 706d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 716d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewanganstruct isl29028_chip { 726d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan struct device *dev; 736d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan struct mutex lock; 746d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan struct regmap *regmap; 756d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 766d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan unsigned int prox_sampling; 776d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan bool enable_prox; 786d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 796d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan int lux_scale; 806d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan int als_ir_mode; 816d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan}; 826d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 836d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewanganstatic int isl29028_set_proxim_sampling(struct isl29028_chip *chip, 846d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan unsigned int sampling) 856d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan{ 866d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan static unsigned int prox_period[] = {800, 400, 200, 100, 75, 50, 12, 0}; 876d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan int sel; 886d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan unsigned int period = DIV_ROUND_UP(1000, sampling); 896d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 906d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan for (sel = 0; sel < ARRAY_SIZE(prox_period); ++sel) { 916d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan if (period >= prox_period[sel]) 926d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan break; 936d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan } 946d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan return regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE, 956d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan CONFIGURE_PROX_SLP_MASK, sel << CONFIGURE_PROX_SLP_SH); 966d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan} 976d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 986d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewanganstatic int isl29028_enable_proximity(struct isl29028_chip *chip, bool enable) 996d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan{ 1006d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan int ret; 1016d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan int val = 0; 1026d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 1036d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan if (enable) 1046d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan val = CONFIGURE_PROX_EN; 1056d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE, 1066d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan CONFIGURE_PROX_EN_MASK, val); 1076d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan if (ret < 0) 1086d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan return ret; 1096d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 1106d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan /* Wait for conversion to be complete for first sample */ 1116d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan mdelay(DIV_ROUND_UP(1000, chip->prox_sampling)); 1126d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan return 0; 1136d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan} 1146d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 1156d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewanganstatic int isl29028_set_als_scale(struct isl29028_chip *chip, int lux_scale) 1166d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan{ 1176d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan int val = (lux_scale == 2000) ? CONFIGURE_ALS_RANGE_HIGH_LUX : 1186d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan CONFIGURE_ALS_RANGE_LOW_LUX; 1196d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 1206d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan return regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE, 1216d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan CONFIGURE_ALS_RANGE_MASK, val); 1226d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan} 1236d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 1246d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewanganstatic int isl29028_set_als_ir_mode(struct isl29028_chip *chip, 1256d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan enum als_ir_mode mode) 1266d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan{ 1276d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan int ret = 0; 1286d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 1296d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan switch (mode) { 1306d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan case MODE_ALS: 1316d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE, 1326d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan CONFIGURE_ALS_IR_MODE_MASK, CONFIGURE_ALS_IR_MODE_ALS); 1336d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan if (ret < 0) 1346d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan return ret; 1356d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 1366d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE, 1376d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan CONFIGURE_ALS_RANGE_MASK, CONFIGURE_ALS_RANGE_HIGH_LUX); 1386d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan break; 1396d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 1406d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan case MODE_IR: 1416d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE, 1426d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan CONFIGURE_ALS_IR_MODE_MASK, CONFIGURE_ALS_IR_MODE_IR); 1436d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan break; 1446d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 1456d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan case MODE_NONE: 1466d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan return regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE, 1476d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan CONFIGURE_ALS_EN_MASK, CONFIGURE_ALS_DIS); 1486d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan } 1496d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 1506d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan if (ret < 0) 1516d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan return ret; 1526d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 1536d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan /* Enable the ALS/IR */ 1546d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE, 1556d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan CONFIGURE_ALS_EN_MASK, CONFIGURE_ALS_EN); 1566d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan if (ret < 0) 1576d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan return ret; 1586d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 1596d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan /* Need to wait for conversion time if ALS/IR mode enabled */ 1606d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan mdelay(CONVERSION_TIME_MS); 1616d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan return 0; 1626d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan} 1636d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 1646d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewanganstatic int isl29028_read_als_ir(struct isl29028_chip *chip, int *als_ir) 1656d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan{ 1666d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan unsigned int lsb; 1676d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan unsigned int msb; 1686d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan int ret; 1696d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 1706d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan ret = regmap_read(chip->regmap, ISL29028_REG_ALSIR_L, &lsb); 1716d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan if (ret < 0) { 1726d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan dev_err(chip->dev, 1736d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan "Error in reading register ALSIR_L err %d\n", ret); 1746d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan return ret; 1756d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan } 1766d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 1776d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan ret = regmap_read(chip->regmap, ISL29028_REG_ALSIR_U, &msb); 1786d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan if (ret < 0) { 1796d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan dev_err(chip->dev, 1806d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan "Error in reading register ALSIR_U err %d\n", ret); 1816d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan return ret; 1826d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan } 1836d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 1846d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan *als_ir = ((msb & 0xF) << 8) | (lsb & 0xFF); 1856d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan return 0; 1866d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan} 1876d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 1886d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewanganstatic int isl29028_read_proxim(struct isl29028_chip *chip, int *prox) 1896d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan{ 1906d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan unsigned int data; 1916d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan int ret; 1926d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 1936d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan ret = regmap_read(chip->regmap, ISL29028_REG_PROX_DATA, &data); 1946d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan if (ret < 0) { 1956d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan dev_err(chip->dev, "Error in reading register %d, error %d\n", 1966d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan ISL29028_REG_PROX_DATA, ret); 1976d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan return ret; 1986d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan } 1996d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan *prox = data; 2006d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan return 0; 2016d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan} 2026d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 2036d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewanganstatic int isl29028_proxim_get(struct isl29028_chip *chip, int *prox_data) 2046d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan{ 2056d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan int ret; 2066d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 2076d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan if (!chip->enable_prox) { 2086d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan ret = isl29028_enable_proximity(chip, true); 2096d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan if (ret < 0) 2106d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan return ret; 2116d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan chip->enable_prox = true; 2126d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan } 2136d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan return isl29028_read_proxim(chip, prox_data); 2146d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan} 2156d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 2166d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewanganstatic int isl29028_als_get(struct isl29028_chip *chip, int *als_data) 2176d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan{ 2186d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan int ret; 2196d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan int als_ir_data; 2206d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 2216d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan if (chip->als_ir_mode != MODE_ALS) { 2226d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan ret = isl29028_set_als_ir_mode(chip, MODE_ALS); 2236d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan if (ret < 0) { 2246d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan dev_err(chip->dev, 2256d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan "Error in enabling ALS mode err %d\n", ret); 2266d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan return ret; 2276d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan } 2286d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan chip->als_ir_mode = MODE_ALS; 2296d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan } 2306d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 2316d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan ret = isl29028_read_als_ir(chip, &als_ir_data); 2326d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan if (ret < 0) 2336d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan return ret; 2346d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 2356d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan /* 2366d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan * convert als data count to lux. 2376d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan * if lux_scale = 125, lux = count * 0.031 2386d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan * if lux_scale = 2000, lux = count * 0.49 2396d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan */ 2406d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan if (chip->lux_scale == 125) 2416d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan als_ir_data = (als_ir_data * 31) / 1000; 2426d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan else 2436d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan als_ir_data = (als_ir_data * 49) / 100; 2446d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 2456d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan *als_data = als_ir_data; 2466d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan return 0; 2476d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan} 2486d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 2496d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewanganstatic int isl29028_ir_get(struct isl29028_chip *chip, int *ir_data) 2506d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan{ 2516d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan int ret; 2526d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 2536d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan if (chip->als_ir_mode != MODE_IR) { 2546d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan ret = isl29028_set_als_ir_mode(chip, MODE_IR); 2556d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan if (ret < 0) { 2566d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan dev_err(chip->dev, 2576d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan "Error in enabling IR mode err %d\n", ret); 2586d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan return ret; 2596d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan } 2606d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan chip->als_ir_mode = MODE_IR; 2616d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan } 2626d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan return isl29028_read_als_ir(chip, ir_data); 2636d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan} 2646d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 2656d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan/* Channel IO */ 2666d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewanganstatic int isl29028_write_raw(struct iio_dev *indio_dev, 2676d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan struct iio_chan_spec const *chan, int val, int val2, long mask) 2686d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan{ 2696d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan struct isl29028_chip *chip = iio_priv(indio_dev); 2706d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan int ret = -EINVAL; 2716d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 2726d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan mutex_lock(&chip->lock); 2736d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan switch (chan->type) { 2746d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan case IIO_PROXIMITY: 275892cb6dc9fbbfa7281f3aa53aa6599618aec7cb1Laxman Dewangan if (mask != IIO_CHAN_INFO_SAMP_FREQ) { 2766d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan dev_err(chip->dev, 2776d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan "proximity: mask value 0x%08lx not supported\n", 2786d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan mask); 2796d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan break; 2806d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan } 2816d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan if (val < 1 || val > 100) { 2826d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan dev_err(chip->dev, 2836d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan "Samp_freq %d is not in range[1:100]\n", val); 2846d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan break; 2856d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan } 2866d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan ret = isl29028_set_proxim_sampling(chip, val); 2876d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan if (ret < 0) { 2886d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan dev_err(chip->dev, 2896d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan "Setting proximity samp_freq fail, err %d\n", 2906d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan ret); 2916d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan break; 2926d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan } 2936d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan chip->prox_sampling = val; 2946d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan break; 2956d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 2966d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan case IIO_LIGHT: 297892cb6dc9fbbfa7281f3aa53aa6599618aec7cb1Laxman Dewangan if (mask != IIO_CHAN_INFO_SCALE) { 2986d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan dev_err(chip->dev, 2996d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan "light: mask value 0x%08lx not supported\n", 3006d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan mask); 3016d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan break; 3026d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan } 3036d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan if ((val != 125) && (val != 2000)) { 3046d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan dev_err(chip->dev, 3056d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan "lux scale %d is invalid [125, 2000]\n", val); 3066d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan break; 3076d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan } 3086d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan ret = isl29028_set_als_scale(chip, val); 3096d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan if (ret < 0) { 3106d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan dev_err(chip->dev, 3116d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan "Setting lux scale fail with error %d\n", ret); 3126d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan break; 3136d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan } 3146d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan chip->lux_scale = val; 3156d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan break; 3166d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 3176d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan default: 3186d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan dev_err(chip->dev, "Unsupported channel type\n"); 3196d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan break; 3206d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan } 3216d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan mutex_unlock(&chip->lock); 3226d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan return ret; 3236d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan} 3246d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 3256d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewanganstatic int isl29028_read_raw(struct iio_dev *indio_dev, 3266d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan struct iio_chan_spec const *chan, int *val, int *val2, long mask) 3276d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan{ 3286d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan struct isl29028_chip *chip = iio_priv(indio_dev); 3296d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan int ret = -EINVAL; 3306d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 3316d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan mutex_lock(&chip->lock); 3326d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan switch (mask) { 333a8c0ed756574ba5a484cd8238892f88501ff400dJonathan Cameron case IIO_CHAN_INFO_RAW: 334a8c0ed756574ba5a484cd8238892f88501ff400dJonathan Cameron case IIO_CHAN_INFO_PROCESSED: 3356d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan switch (chan->type) { 3366d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan case IIO_LIGHT: 3376d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan ret = isl29028_als_get(chip, val); 3386d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan break; 3396d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan case IIO_INTENSITY: 3406d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan ret = isl29028_ir_get(chip, val); 3416d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan break; 3426d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan case IIO_PROXIMITY: 3436d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan ret = isl29028_proxim_get(chip, val); 3446d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan break; 3456d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan default: 3466d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan break; 3476d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan } 3486d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan if (ret < 0) 3496d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan break; 3506d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan ret = IIO_VAL_INT; 3516d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan break; 3526d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 353892cb6dc9fbbfa7281f3aa53aa6599618aec7cb1Laxman Dewangan case IIO_CHAN_INFO_SAMP_FREQ: 3546d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan if (chan->type != IIO_PROXIMITY) 3556d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan break; 3566d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan *val = chip->prox_sampling; 3576d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan ret = IIO_VAL_INT; 3586d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan break; 3596d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 360892cb6dc9fbbfa7281f3aa53aa6599618aec7cb1Laxman Dewangan case IIO_CHAN_INFO_SCALE: 3616d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan if (chan->type != IIO_LIGHT) 3626d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan break; 3636d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan *val = chip->lux_scale; 3646d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan ret = IIO_VAL_INT; 3656d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan break; 3666d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 3676d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan default: 3686d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan dev_err(chip->dev, "mask value 0x%08lx not supported\n", mask); 3696d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan break; 3706d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan } 3716d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan mutex_unlock(&chip->lock); 3726d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan return ret; 3736d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan} 3746d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 3756d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewanganstatic IIO_CONST_ATTR(in_proximity_sampling_frequency_available, 3766d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan "1, 3, 5, 10, 13, 20, 83, 100"); 3776d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewanganstatic IIO_CONST_ATTR(in_illuminance_scale_available, "125, 2000"); 3786d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 3796d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan#define ISL29028_DEV_ATTR(name) (&iio_dev_attr_##name.dev_attr.attr) 3806d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan#define ISL29028_CONST_ATTR(name) (&iio_const_attr_##name.dev_attr.attr) 3816d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewanganstatic struct attribute *isl29028_attributes[] = { 3826d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan ISL29028_CONST_ATTR(in_proximity_sampling_frequency_available), 3836d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan ISL29028_CONST_ATTR(in_illuminance_scale_available), 3846d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan NULL, 3856d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan}; 3866d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 3876d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewanganstatic const struct attribute_group isl29108_group = { 3886d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan .attrs = isl29028_attributes, 3896d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan}; 3906d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 3916d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewanganstatic const struct iio_chan_spec isl29028_channels[] = { 3926d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan { 3936d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan .type = IIO_LIGHT, 39493a9fdff2106f34747ec934812c89fa8b28b419fJonathan Cameron .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | 39593a9fdff2106f34747ec934812c89fa8b28b419fJonathan Cameron BIT(IIO_CHAN_INFO_SCALE), 3966d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan }, { 3976d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan .type = IIO_INTENSITY, 39893a9fdff2106f34747ec934812c89fa8b28b419fJonathan Cameron .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 3996d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan }, { 4006d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan .type = IIO_PROXIMITY, 40193a9fdff2106f34747ec934812c89fa8b28b419fJonathan Cameron .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 40293a9fdff2106f34747ec934812c89fa8b28b419fJonathan Cameron BIT(IIO_CHAN_INFO_SAMP_FREQ), 4036d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan } 4046d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan}; 4056d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 4066d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewanganstatic const struct iio_info isl29028_info = { 4076d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan .attrs = &isl29108_group, 4086d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan .driver_module = THIS_MODULE, 4096d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan .read_raw = &isl29028_read_raw, 4106d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan .write_raw = &isl29028_write_raw, 4116d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan}; 4126d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 4136d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewanganstatic int isl29028_chip_init(struct isl29028_chip *chip) 4146d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan{ 4156d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan int ret; 4166d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 4176d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan chip->enable_prox = false; 4186d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan chip->prox_sampling = 20; 4196d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan chip->lux_scale = 2000; 4206d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan chip->als_ir_mode = MODE_NONE; 4216d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 4226d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan ret = regmap_write(chip->regmap, ISL29028_REG_TEST1_MODE, 0x0); 4236d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan if (ret < 0) { 4246d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan dev_err(chip->dev, "%s(): write to reg %d failed, err = %d\n", 4256d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan __func__, ISL29028_REG_TEST1_MODE, ret); 4266d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan return ret; 4276d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan } 4286d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan ret = regmap_write(chip->regmap, ISL29028_REG_TEST2_MODE, 0x0); 4296d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan if (ret < 0) { 4306d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan dev_err(chip->dev, "%s(): write to reg %d failed, err = %d\n", 4316d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan __func__, ISL29028_REG_TEST2_MODE, ret); 4326d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan return ret; 4336d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan } 4346d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 4356d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan ret = regmap_write(chip->regmap, ISL29028_REG_CONFIGURE, 0x0); 4366d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan if (ret < 0) { 4376d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan dev_err(chip->dev, "%s(): write to reg %d failed, err = %d\n", 4386d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan __func__, ISL29028_REG_CONFIGURE, ret); 4396d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan return ret; 4406d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan } 4416d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 4426d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan ret = isl29028_set_proxim_sampling(chip, chip->prox_sampling); 4436d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan if (ret < 0) { 4446d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan dev_err(chip->dev, "%s(): setting the proximity, err = %d\n", 4456d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan __func__, ret); 4466d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan return ret; 4476d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan } 4486d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 4496d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan ret = isl29028_set_als_scale(chip, chip->lux_scale); 4506d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan if (ret < 0) 4516d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan dev_err(chip->dev, "%s(): setting als scale failed, err = %d\n", 4526d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan __func__, ret); 4536d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan return ret; 4546d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan} 4556d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 4566d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewanganstatic bool is_volatile_reg(struct device *dev, unsigned int reg) 4576d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan{ 4586d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan switch (reg) { 4596d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan case ISL29028_REG_INTERRUPT: 4606d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan case ISL29028_REG_PROX_DATA: 4616d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan case ISL29028_REG_ALSIR_L: 4626d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan case ISL29028_REG_ALSIR_U: 4636d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan return true; 4646d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan default: 4656d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan return false; 4666d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan } 4676d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan} 4686d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 4696d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewanganstatic const struct regmap_config isl29028_regmap_config = { 4706d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan .reg_bits = 8, 4716d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan .val_bits = 8, 4726d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan .volatile_reg = is_volatile_reg, 4736d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan .max_register = ISL29028_NUM_REGS - 1, 4746d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan .num_reg_defaults_raw = ISL29028_NUM_REGS, 4756d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan .cache_type = REGCACHE_RBTREE, 4766d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan}; 4776d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 4784ae1c61ff2ba4fea4e4c1a045cb1f34520608789Bill Pembertonstatic int isl29028_probe(struct i2c_client *client, 4796d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan const struct i2c_device_id *id) 4806d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan{ 4816d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan struct isl29028_chip *chip; 4826d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan struct iio_dev *indio_dev; 4836d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan int ret; 4846d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 48580cab1da704e3f27fb4a631f95369fc31323e91cSachin Kamat indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip)); 4866d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan if (!indio_dev) { 4876d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan dev_err(&client->dev, "iio allocation fails\n"); 4886d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan return -ENOMEM; 4896d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan } 4906d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 4916d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan chip = iio_priv(indio_dev); 4926d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 4936d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan i2c_set_clientdata(client, indio_dev); 4946d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan chip->dev = &client->dev; 4956d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan mutex_init(&chip->lock); 4966d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 4976d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan chip->regmap = devm_regmap_init_i2c(client, &isl29028_regmap_config); 4986d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan if (IS_ERR(chip->regmap)) { 4996d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan ret = PTR_ERR(chip->regmap); 5006d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan dev_err(chip->dev, "regmap initialization failed: %d\n", ret); 50180cab1da704e3f27fb4a631f95369fc31323e91cSachin Kamat return ret; 5026d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan } 5036d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 5046d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan ret = isl29028_chip_init(chip); 5056d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan if (ret < 0) { 5066d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan dev_err(chip->dev, "chip initialization failed: %d\n", ret); 50780cab1da704e3f27fb4a631f95369fc31323e91cSachin Kamat return ret; 5086d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan } 5096d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 5106d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan indio_dev->info = &isl29028_info; 5116d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan indio_dev->channels = isl29028_channels; 5126d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan indio_dev->num_channels = ARRAY_SIZE(isl29028_channels); 5136d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan indio_dev->name = id->name; 5146d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan indio_dev->dev.parent = &client->dev; 5156d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan indio_dev->modes = INDIO_DIRECT_MODE; 5166d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan ret = iio_device_register(indio_dev); 5176d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan if (ret < 0) { 5186d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan dev_err(chip->dev, "iio registration fails with error %d\n", 5196d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan ret); 52080cab1da704e3f27fb4a631f95369fc31323e91cSachin Kamat return ret; 5216d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan } 5226d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan return 0; 5236d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan} 5246d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 525447d4f29ee3fa62f13c65688bb7b74d5a9a0d767Bill Pembertonstatic int isl29028_remove(struct i2c_client *client) 5266d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan{ 5276d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan struct iio_dev *indio_dev = i2c_get_clientdata(client); 5286d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 5296d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan iio_device_unregister(indio_dev); 5306d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan return 0; 5316d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan} 5326d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 5336d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewanganstatic const struct i2c_device_id isl29028_id[] = { 5346d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan {"isl29028", 0}, 5356d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan {} 5366d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan}; 5376d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman DewanganMODULE_DEVICE_TABLE(i2c, isl29028_id); 5386d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 5396d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewanganstatic const struct of_device_id isl29028_of_match[] = { 540610202ddc6951453034475fdcf5c9caf14f050deLaxman Dewangan { .compatible = "isil,isl29028", }, 5416d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan { }, 5426d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan}; 5436d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman DewanganMODULE_DEVICE_TABLE(of, isl29028_of_match); 5446d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 5456d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewanganstatic struct i2c_driver isl29028_driver = { 5466d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan .class = I2C_CLASS_HWMON, 5476d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan .driver = { 5486d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan .name = "isl29028", 5496d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan .owner = THIS_MODULE, 5506d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan .of_match_table = isl29028_of_match, 5516d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan }, 5526d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan .probe = isl29028_probe, 553e543acf07db78cfc135e45c4ce0ed26ccf774c37Bill Pemberton .remove = isl29028_remove, 5546d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan .id_table = isl29028_id, 5556d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan}; 5566d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 5576d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewanganmodule_i2c_driver(isl29028_driver); 5586d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman Dewangan 5596d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman DewanganMODULE_DESCRIPTION("ISL29028 Ambient Light and Proximity Sensor driver"); 5606d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman DewanganMODULE_LICENSE("GPL v2"); 5616d59ba2f9676210b4631e9c447ab1c9faf0a9577Laxman DewanganMODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>"); 562