blob: 9db162a57dce2e40bbe11638de06a62a56739d49 [file] [log] [blame]
/*
* Copyright (C) 2010,Imagis Technology Co. Ltd. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include <asm/unaligned.h>
#include <asm/io.h>
#include <mach/gpio.h>
//#include <mach/vreg.h>
#include <linux/regulator/consumer.h>
#include "ist30xx.h"
/******************************************************************************
* Return value of Error
* EPERM : 1 (Operation not permitted)
* ENOENT : 2 (No such file or directory)
* EIO : 5 (I/O error)
* ENXIO : 6 (No such device or address)
* EINVAL : 22 (Invalid argument)
*****************************************************************************/
extern struct ist30xx_data *ts_data;
#if IST30XX_NOISE_MODE
#endif
const u32 pos_cmd = cpu_to_be32(CMD_GET_COORD);
struct i2c_msg pos_msg[READ_CMD_MSG_LEN] = {
{
.flags = 0,
.len = IST30XX_ADDR_LEN,
.buf = (u8 *)&pos_cmd,
},
{ .flags = I2C_M_RD, },
};
int ist30xx_get_position(struct i2c_client *client, u32 *buf, u16 len)
{
int ret, i;
pos_msg[0].addr = client->addr;
pos_msg[1].addr = client->addr;
pos_msg[1].len = len * IST30XX_DATA_LEN,
pos_msg[1].buf = (u8 *)buf,
ret = i2c_transfer(client->adapter, pos_msg, READ_CMD_MSG_LEN);
if (ret != READ_CMD_MSG_LEN) {
tsp_err("%s: i2c failed (%d)\n", __func__, ret);
return -EIO;
}
for (i = 0; i < len; i++)
buf[i] = cpu_to_be32(buf[i]);
return 0;
}
int ist30xx_cmd_run_device(struct i2c_client *client)
{
int ret = -EIO;
ist30xx_reset();
ret = ist30xx_write_cmd(client, CMD_RUN_DEVICE, 0);
msleep(10);
return ret;
}
int ist30xx_cmd_start_scan(struct i2c_client *client)
{
int ret;
ret = ist30xx_write_cmd(client, CMD_START_SCAN, 0);
msleep(100);
#if IST30XX_NOISE_MODE
ts_data->status.noise_mode = true;
#endif
return ret;
}
int ist30xx_cmd_calibrate(struct i2c_client *client)
{
int ret = ist30xx_write_cmd(client, CMD_CALIBRATE, 0);
tsp_info("%s\n", __func__);
msleep(100);
return ret;
}
int ist30xx_cmd_check_calib(struct i2c_client *client)
{
int ret = ist30xx_write_cmd(client, CMD_CHECK_CALIB, 0);
tsp_info("*** Check Calibration cmd ***\n");
msleep(20);
return ret;
}
int ist30xx_cmd_update(struct i2c_client *client, int cmd)
{
u32 val = (cmd == CMD_ENTER_FW_UPDATE ? CMD_FW_UPDATE_MAGIC : 0);
int ret = ist30xx_write_cmd(client, cmd, val);
msleep(10);
return ret;
}
int ist30xx_cmd_reg(struct i2c_client *client, int cmd)
{
int ret = ist30xx_write_cmd(client, cmd, 0);
if (cmd == CMD_ENTER_REG_ACCESS)
msleep(100);
else if (cmd == CMD_EXIT_REG_ACCESS)
msleep(10);
return ret;
}
int ist30xx_read_cmd(struct i2c_client *client, u32 cmd, u32 *buf)
{
int ret;
u32 le_reg = cpu_to_be32(cmd);
struct i2c_msg msg[READ_CMD_MSG_LEN] = {
{
.addr = client->addr,
.flags = 0,
.len = IST30XX_ADDR_LEN,
.buf = (u8 *)&le_reg,
},
{
.addr = client->addr,
.flags = I2C_M_RD,
.len = IST30XX_DATA_LEN,
.buf = (u8 *)buf,
},
};
ret = i2c_transfer(client->adapter, msg, READ_CMD_MSG_LEN);
if (ret != READ_CMD_MSG_LEN) {
tsp_err("%s: i2c failed (%d), cmd: %x\n", __func__, ret, cmd);
return -EIO;
}
*buf = cpu_to_be32(*buf);
return 0;
}
int ist30xx_write_cmd(struct i2c_client *client, u32 cmd, u32 val)
{
int ret;
struct i2c_msg msg;
u8 msg_buf[IST30XX_ADDR_LEN + IST30XX_DATA_LEN];
put_unaligned_be32(cmd, msg_buf);
put_unaligned_be32(val, msg_buf + IST30XX_ADDR_LEN);
msg.addr = client->addr;
msg.flags = 0;
msg.len = IST30XX_ADDR_LEN + IST30XX_DATA_LEN;
msg.buf = msg_buf;
ret = i2c_transfer(client->adapter, &msg, WRITE_CMD_MSG_LEN);
if (ret != WRITE_CMD_MSG_LEN) {
tsp_err("%s: i2c failed (%d), cmd: %x(%x)\n", __func__, ret, cmd, val);
return -EIO;
}
return 0;
}
#define TSP_PWR_LDO_GPIO 41
#define GPIO_TSP_SCL 35
#define GPIO_TSP_SDA 40
static struct regulator *touch_regulator;
static void ts_power_enable(int en)
{
int ret;
printk(KERN_ERR "%s %s\n", __func__, (en) ? "on" : "off");
if(touch_regulator == NULL)
{
touch_regulator = regulator_get(NULL, "gpldo2_uc");
if(printk(touch_regulator))
printk("can not get VTOUCH_3.3V\n");
printk("touch_regulator= %d\n",touch_regulator);
}
if(en==1)
{
ret = regulator_set_voltage(touch_regulator,3000000,3000000); //@Fixed me, HW
if(ret < 0)
printk("[TSP] regulator_set_voltage ret = %d \n", ret);
ret = regulator_enable(touch_regulator);
if(ret < 0)
printk("[TSP] regulator_enable ret = %d \n", ret);
}
else
{
ret = regulator_disable(touch_regulator);
if(ret < 0)
printk("regulator_disable ret = %d \n", ret);
}
}
int ist30xx_power_on(void)
{
if (ts_data->status.power != 1) {
tsp_info("%s()\n", __func__);
/* VDD enable */
msleep(5);
/* VDDIO enable */
ts_power_enable(1);
msleep(100);
ts_data->status.power = 1;
}
return 0;
}
int ist30xx_power_off(void)
{
if (ts_data->status.power != 0) {
tsp_info("%s()\n", __func__);
/* VDDIO disable */
msleep(5);
/* VDD disable */
ts_power_enable(0);
msleep(50);
ts_data->status.power = 0;
ts_data->status.noise_mode = false;
}
return 0;
}
int ist30xx_reset(void)
{
tsp_info("%s()\n", __func__);
ist30xx_power_off();
msleep(10);
ist30xx_power_on();
ts_data->status.power = 1;
return 0;
}
int ist30xx_internal_suspend(struct ist30xx_data *data)
{
ist30xx_power_off();
return 0;
}
int ist30xx_internal_resume(struct ist30xx_data *data)
{
ist30xx_power_on();
ist30xx_write_cmd(data->client, CMD_RUN_DEVICE, 0);
msleep(10);
return 0;
}
int ist30xx_init_system(void)
{
int ret;
// TODO : place additional code here.
#if 1
ret = ist30xx_power_on();
if (ret) {
tsp_err("%s: ist30xx_power_on failed (%d)\n", __func__, ret);
return -EIO;
}
#endif
#if 0
ret = ist30xx_reset();
if (ret) {
tsp_err("%s: ist30xx_reset failed (%d)\n", __func__, ret);
return -EIO;
}
#endif
return 0;
}