1e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo/*
2e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo * Copyright (C) 2013 Samsung Electronics Co., Ltd.
3e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo * Author: Beomho Seo <beomho.seo@samsung.com>
4e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo *
5e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo * This program is free software; you can redistribute  it and/or modify it
6e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo * under  the terms of  the GNU General Public License version 2, as published
7e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo * by the Free Software Foundation.
8e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo */
9e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
10e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#include <linux/delay.h>
11e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#include <linux/err.h>
12e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#include <linux/i2c.h>
13e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#include <linux/mutex.h>
14e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#include <linux/module.h>
15e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#include <linux/interrupt.h>
16e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#include <linux/regulator/consumer.h>
17e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#include <linux/iio/iio.h>
18e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#include <linux/iio/sysfs.h>
19e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#include <linux/iio/events.h>
20e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
21e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo/* Slave address 0x19 for PS of 7 bit addressing protocol for I2C */
22e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_I2C_ADDR_PS		0x19
23e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo/* Alert Response Address */
24e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_ARA			0x0C
25e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
26e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo/* Ambient light sensor */
27e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_CS_CONF1		0x00
28e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_CS_CONF2		0x01
29e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_ALS_WH_M		0x02
30e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_ALS_WH_L		0x03
31e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_ALS_WL_M		0x04
32e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_ALS_WL_L		0x05
33e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_CS_CONF3		0x06
34e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_CS_CONF_REG_NUM		0x02
35e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
36e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo/* Proximity sensor */
37e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_PS_CONF1		0x00
38e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_PS_THD			0x01
39e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_PS_CANC			0x02
40e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_PS_CONF2		0x03
41e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_PS_REG_NUM		0x04
42e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
43e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo/* CS_CONF1 command code */
44e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_ALS_ENABLE		0x00
45e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_ALS_DISABLE		0x01
46e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_ALS_INT_EN		0x02
47e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_ALS_THRES		0x04
48e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
49e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo/* CS_CONF2 command code */
50e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_CS_CONF2_DEFAULT_BIT	0x08
51e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
52e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo/* CS_CONF3 channel integration time */
5326c17a1c56f957560cb96d219c13d21dfb605819Beomho Seo#define CM36651_CS_IT1			0x00 /* Integration time 80 msec */
5426c17a1c56f957560cb96d219c13d21dfb605819Beomho Seo#define CM36651_CS_IT2			0x40 /* Integration time 160 msec */
5526c17a1c56f957560cb96d219c13d21dfb605819Beomho Seo#define CM36651_CS_IT3			0x80 /* Integration time 320 msec */
5626c17a1c56f957560cb96d219c13d21dfb605819Beomho Seo#define CM36651_CS_IT4			0xC0 /* Integration time 640 msec */
57e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
58e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo/* PS_CONF1 command code */
59e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_PS_ENABLE		0x00
60e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_PS_DISABLE		0x01
61e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_PS_INT_EN		0x02
62e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_PS_PERS2		0x04
63e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_PS_PERS3		0x08
64e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_PS_PERS4		0x0C
65e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
66e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo/* PS_CONF1 command code: integration time */
6726c17a1c56f957560cb96d219c13d21dfb605819Beomho Seo#define CM36651_PS_IT1			0x00 /* Integration time 0.32 msec */
6826c17a1c56f957560cb96d219c13d21dfb605819Beomho Seo#define CM36651_PS_IT2			0x10 /* Integration time 0.42 msec */
6926c17a1c56f957560cb96d219c13d21dfb605819Beomho Seo#define CM36651_PS_IT3			0x20 /* Integration time 0.52 msec */
7026c17a1c56f957560cb96d219c13d21dfb605819Beomho Seo#define CM36651_PS_IT4			0x30 /* Integration time 0.64 msec */
71e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
72e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo/* PS_CONF1 command code: duty ratio */
73e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_PS_DR1			0x00 /* Duty ratio 1/80 */
74e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_PS_DR2			0x40 /* Duty ratio 1/160 */
75e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_PS_DR3			0x80 /* Duty ratio 1/320 */
76e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_PS_DR4			0xC0 /* Duty ratio 1/640 */
77e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
78e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo/* PS_THD command code */
79e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_PS_INITIAL_THD		0x05
80e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
81e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo/* PS_CANC command code */
82e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_PS_CANC_DEFAULT		0x00
83e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
84e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo/* PS_CONF2 command code */
85e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_PS_HYS1			0x00
86e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_PS_HYS2			0x01
87e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_PS_SMART_PERS_EN	0x02
88e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_PS_DIR_INT		0x04
89e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_PS_MS			0x10
90e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
91e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_CS_COLOR_NUM		4
92e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
93e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_CLOSE_PROXIMITY		0x32
94e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_FAR_PROXIMITY			0x33
95e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
9626c17a1c56f957560cb96d219c13d21dfb605819Beomho Seo#define CM36651_CS_INT_TIME_AVAIL	"0.08 0.16 0.32 0.64"
9726c17a1c56f957560cb96d219c13d21dfb605819Beomho Seo#define CM36651_PS_INT_TIME_AVAIL	"0.000320 0.000420 0.000520 0.000640"
98e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
99e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seoenum cm36651_operation_mode {
100e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	CM36651_LIGHT_EN,
101e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	CM36651_PROXIMITY_EN,
102e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	CM36651_PROXIMITY_EV_EN,
103e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo};
104e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
105e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seoenum cm36651_light_channel_idx {
106e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	CM36651_LIGHT_CHANNEL_IDX_RED,
107e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	CM36651_LIGHT_CHANNEL_IDX_GREEN,
108e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	CM36651_LIGHT_CHANNEL_IDX_BLUE,
109e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	CM36651_LIGHT_CHANNEL_IDX_CLEAR,
110e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo};
111e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
112e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seoenum cm36651_command {
113e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	CM36651_CMD_READ_RAW_LIGHT,
114e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	CM36651_CMD_READ_RAW_PROXIMITY,
115e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	CM36651_CMD_PROX_EV_EN,
116e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	CM36651_CMD_PROX_EV_DIS,
117e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo};
118e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
119e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seostatic const u8 cm36651_cs_reg[CM36651_CS_CONF_REG_NUM] = {
120e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	CM36651_CS_CONF1,
121e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	CM36651_CS_CONF2,
122e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo};
123e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
124e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seostatic const u8 cm36651_ps_reg[CM36651_PS_REG_NUM] = {
125e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	CM36651_PS_CONF1,
126e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	CM36651_PS_THD,
127e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	CM36651_PS_CANC,
128e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	CM36651_PS_CONF2,
129e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo};
130e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
131e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seostruct cm36651_data {
132e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	const struct cm36651_platform_data *pdata;
133e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	struct i2c_client *client;
134e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	struct i2c_client *ps_client;
135e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	struct i2c_client *ara_client;
136e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	struct mutex lock;
137e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	struct regulator *vled_reg;
138e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	unsigned long flags;
139e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	int cs_int_time[CM36651_CS_COLOR_NUM];
140e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	int ps_int_time;
141e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	u8 cs_ctrl_regs[CM36651_CS_CONF_REG_NUM];
142e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	u8 ps_ctrl_regs[CM36651_PS_REG_NUM];
143e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	u16 color[CM36651_CS_COLOR_NUM];
144e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo};
145e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
146e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seostatic int cm36651_setup_reg(struct cm36651_data *cm36651)
147e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo{
148e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	struct i2c_client *client = cm36651->client;
149e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	struct i2c_client *ps_client = cm36651->ps_client;
150e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	int i, ret;
151e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
152e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	/* CS initialization */
153e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	cm36651->cs_ctrl_regs[CM36651_CS_CONF1] = CM36651_ALS_ENABLE |
154e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo							     CM36651_ALS_THRES;
155e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	cm36651->cs_ctrl_regs[CM36651_CS_CONF2] = CM36651_CS_CONF2_DEFAULT_BIT;
156e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
157e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	for (i = 0; i < CM36651_CS_CONF_REG_NUM; i++) {
158e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		ret = i2c_smbus_write_byte_data(client, cm36651_cs_reg[i],
159e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo						     cm36651->cs_ctrl_regs[i]);
160e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		if (ret < 0)
161e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			return ret;
162e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	}
163e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
164e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	/* PS initialization */
165e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	cm36651->ps_ctrl_regs[CM36651_PS_CONF1] = CM36651_PS_ENABLE |
166e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo								CM36651_PS_IT2;
167e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	cm36651->ps_ctrl_regs[CM36651_PS_THD] = CM36651_PS_INITIAL_THD;
168e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	cm36651->ps_ctrl_regs[CM36651_PS_CANC] = CM36651_PS_CANC_DEFAULT;
169e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	cm36651->ps_ctrl_regs[CM36651_PS_CONF2] = CM36651_PS_HYS2 |
170e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo				CM36651_PS_DIR_INT | CM36651_PS_SMART_PERS_EN;
171e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
172e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	for (i = 0; i < CM36651_PS_REG_NUM; i++) {
173e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		ret = i2c_smbus_write_byte_data(ps_client, cm36651_ps_reg[i],
174e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo						     cm36651->ps_ctrl_regs[i]);
175e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		if (ret < 0)
176e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			return ret;
177e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	}
178e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
179e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	/* Set shutdown mode */
180e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	ret = i2c_smbus_write_byte_data(client, CM36651_CS_CONF1,
181e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo							  CM36651_ALS_DISABLE);
182e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	if (ret < 0)
183e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		return ret;
184e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
185e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	ret = i2c_smbus_write_byte_data(cm36651->ps_client,
186e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo					 CM36651_PS_CONF1, CM36651_PS_DISABLE);
187e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	if (ret < 0)
188e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		return ret;
189e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
190e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	return 0;
191e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo}
192e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
193e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seostatic int cm36651_read_output(struct cm36651_data *cm36651,
194e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo				struct iio_chan_spec const *chan, int *val)
195e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo{
196e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	struct i2c_client *client = cm36651->client;
197e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	int ret = -EINVAL;
198e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
199e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	switch (chan->type) {
200e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	case IIO_LIGHT:
201e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		*val = i2c_smbus_read_word_data(client, chan->address);
202e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		if (*val < 0)
203e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			return ret;
204e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
205e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		ret = i2c_smbus_write_byte_data(client, CM36651_CS_CONF1,
206e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo							CM36651_ALS_DISABLE);
207e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		if (ret < 0)
208e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			return ret;
209e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
210e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		ret = IIO_VAL_INT;
211e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		break;
212e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	case IIO_PROXIMITY:
213e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		*val = i2c_smbus_read_byte(cm36651->ps_client);
214e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		if (*val < 0)
215e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			return ret;
216e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
217e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		if (!test_bit(CM36651_PROXIMITY_EV_EN, &cm36651->flags)) {
218e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			ret = i2c_smbus_write_byte_data(cm36651->ps_client,
219e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo					CM36651_PS_CONF1, CM36651_PS_DISABLE);
220e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			if (ret < 0)
221e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo				return ret;
222e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		}
223e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
224e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		ret = IIO_VAL_INT;
225e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		break;
226e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	default:
227e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		break;
228e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	}
229e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
230e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	return ret;
231e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo}
232e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
233e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seostatic irqreturn_t cm36651_irq_handler(int irq, void *data)
234e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo{
235e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	struct iio_dev *indio_dev = data;
236e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	struct cm36651_data *cm36651 = iio_priv(indio_dev);
237e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	struct i2c_client *client = cm36651->client;
238e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	int ev_dir, ret;
239e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	u64 ev_code;
240e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
241e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	/*
242e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	 * The PS INT pin is an active low signal that PS INT move logic low
243e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	 * when the object is detect. Once the MCU host received the PS INT
244e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	 * "LOW" signal, the Host needs to read the data at Alert Response
245e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	 * Address(ARA) to clear the PS INT signal. After clearing the PS
246e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	 * INT pin, the PS INT signal toggles from low to high.
247e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	 */
248e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	ret = i2c_smbus_read_byte(cm36651->ara_client);
249e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	if (ret < 0) {
250e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		dev_err(&client->dev,
251e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo				"%s: Data read failed: %d\n", __func__, ret);
252e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		return IRQ_HANDLED;
253e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	}
254e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	switch (ret) {
255e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	case CM36651_CLOSE_PROXIMITY:
256e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		ev_dir = IIO_EV_DIR_RISING;
257e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		break;
258e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	case CM36651_FAR_PROXIMITY:
259e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		ev_dir = IIO_EV_DIR_FALLING;
260e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		break;
261e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	default:
262e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		dev_err(&client->dev,
263e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			"%s: Data read wrong: %d\n", __func__, ret);
264e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		return IRQ_HANDLED;
265e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	}
266e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
267e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	ev_code = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY,
268e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo				CM36651_CMD_READ_RAW_PROXIMITY,
269e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo				IIO_EV_TYPE_THRESH, ev_dir);
270e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
271e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	iio_push_event(indio_dev, ev_code, iio_get_time_ns());
272e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
273e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	return IRQ_HANDLED;
274e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo}
275e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
276e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seostatic int cm36651_set_operation_mode(struct cm36651_data *cm36651, int cmd)
277e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo{
278e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	struct i2c_client *client = cm36651->client;
279e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	struct i2c_client *ps_client = cm36651->ps_client;
280e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	int ret = -EINVAL;
281e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
282e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	switch (cmd) {
283e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	case CM36651_CMD_READ_RAW_LIGHT:
284e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		ret = i2c_smbus_write_byte_data(client, CM36651_CS_CONF1,
285e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo				cm36651->cs_ctrl_regs[CM36651_CS_CONF1]);
286e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		break;
287e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	case CM36651_CMD_READ_RAW_PROXIMITY:
288e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		if (test_bit(CM36651_PROXIMITY_EV_EN, &cm36651->flags))
289e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			return CM36651_PROXIMITY_EV_EN;
290e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
291e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		ret = i2c_smbus_write_byte_data(ps_client, CM36651_PS_CONF1,
292e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo				cm36651->ps_ctrl_regs[CM36651_PS_CONF1]);
293e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		break;
294e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	case CM36651_CMD_PROX_EV_EN:
295e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		if (test_bit(CM36651_PROXIMITY_EV_EN, &cm36651->flags)) {
296e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			dev_err(&client->dev,
297e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo				"Already proximity event enable state\n");
298e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			return ret;
299e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		}
300e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		set_bit(CM36651_PROXIMITY_EV_EN, &cm36651->flags);
301e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
302e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		ret = i2c_smbus_write_byte_data(ps_client,
303e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			cm36651_ps_reg[CM36651_PS_CONF1],
304e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			CM36651_PS_INT_EN | CM36651_PS_PERS2 | CM36651_PS_IT2);
305e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
306e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		if (ret < 0) {
307e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			dev_err(&client->dev, "Proximity enable event failed\n");
308e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			return ret;
309e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		}
310e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		break;
311e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	case CM36651_CMD_PROX_EV_DIS:
312e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		if (!test_bit(CM36651_PROXIMITY_EV_EN, &cm36651->flags)) {
313e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			dev_err(&client->dev,
314e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo				"Already proximity event disable state\n");
315e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			return ret;
316e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		}
317e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		clear_bit(CM36651_PROXIMITY_EV_EN, &cm36651->flags);
318e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		ret = i2c_smbus_write_byte_data(ps_client,
319e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo					CM36651_PS_CONF1, CM36651_PS_DISABLE);
320e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		break;
321e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	}
322e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
323e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	if (ret < 0)
324e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		dev_err(&client->dev, "Write register failed\n");
325e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
326e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	return ret;
327e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo}
328e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
329e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seostatic int cm36651_read_channel(struct cm36651_data *cm36651,
330e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo				struct iio_chan_spec const *chan, int *val)
331e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo{
332e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	struct i2c_client *client = cm36651->client;
333e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	int cmd, ret;
334e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
335e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	if (chan->type == IIO_LIGHT)
336e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		cmd = CM36651_CMD_READ_RAW_LIGHT;
337e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	else if (chan->type == IIO_PROXIMITY)
338e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		cmd = CM36651_CMD_READ_RAW_PROXIMITY;
339e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	else
340e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		return -EINVAL;
341e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
342e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	ret = cm36651_set_operation_mode(cm36651, cmd);
343e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	if (ret < 0) {
344e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		dev_err(&client->dev, "CM36651 set operation mode failed\n");
345e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		return ret;
346e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	}
347e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	/* Delay for work after enable operation */
348e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	msleep(50);
349e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	ret = cm36651_read_output(cm36651, chan, val);
350e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	if (ret < 0) {
351e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		dev_err(&client->dev, "CM36651 read output failed\n");
352e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		return ret;
353e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	}
354e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
355e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	return ret;
356e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo}
357e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
358e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seostatic int cm36651_read_int_time(struct cm36651_data *cm36651,
35926c17a1c56f957560cb96d219c13d21dfb605819Beomho Seo				struct iio_chan_spec const *chan, int *val2)
360e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo{
361e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	switch (chan->type) {
362e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	case IIO_LIGHT:
363e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		if (cm36651->cs_int_time[chan->address] == CM36651_CS_IT1)
36426c17a1c56f957560cb96d219c13d21dfb605819Beomho Seo			*val2 = 80000;
365e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		else if (cm36651->cs_int_time[chan->address] == CM36651_CS_IT2)
36626c17a1c56f957560cb96d219c13d21dfb605819Beomho Seo			*val2 = 160000;
367e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		else if (cm36651->cs_int_time[chan->address] == CM36651_CS_IT3)
36826c17a1c56f957560cb96d219c13d21dfb605819Beomho Seo			*val2 = 320000;
369e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		else if (cm36651->cs_int_time[chan->address] == CM36651_CS_IT4)
37026c17a1c56f957560cb96d219c13d21dfb605819Beomho Seo			*val2 = 640000;
371e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		else
372e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			return -EINVAL;
373e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		break;
374e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	case IIO_PROXIMITY:
375e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		if (cm36651->ps_int_time == CM36651_PS_IT1)
37626c17a1c56f957560cb96d219c13d21dfb605819Beomho Seo			*val2 = 320;
377e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		else if (cm36651->ps_int_time == CM36651_PS_IT2)
37826c17a1c56f957560cb96d219c13d21dfb605819Beomho Seo			*val2 = 420;
379e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		else if (cm36651->ps_int_time == CM36651_PS_IT3)
38026c17a1c56f957560cb96d219c13d21dfb605819Beomho Seo			*val2 = 520;
381e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		else if (cm36651->ps_int_time == CM36651_PS_IT4)
38226c17a1c56f957560cb96d219c13d21dfb605819Beomho Seo			*val2 = 640;
383e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		else
384e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			return -EINVAL;
385e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		break;
386e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	default:
387e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		return -EINVAL;
388e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	}
389e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
39026c17a1c56f957560cb96d219c13d21dfb605819Beomho Seo	return IIO_VAL_INT_PLUS_MICRO;
391e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo}
392e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
393e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seostatic int cm36651_write_int_time(struct cm36651_data *cm36651,
394e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo				struct iio_chan_spec const *chan, int val)
395e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo{
396e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	struct i2c_client *client = cm36651->client;
397e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	struct i2c_client *ps_client = cm36651->ps_client;
398e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	int int_time, ret;
399e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
400e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	switch (chan->type) {
401e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	case IIO_LIGHT:
402e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		if (val == 80000)
403e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			int_time = CM36651_CS_IT1;
404e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		else if (val == 160000)
405e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			int_time = CM36651_CS_IT2;
406e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		else if (val == 320000)
407e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			int_time = CM36651_CS_IT3;
408e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		else if (val == 640000)
409e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			int_time = CM36651_CS_IT4;
410e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		else
411e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			return -EINVAL;
412e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
413e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		ret = i2c_smbus_write_byte_data(client, CM36651_CS_CONF3,
414e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo					   int_time >> 2 * (chan->address));
415e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		if (ret < 0) {
416e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			dev_err(&client->dev, "CS integration time write failed\n");
417e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			return ret;
418e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		}
419e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		cm36651->cs_int_time[chan->address] = int_time;
420e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		break;
421e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	case IIO_PROXIMITY:
422e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		if (val == 320)
423e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			int_time = CM36651_PS_IT1;
424e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		else if (val == 420)
425e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			int_time = CM36651_PS_IT2;
426e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		else if (val == 520)
427e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			int_time = CM36651_PS_IT3;
428e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		else if (val == 640)
429e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			int_time = CM36651_PS_IT4;
430e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		else
431e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			return -EINVAL;
432e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
433e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		ret = i2c_smbus_write_byte_data(ps_client,
434e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo						CM36651_PS_CONF1, int_time);
435e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		if (ret < 0) {
436e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			dev_err(&client->dev, "PS integration time write failed\n");
437e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			return ret;
438e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		}
439e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		cm36651->ps_int_time = int_time;
440e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		break;
441e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	default:
442e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		return -EINVAL;
443e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	}
444e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
445e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	return ret;
446e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo}
447e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
448e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seostatic int cm36651_read_raw(struct iio_dev *indio_dev,
449e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			    struct iio_chan_spec const *chan,
450e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			    int *val, int *val2, long mask)
451e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo{
452e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	struct cm36651_data *cm36651 = iio_priv(indio_dev);
453e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	int ret;
454e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
455e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	mutex_lock(&cm36651->lock);
456e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
457e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	switch (mask) {
458e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	case IIO_CHAN_INFO_RAW:
459e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		ret = cm36651_read_channel(cm36651, chan, val);
460e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		break;
461e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	case IIO_CHAN_INFO_INT_TIME:
46226c17a1c56f957560cb96d219c13d21dfb605819Beomho Seo		*val = 0;
46326c17a1c56f957560cb96d219c13d21dfb605819Beomho Seo		ret = cm36651_read_int_time(cm36651, chan, val2);
464e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		break;
465e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	default:
466e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		ret = -EINVAL;
467e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	}
468e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
469e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	mutex_unlock(&cm36651->lock);
470e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
471e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	return ret;
472e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo}
473e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
474e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seostatic int cm36651_write_raw(struct iio_dev *indio_dev,
475e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			     struct iio_chan_spec const *chan,
476e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			     int val, int val2, long mask)
477e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo{
478e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	struct cm36651_data *cm36651 = iio_priv(indio_dev);
479e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	struct i2c_client *client = cm36651->client;
480e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	int ret = -EINVAL;
481e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
482e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	if (mask == IIO_CHAN_INFO_INT_TIME) {
48326c17a1c56f957560cb96d219c13d21dfb605819Beomho Seo		ret = cm36651_write_int_time(cm36651, chan, val2);
484e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		if (ret < 0)
485e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			dev_err(&client->dev, "Integration time write failed\n");
486e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	}
487e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
488e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	return ret;
489e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo}
490e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
491e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seostatic int cm36651_read_prox_thresh(struct iio_dev *indio_dev,
492bb7f9d90a5c0c29885cc37418ae208118e04bd4fLars-Peter Clausen					const struct iio_chan_spec *chan,
493bb7f9d90a5c0c29885cc37418ae208118e04bd4fLars-Peter Clausen					enum iio_event_type type,
494bb7f9d90a5c0c29885cc37418ae208118e04bd4fLars-Peter Clausen					enum iio_event_direction dir,
495bb7f9d90a5c0c29885cc37418ae208118e04bd4fLars-Peter Clausen					enum iio_event_info info,
496bb7f9d90a5c0c29885cc37418ae208118e04bd4fLars-Peter Clausen					int *val, int *val2)
497e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo{
498e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	struct cm36651_data *cm36651 = iio_priv(indio_dev);
499e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
500e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	*val = cm36651->ps_ctrl_regs[CM36651_PS_THD];
501e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
502e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	return 0;
503e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo}
504e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
505e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seostatic int cm36651_write_prox_thresh(struct iio_dev *indio_dev,
506bb7f9d90a5c0c29885cc37418ae208118e04bd4fLars-Peter Clausen					const struct iio_chan_spec *chan,
507bb7f9d90a5c0c29885cc37418ae208118e04bd4fLars-Peter Clausen					enum iio_event_type type,
508bb7f9d90a5c0c29885cc37418ae208118e04bd4fLars-Peter Clausen					enum iio_event_direction dir,
509bb7f9d90a5c0c29885cc37418ae208118e04bd4fLars-Peter Clausen					enum iio_event_info info,
510bb7f9d90a5c0c29885cc37418ae208118e04bd4fLars-Peter Clausen					int val, int val2)
511e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo{
512e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	struct cm36651_data *cm36651 = iio_priv(indio_dev);
513e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	struct i2c_client *client = cm36651->client;
514e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	int ret;
515e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
516e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	if (val < 3 || val > 255)
517e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		return -EINVAL;
518e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
519e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	cm36651->ps_ctrl_regs[CM36651_PS_THD] = val;
520e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	ret = i2c_smbus_write_byte_data(cm36651->ps_client, CM36651_PS_THD,
521e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo					cm36651->ps_ctrl_regs[CM36651_PS_THD]);
522e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
523e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	if (ret < 0) {
524e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		dev_err(&client->dev, "PS threshold write failed: %d\n", ret);
525e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		return ret;
526e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	}
527e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
528e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	return 0;
529e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo}
530e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
531e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seostatic int cm36651_write_prox_event_config(struct iio_dev *indio_dev,
532bb7f9d90a5c0c29885cc37418ae208118e04bd4fLars-Peter Clausen					const struct iio_chan_spec *chan,
533bb7f9d90a5c0c29885cc37418ae208118e04bd4fLars-Peter Clausen					enum iio_event_type type,
534bb7f9d90a5c0c29885cc37418ae208118e04bd4fLars-Peter Clausen					enum iio_event_direction dir,
535bb7f9d90a5c0c29885cc37418ae208118e04bd4fLars-Peter Clausen					int state)
536e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo{
537e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	struct cm36651_data *cm36651 = iio_priv(indio_dev);
538e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	int cmd, ret = -EINVAL;
539e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
540e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	mutex_lock(&cm36651->lock);
541e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
542e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	cmd = state ? CM36651_CMD_PROX_EV_EN : CM36651_CMD_PROX_EV_DIS;
543e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	ret = cm36651_set_operation_mode(cm36651, cmd);
544e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
545e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	mutex_unlock(&cm36651->lock);
546e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
547e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	return ret;
548e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo}
549e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
550e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seostatic int cm36651_read_prox_event_config(struct iio_dev *indio_dev,
551bb7f9d90a5c0c29885cc37418ae208118e04bd4fLars-Peter Clausen					const struct iio_chan_spec *chan,
552bb7f9d90a5c0c29885cc37418ae208118e04bd4fLars-Peter Clausen					enum iio_event_type type,
553bb7f9d90a5c0c29885cc37418ae208118e04bd4fLars-Peter Clausen					enum iio_event_direction dir)
554e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo{
555e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	struct cm36651_data *cm36651 = iio_priv(indio_dev);
556e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	int event_en;
557e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
558e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	mutex_lock(&cm36651->lock);
559e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
560e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	event_en = test_bit(CM36651_PROXIMITY_EV_EN, &cm36651->flags);
561e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
562e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	mutex_unlock(&cm36651->lock);
563e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
564e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	return event_en;
565e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo}
566e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
567e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo#define CM36651_LIGHT_CHANNEL(_color, _idx) {		\
568e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	.type = IIO_LIGHT,				\
569e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |	\
570e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			BIT(IIO_CHAN_INFO_INT_TIME),	\
571e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	.address = _idx,				\
572e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	.modified = 1,					\
573e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	.channel2 = IIO_MOD_LIGHT_##_color,		\
574e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo}							\
575e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
576bb7f9d90a5c0c29885cc37418ae208118e04bd4fLars-Peter Clausenstatic const struct iio_event_spec cm36651_event_spec[] = {
577bb7f9d90a5c0c29885cc37418ae208118e04bd4fLars-Peter Clausen	{
578bb7f9d90a5c0c29885cc37418ae208118e04bd4fLars-Peter Clausen		.type = IIO_EV_TYPE_THRESH,
579bb7f9d90a5c0c29885cc37418ae208118e04bd4fLars-Peter Clausen		.dir = IIO_EV_DIR_EITHER,
580bb7f9d90a5c0c29885cc37418ae208118e04bd4fLars-Peter Clausen		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
581bb7f9d90a5c0c29885cc37418ae208118e04bd4fLars-Peter Clausen				BIT(IIO_EV_INFO_ENABLE),
582bb7f9d90a5c0c29885cc37418ae208118e04bd4fLars-Peter Clausen	}
583bb7f9d90a5c0c29885cc37418ae208118e04bd4fLars-Peter Clausen};
584bb7f9d90a5c0c29885cc37418ae208118e04bd4fLars-Peter Clausen
585e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seostatic const struct iio_chan_spec cm36651_channels[] = {
586e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	{
587e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		.type = IIO_PROXIMITY,
588e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
589e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo				BIT(IIO_CHAN_INFO_INT_TIME),
590bb7f9d90a5c0c29885cc37418ae208118e04bd4fLars-Peter Clausen		.event_spec = cm36651_event_spec,
591bb7f9d90a5c0c29885cc37418ae208118e04bd4fLars-Peter Clausen		.num_event_specs = ARRAY_SIZE(cm36651_event_spec),
592e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	},
593e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	CM36651_LIGHT_CHANNEL(RED, CM36651_LIGHT_CHANNEL_IDX_RED),
594e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	CM36651_LIGHT_CHANNEL(GREEN, CM36651_LIGHT_CHANNEL_IDX_GREEN),
595e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	CM36651_LIGHT_CHANNEL(BLUE, CM36651_LIGHT_CHANNEL_IDX_BLUE),
596e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	CM36651_LIGHT_CHANNEL(CLEAR, CM36651_LIGHT_CHANNEL_IDX_CLEAR),
597e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo};
598e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
599e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seostatic IIO_CONST_ATTR(in_illuminance_integration_time_available,
600e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo					CM36651_CS_INT_TIME_AVAIL);
601e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seostatic IIO_CONST_ATTR(in_proximity_integration_time_available,
602e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo					CM36651_PS_INT_TIME_AVAIL);
603e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
604e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seostatic struct attribute *cm36651_attributes[] = {
605e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	&iio_const_attr_in_illuminance_integration_time_available.dev_attr.attr,
606e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	&iio_const_attr_in_proximity_integration_time_available.dev_attr.attr,
607e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	NULL,
608e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo};
609e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
610e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seostatic const struct attribute_group cm36651_attribute_group = {
611e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	.attrs = cm36651_attributes
612e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo};
613e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
614e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seostatic const struct iio_info cm36651_info = {
615e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	.driver_module		= THIS_MODULE,
616e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	.read_raw		= &cm36651_read_raw,
617e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	.write_raw		= &cm36651_write_raw,
618e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	.read_event_value	= &cm36651_read_prox_thresh,
619e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	.write_event_value	= &cm36651_write_prox_thresh,
620e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	.read_event_config	= &cm36651_read_prox_event_config,
621e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	.write_event_config	= &cm36651_write_prox_event_config,
622e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	.attrs			= &cm36651_attribute_group,
623e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo};
624e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
625e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seostatic int cm36651_probe(struct i2c_client *client,
626e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo			     const struct i2c_device_id *id)
627e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo{
628e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	struct cm36651_data *cm36651;
629e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	struct iio_dev *indio_dev;
630e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	int ret;
631e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
632e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*cm36651));
633e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	if (!indio_dev)
634e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		return -ENOMEM;
635e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
636e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	cm36651 = iio_priv(indio_dev);
637e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
638e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	cm36651->vled_reg = devm_regulator_get(&client->dev, "vled");
639e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	if (IS_ERR(cm36651->vled_reg)) {
640e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		dev_err(&client->dev, "get regulator vled failed\n");
641e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		return PTR_ERR(cm36651->vled_reg);
642e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	}
643e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
644e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	ret = regulator_enable(cm36651->vled_reg);
645e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	if (ret) {
646e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		dev_err(&client->dev, "enable regulator vled failed\n");
647e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		return ret;
648e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	}
649e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
650e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	i2c_set_clientdata(client, indio_dev);
651e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
652e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	cm36651->client = client;
653e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	cm36651->ps_client = i2c_new_dummy(client->adapter,
654e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo						     CM36651_I2C_ADDR_PS);
655d0a588a57c2b0748df8307a0865a1bbbf1624c53Krzysztof Kozlowski	if (!cm36651->ps_client) {
656d0a588a57c2b0748df8307a0865a1bbbf1624c53Krzysztof Kozlowski		dev_err(&client->dev, "%s: new i2c device failed\n", __func__);
657d0a588a57c2b0748df8307a0865a1bbbf1624c53Krzysztof Kozlowski		ret = -ENODEV;
658d0a588a57c2b0748df8307a0865a1bbbf1624c53Krzysztof Kozlowski		goto error_disable_reg;
659d0a588a57c2b0748df8307a0865a1bbbf1624c53Krzysztof Kozlowski	}
660d0a588a57c2b0748df8307a0865a1bbbf1624c53Krzysztof Kozlowski
661e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	cm36651->ara_client = i2c_new_dummy(client->adapter, CM36651_ARA);
662d0a588a57c2b0748df8307a0865a1bbbf1624c53Krzysztof Kozlowski	if (!cm36651->ara_client) {
663d0a588a57c2b0748df8307a0865a1bbbf1624c53Krzysztof Kozlowski		dev_err(&client->dev, "%s: new i2c device failed\n", __func__);
664d0a588a57c2b0748df8307a0865a1bbbf1624c53Krzysztof Kozlowski		ret = -ENODEV;
665d0a588a57c2b0748df8307a0865a1bbbf1624c53Krzysztof Kozlowski		goto error_i2c_unregister_ps;
666d0a588a57c2b0748df8307a0865a1bbbf1624c53Krzysztof Kozlowski	}
667d0a588a57c2b0748df8307a0865a1bbbf1624c53Krzysztof Kozlowski
668e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	mutex_init(&cm36651->lock);
669e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	indio_dev->dev.parent = &client->dev;
670e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	indio_dev->channels = cm36651_channels;
671e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	indio_dev->num_channels = ARRAY_SIZE(cm36651_channels);
672e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	indio_dev->info = &cm36651_info;
673e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	indio_dev->name = id->name;
674e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	indio_dev->modes = INDIO_DIRECT_MODE;
675e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
676e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	ret = cm36651_setup_reg(cm36651);
677e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	if (ret) {
678e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		dev_err(&client->dev, "%s: register setup failed\n", __func__);
679d0a588a57c2b0748df8307a0865a1bbbf1624c53Krzysztof Kozlowski		goto error_i2c_unregister_ara;
680e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	}
681e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
682e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	ret = request_threaded_irq(client->irq, NULL, cm36651_irq_handler,
683e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo					IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
684e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo							"cm36651", indio_dev);
685e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	if (ret) {
686e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		dev_err(&client->dev, "%s: request irq failed\n", __func__);
687d0a588a57c2b0748df8307a0865a1bbbf1624c53Krzysztof Kozlowski		goto error_i2c_unregister_ara;
688e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	}
689e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
690e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	ret = iio_device_register(indio_dev);
691e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	if (ret) {
692e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		dev_err(&client->dev, "%s: regist device failed\n", __func__);
693e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		goto error_free_irq;
694e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	}
695e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
696e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	return 0;
697e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
698e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seoerror_free_irq:
699e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	free_irq(client->irq, indio_dev);
700d0a588a57c2b0748df8307a0865a1bbbf1624c53Krzysztof Kozlowskierror_i2c_unregister_ara:
701d0a588a57c2b0748df8307a0865a1bbbf1624c53Krzysztof Kozlowski	i2c_unregister_device(cm36651->ara_client);
702d0a588a57c2b0748df8307a0865a1bbbf1624c53Krzysztof Kozlowskierror_i2c_unregister_ps:
703d0a588a57c2b0748df8307a0865a1bbbf1624c53Krzysztof Kozlowski	i2c_unregister_device(cm36651->ps_client);
704e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seoerror_disable_reg:
705e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	regulator_disable(cm36651->vled_reg);
706e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	return ret;
707e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo}
708e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
709e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seostatic int cm36651_remove(struct i2c_client *client)
710e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo{
711e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	struct iio_dev *indio_dev = i2c_get_clientdata(client);
712e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	struct cm36651_data *cm36651 = iio_priv(indio_dev);
713e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
714e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	iio_device_unregister(indio_dev);
715e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	regulator_disable(cm36651->vled_reg);
716e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	free_irq(client->irq, indio_dev);
717d0a588a57c2b0748df8307a0865a1bbbf1624c53Krzysztof Kozlowski	i2c_unregister_device(cm36651->ps_client);
718d0a588a57c2b0748df8307a0865a1bbbf1624c53Krzysztof Kozlowski	i2c_unregister_device(cm36651->ara_client);
719e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
720e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	return 0;
721e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo}
722e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
723e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seostatic const struct i2c_device_id cm36651_id[] = {
724e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	{ "cm36651", 0 },
725e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	{ }
726e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo};
727e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
728e590d451908329fee0515a4ec397154a16cfc8c4Beomho SeoMODULE_DEVICE_TABLE(i2c, cm36651_id);
729e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
730e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seostatic const struct of_device_id cm36651_of_match[] = {
731e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	{ .compatible = "capella,cm36651" },
732e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	{ }
733e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo};
734e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
735e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seostatic struct i2c_driver cm36651_driver = {
736e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	.driver = {
737e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		.name	= "cm36651",
738a451521d2229266dae0b876efb5999d82d03850eSachin Kamat		.of_match_table = cm36651_of_match,
739e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo		.owner	= THIS_MODULE,
740e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	},
741e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	.probe		= cm36651_probe,
742e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	.remove		= cm36651_remove,
743e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo	.id_table	= cm36651_id,
744e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo};
745e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
746e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seomodule_i2c_driver(cm36651_driver);
747e590d451908329fee0515a4ec397154a16cfc8c4Beomho Seo
748e590d451908329fee0515a4ec397154a16cfc8c4Beomho SeoMODULE_AUTHOR("Beomho Seo <beomho.seo@samsung.com>");
749e590d451908329fee0515a4ec397154a16cfc8c4Beomho SeoMODULE_DESCRIPTION("CM36651 proximity/ambient light sensor driver");
750e590d451908329fee0515a4ec397154a16cfc8c4Beomho SeoMODULE_LICENSE("GPL v2");
751