tizen 2.4 release
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / drivers / input / touchscreen / ist30xx / ist30xx_sys.c
1 /*
2  *  Copyright (C) 2010,Imagis Technology Co. Ltd. All Rights Reserved.
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  */
15
16 #include <linux/kernel.h>
17 #include <linux/module.h>
18 #include <linux/slab.h>
19 #include <linux/i2c.h>
20 #include <linux/delay.h>
21 #include <asm/unaligned.h>
22 #include <asm/io.h>
23 #include <mach/gpio.h>
24 /* Removing the error for finding mach/vreg.h
25 #include <mach/vreg.h>
26 */
27 #include "ist30xx.h"
28 #include "ist30xx_tracking.h"
29 /*For regulators*/
30 #include <linux/regulator/machine.h>
31
32
33
34
35
36
37
38 /******************************************************************************
39  * Return value of Error
40  * EPERM  : 1 (Operation not permitted)
41  * ENOENT : 2 (No such file or directory)
42  * EIO    : 5 (I/O error)
43  * ENXIO  : 6 (No such device or address)
44  * EINVAL : 22 (Invalid argument)
45  *****************************************************************************/
46
47 extern struct ist30xx_data *ts_data;
48 const u32 pos_cmd = cpu_to_be32(CMD_GET_COORD);
49 struct i2c_msg pos_msg[READ_CMD_MSG_LEN] = {
50         {
51                 .flags = 0,
52                 .len = IST30XX_ADDR_LEN,
53                 .buf = (u8 *)&pos_cmd,
54         },
55         { .flags = I2C_M_RD, },
56 };
57
58 int ist30xx_get_position(struct i2c_client *client, u32 *buf, u16 len)
59 {
60         int ret, i;
61
62         pos_msg[0].addr = client->addr;
63         pos_msg[1].addr = client->addr;
64         pos_msg[1].len = len * IST30XX_DATA_LEN,
65         pos_msg[1].buf = (u8 *)buf,
66
67         ret = i2c_transfer(client->adapter, pos_msg, READ_CMD_MSG_LEN);
68         if (ret != READ_CMD_MSG_LEN) {
69                 tsp_err("%s: i2c failed (%d)\n", __func__, ret);
70                 return -EIO;
71         }
72
73         for (i = 0; i < len; i++)
74                 buf[i] = cpu_to_be32(buf[i]);
75
76         return 0;
77 }
78
79 int ist30xx_cmd_run_device(struct i2c_client *client, bool is_reset)
80 {
81         int ret = -EIO;
82
83         if (is_reset == true) ist30xx_reset();
84         ret = ist30xx_write_cmd(client, CMD_RUN_DEVICE, 0);
85
86         ist30xx_tracking(TRACK_CMD_RUN_DEVICE);
87
88         msleep(10);
89
90         return ret;
91 }
92
93 int ist30xx_cmd_start_scan(struct i2c_client *client)
94 {
95         int ret;
96
97         ret = ist30xx_write_cmd(client, CMD_START_SCAN, 0);
98
99         ist30xx_tracking(TRACK_CMD_SCAN);
100
101         msleep(100);
102
103         ts_data->status.noise_mode = true;
104
105         return ret;
106 }
107
108 int ist30xx_cmd_calibrate(struct i2c_client *client)
109 {
110         int ret = ist30xx_write_cmd(client, CMD_CALIBRATE, 0);
111
112         ist30xx_tracking(TRACK_CMD_CALIB);
113
114         tsp_info("%s\n", __func__);
115
116         msleep(100);
117
118         return ret;
119 }
120
121 int ist30xx_cmd_check_calib(struct i2c_client *client)
122 {
123         int ret = ist30xx_write_cmd(client, CMD_CHECK_CALIB, 0);
124
125         ist30xx_tracking(TRACK_CMD_CHECK_CALIB);
126
127         tsp_info("*** Check Calibration cmd ***\n");
128
129         msleep(20);
130
131         return ret;
132 }
133
134 int ist30xx_cmd_update(struct i2c_client *client, int cmd)
135 {
136         u32 val = (cmd == CMD_ENTER_FW_UPDATE ? CMD_FW_UPDATE_MAGIC : 0);
137         int ret = ist30xx_write_cmd(client, cmd, val);
138
139         ist30xx_tracking(TRACK_CMD_FWUPDATE);
140
141         msleep(10);
142
143         return ret;
144 }
145
146 int ist30xx_cmd_reg(struct i2c_client *client, int cmd)
147 {
148         int ret = ist30xx_write_cmd(client, cmd, 0);
149
150         if (cmd == CMD_ENTER_REG_ACCESS) {
151                 ist30xx_tracking(TRACK_CMD_ENTER_REG);
152                 msleep(100);
153         } else if (cmd == CMD_EXIT_REG_ACCESS) {
154                 ist30xx_tracking(TRACK_CMD_EXIT_REG);
155                 msleep(10);
156         }
157
158         return ret;
159 }
160
161
162 int ist30xx_read_cmd(struct i2c_client *client, u32 cmd, u32 *buf)
163 {
164         int ret,count=0;
165         u32 le_reg = cpu_to_be32(cmd);
166
167         struct i2c_msg msg[READ_CMD_MSG_LEN] = {
168                 {
169                         .addr = client->addr,
170                         .flags = 0,
171                         .len = IST30XX_ADDR_LEN,
172                         .buf = (u8 *)&le_reg,
173                 },
174                 {
175                         .addr = client->addr,
176                         .flags = I2C_M_RD,
177                         .len = IST30XX_DATA_LEN,
178                         .buf = (u8 *)buf,
179                 },
180         };
181 retry:
182         ret = i2c_transfer(client->adapter, msg, READ_CMD_MSG_LEN);
183         if (ret != READ_CMD_MSG_LEN) {
184                 if(count++ < 3)
185                         goto retry;
186                 tsp_err("%s: i2c failed (%d), cmd: %x\n", __func__, ret, cmd);
187                 return -EIO;
188         }
189         *buf = cpu_to_be32(*buf);
190
191         return 0;
192 }
193
194
195 int ist30xx_write_cmd(struct i2c_client *client, u32 cmd, u32 val)
196 {
197         int ret,count=0;
198         struct i2c_msg msg;
199         u8 msg_buf[IST30XX_ADDR_LEN + IST30XX_DATA_LEN];
200
201         put_unaligned_be32(cmd, msg_buf);
202         put_unaligned_be32(val, msg_buf + IST30XX_ADDR_LEN);
203
204         msg.addr = client->addr;
205         msg.flags = 0;
206         msg.len = IST30XX_ADDR_LEN + IST30XX_DATA_LEN;
207         msg.buf = msg_buf;
208 retry:
209         ret = i2c_transfer(client->adapter, &msg, WRITE_CMD_MSG_LEN);
210         if (ret != WRITE_CMD_MSG_LEN) {
211                 if(count++ < 3)
212                         goto retry;
213                 tsp_err("%s: i2c failed (%d), cmd: %x(%x)\n", __func__, ret, cmd, val);
214                 return -EIO;
215         }
216
217         return 0;
218 }
219
220 static void ts_power_enable(int en)
221 {
222
223
224         static struct regulator *ts_vdd = NULL;
225
226         if (ts_vdd == NULL) {
227                 ts_vdd = regulator_get(NULL, "vddsim2");
228
229                 if (IS_ERR(ts_vdd)) {
230                         pr_err("Get regulator of TSP error!\n");
231                         return;
232                 }
233         }
234         if (en) {
235                 regulator_set_voltage(ts_vdd, 3000000, 3000000);
236                 regulator_enable(ts_vdd);
237         }
238         else if (regulator_is_enabled(ts_vdd)) {
239                 regulator_disable(ts_vdd);
240         }
241
242
243         printk(KERN_INFO "%s %s\n", __func__, (en) ? "on" : "off");
244         printk("%s: TS power change to %d.\n", __func__, en);
245 }
246
247 int ist30xx_power_on(void)
248 {
249         if (ts_data->status.power != 1) {
250                 tsp_info("%s()\n", __func__);
251                 /* VDD enable */
252                 /* VDDIO enable */
253                 ist30xx_tracking(TRACK_PWR_ON);
254                 ts_power_enable(1);
255                 msleep(100);
256                 ts_data->status.power = 1;
257                 printk("[ TSP ] %s\n", __func__);
258         }
259
260         return 0;
261 }
262
263
264 int ist30xx_power_off(void)
265 {
266         if (ts_data->status.power != 0) {
267                 tsp_info("%s()\n", __func__);
268                 /* VDDIO disable */
269                 /* VDD disable */
270                 ist30xx_tracking(TRACK_PWR_OFF);
271                 ts_power_enable(0);
272                 msleep(50);
273                 ts_data->status.power = 0;
274                 ts_data->status.noise_mode = false;
275                 printk("[ TSP ] %s\n", __func__);
276         }
277
278         return 0;
279 }
280
281
282 int ist30xx_reset(void)
283 {
284         tsp_info("%s()\n", __func__);
285         ist30xx_power_off();
286         msleep(10);
287         ist30xx_power_on();
288
289         ts_data->status.power = 1;
290         return 0;
291 }
292
293
294 int ist30xx_internal_suspend(struct ist30xx_data *data)
295 {
296         ist30xx_power_off();
297         return 0;
298 }
299
300
301 int ist30xx_internal_resume(struct ist30xx_data *data)
302 {
303         ist30xx_power_on();
304         ist30xx_cmd_run_device(data->client, false);
305         return 0;
306 }
307
308
309 int ist30xx_init_system(void)
310 {
311         int ret;
312
313         // TODO : place additional code here.
314         ret = ist30xx_power_on();
315         if (ret) {
316                 tsp_err("%s: ist30xx_power_on failed (%d)\n", __func__, ret);
317                 return -EIO;
318         }
319 #if 0
320         ret = ist30xx_reset();
321         if (ret) {
322                 tsp_err("%s: ist30xx_reset failed (%d)\n", __func__, ret);
323                 return -EIO;
324         }
325 #endif
326         return 0;
327 }