2 * Copyright (C) 2010,Imagis Technology Co. Ltd. All Rights Reserved.
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.
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.
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>
23 #include <mach/gpio.h>
24 /* Removing the error for finding mach/vreg.h
25 #include <mach/vreg.h>
28 #include "ist30xx_tracking.h"
30 #include <linux/regulator/machine.h>
38 /******************************************************************************
39 * Return value of Error
40 * EPERM : 1 (Operation not permitted)
41 * ENOENT : 2 (No such file or directory)
43 * ENXIO : 6 (No such device or address)
44 * EINVAL : 22 (Invalid argument)
45 *****************************************************************************/
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] = {
52 .len = IST30XX_ADDR_LEN,
53 .buf = (u8 *)&pos_cmd,
55 { .flags = I2C_M_RD, },
58 int ist30xx_get_position(struct i2c_client *client, u32 *buf, u16 len)
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,
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);
73 for (i = 0; i < len; i++)
74 buf[i] = cpu_to_be32(buf[i]);
79 int ist30xx_cmd_run_device(struct i2c_client *client, bool is_reset)
83 if (is_reset == true) ist30xx_reset();
84 ret = ist30xx_write_cmd(client, CMD_RUN_DEVICE, 0);
86 ist30xx_tracking(TRACK_CMD_RUN_DEVICE);
93 int ist30xx_cmd_start_scan(struct i2c_client *client)
97 ret = ist30xx_write_cmd(client, CMD_START_SCAN, 0);
99 ist30xx_tracking(TRACK_CMD_SCAN);
103 ts_data->status.noise_mode = true;
108 int ist30xx_cmd_calibrate(struct i2c_client *client)
110 int ret = ist30xx_write_cmd(client, CMD_CALIBRATE, 0);
112 ist30xx_tracking(TRACK_CMD_CALIB);
114 tsp_info("%s\n", __func__);
121 int ist30xx_cmd_check_calib(struct i2c_client *client)
123 int ret = ist30xx_write_cmd(client, CMD_CHECK_CALIB, 0);
125 ist30xx_tracking(TRACK_CMD_CHECK_CALIB);
127 tsp_info("*** Check Calibration cmd ***\n");
134 int ist30xx_cmd_update(struct i2c_client *client, int cmd)
136 u32 val = (cmd == CMD_ENTER_FW_UPDATE ? CMD_FW_UPDATE_MAGIC : 0);
137 int ret = ist30xx_write_cmd(client, cmd, val);
139 ist30xx_tracking(TRACK_CMD_FWUPDATE);
146 int ist30xx_cmd_reg(struct i2c_client *client, int cmd)
148 int ret = ist30xx_write_cmd(client, cmd, 0);
150 if (cmd == CMD_ENTER_REG_ACCESS) {
151 ist30xx_tracking(TRACK_CMD_ENTER_REG);
153 } else if (cmd == CMD_EXIT_REG_ACCESS) {
154 ist30xx_tracking(TRACK_CMD_EXIT_REG);
162 int ist30xx_read_cmd(struct i2c_client *client, u32 cmd, u32 *buf)
165 u32 le_reg = cpu_to_be32(cmd);
167 struct i2c_msg msg[READ_CMD_MSG_LEN] = {
169 .addr = client->addr,
171 .len = IST30XX_ADDR_LEN,
172 .buf = (u8 *)&le_reg,
175 .addr = client->addr,
177 .len = IST30XX_DATA_LEN,
182 ret = i2c_transfer(client->adapter, msg, READ_CMD_MSG_LEN);
183 if (ret != READ_CMD_MSG_LEN) {
186 tsp_err("%s: i2c failed (%d), cmd: %x\n", __func__, ret, cmd);
189 *buf = cpu_to_be32(*buf);
195 int ist30xx_write_cmd(struct i2c_client *client, u32 cmd, u32 val)
199 u8 msg_buf[IST30XX_ADDR_LEN + IST30XX_DATA_LEN];
201 put_unaligned_be32(cmd, msg_buf);
202 put_unaligned_be32(val, msg_buf + IST30XX_ADDR_LEN);
204 msg.addr = client->addr;
206 msg.len = IST30XX_ADDR_LEN + IST30XX_DATA_LEN;
209 ret = i2c_transfer(client->adapter, &msg, WRITE_CMD_MSG_LEN);
210 if (ret != WRITE_CMD_MSG_LEN) {
213 tsp_err("%s: i2c failed (%d), cmd: %x(%x)\n", __func__, ret, cmd, val);
220 static void ts_power_enable(int en)
224 static struct regulator *ts_vdd = NULL;
226 if (ts_vdd == NULL) {
227 ts_vdd = regulator_get(NULL, "vddsim2");
229 if (IS_ERR(ts_vdd)) {
230 pr_err("Get regulator of TSP error!\n");
235 regulator_set_voltage(ts_vdd, 3000000, 3000000);
236 regulator_enable(ts_vdd);
238 else if (regulator_is_enabled(ts_vdd)) {
239 regulator_disable(ts_vdd);
243 printk(KERN_INFO "%s %s\n", __func__, (en) ? "on" : "off");
244 printk("%s: TS power change to %d.\n", __func__, en);
247 int ist30xx_power_on(void)
249 if (ts_data->status.power != 1) {
250 tsp_info("%s()\n", __func__);
253 ist30xx_tracking(TRACK_PWR_ON);
256 ts_data->status.power = 1;
257 printk("[ TSP ] %s\n", __func__);
264 int ist30xx_power_off(void)
266 if (ts_data->status.power != 0) {
267 tsp_info("%s()\n", __func__);
270 ist30xx_tracking(TRACK_PWR_OFF);
273 ts_data->status.power = 0;
274 ts_data->status.noise_mode = false;
275 printk("[ TSP ] %s\n", __func__);
282 int ist30xx_reset(void)
284 tsp_info("%s()\n", __func__);
289 ts_data->status.power = 1;
294 int ist30xx_internal_suspend(struct ist30xx_data *data)
301 int ist30xx_internal_resume(struct ist30xx_data *data)
304 ist30xx_cmd_run_device(data->client, false);
309 int ist30xx_init_system(void)
313 // TODO : place additional code here.
314 ret = ist30xx_power_on();
316 tsp_err("%s: ist30xx_power_on failed (%d)\n", __func__, ret);
320 ret = ist30xx_reset();
322 tsp_err("%s: ist30xx_reset failed (%d)\n", __func__, ret);