mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 11:50:43 +09:00
drivers/input: remove unused auto touchscreen support
Change-Id: Idc012f66abfcad6e5d601f97bded60f230b6fdcc Signed-off-by: Tao Huang <huangtao@rock-chips.com>
This commit is contained in:
@@ -1,16 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# all auto touch screen drivers configuration
|
||||
#
|
||||
|
||||
menuconfig TS_AUTO
|
||||
bool "auto touch screen driver support"
|
||||
default n
|
||||
|
||||
if TS_AUTO
|
||||
|
||||
source "drivers/input/ts/chips/Kconfig"
|
||||
|
||||
endif
|
||||
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# auto touch screen drivers
|
||||
obj-$(CONFIG_TS_AUTO_I2C) += ts-i2c.o
|
||||
obj-$(CONFIG_TS_AUTO_SPI) += ts-spi.o
|
||||
obj-$(CONFIG_TS_AUTO_SERIAL) += ts-serial.o
|
||||
obj-$(CONFIG_TS_AUTO) += chips/
|
||||
obj-$(CONFIG_TS_AUTO) += ts-auto.o
|
||||
@@ -1,40 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
menuconfig TS_AUTO_I2C
|
||||
bool "Support auto touch screen with I2C"
|
||||
default n
|
||||
|
||||
if TS_AUTO_I2C
|
||||
|
||||
config TS_FT5306
|
||||
bool "touch screen ft5306"
|
||||
default n
|
||||
|
||||
config TS_GT8110
|
||||
bool "touch screen gt8110"
|
||||
default n
|
||||
|
||||
config TS_GT828
|
||||
bool "touch screen gt828"
|
||||
default n
|
||||
|
||||
config TS_CT360
|
||||
bool "touch screen ct360"
|
||||
default n
|
||||
|
||||
endif
|
||||
|
||||
config TS_AUTO_SPI
|
||||
bool "Support auto touch screen with SPI"
|
||||
depends on SPI_MASTER
|
||||
|
||||
if TS_AUTO_SPI
|
||||
|
||||
endif
|
||||
|
||||
config TS_AUTO_SERIAL
|
||||
bool "Support auto touch screen with UART"
|
||||
|
||||
if TS_AUTO_SERIAL
|
||||
|
||||
endif
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-$(CONFIG_TS_FT5306) += ft5306.o
|
||||
obj-$(CONFIG_TS_GT8110) += gt8110.o
|
||||
obj-$(CONFIG_TS_CT360) += ct360.o
|
||||
obj-$(CONFIG_TS_GT828) += gt828.o
|
||||
@@ -1,497 +0,0 @@
|
||||
/* drivers/input/ts/chips/ct360.c
|
||||
*
|
||||
* Copyright (C) 2012-2015 ROCKCHIP.
|
||||
* Author: luowei <lw@rock-chips.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* 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/interrupt.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <linux/input/mt.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/board.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/ts-auto.h>
|
||||
#include "ct360_firmware.h"
|
||||
|
||||
static struct i2c_client *this_client;
|
||||
|
||||
#if 0
|
||||
#define DBG(x...) printk(x)
|
||||
#else
|
||||
#define DBG(x...)
|
||||
#endif
|
||||
|
||||
|
||||
#define CT360_ID_REG 0x00
|
||||
#define CT360_DEVID 0x00
|
||||
#define CT360_DATA_REG 0x00
|
||||
|
||||
|
||||
/****************operate according to ts chip:start************/
|
||||
|
||||
static int ts_active(struct ts_private_data *ts, int enable)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if(enable)
|
||||
{
|
||||
gpio_direction_output(ts->pdata->reset_pin, GPIO_LOW);
|
||||
msleep(10);
|
||||
gpio_direction_output(ts->pdata->reset_pin, GPIO_HIGH);
|
||||
msleep(100);
|
||||
}
|
||||
else
|
||||
{
|
||||
gpio_direction_output(ts->pdata->reset_pin, GPIO_LOW);
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int ts_firmware(struct ts_private_data *ts)
|
||||
{
|
||||
int i = 0, j = 0;
|
||||
unsigned int ver_chk_cnt = 0;
|
||||
unsigned int flash_addr = 0;
|
||||
unsigned char CheckSum[16];
|
||||
unsigned char buf[32];
|
||||
char slave_addr = ts->ops->slave_addr;
|
||||
int ret = 0;
|
||||
|
||||
ret = ts_bulk_read_normal(ts, 1, buf, 200*1000);
|
||||
if (Binary_Data_Ct360[16372] <= buf[0] )
|
||||
{
|
||||
printk("%s:%s,firmware is new\n",__func__,ts->ops->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ts->ops->slave_addr = 0x7F;
|
||||
|
||||
//------------------------------
|
||||
// Step1 --> initial BootLoader
|
||||
// Note. 0x7F -> 0x00 -> 0xA5 ;
|
||||
// MCU goto idle
|
||||
//------------------------------
|
||||
printk("%s() Set mcu to idle \n", __FUNCTION__);
|
||||
buf[0] = 0x00;
|
||||
buf[1] = 0xA5;
|
||||
ts_bulk_write_normal(ts, 2, buf, 200*1000);
|
||||
mdelay(10);
|
||||
|
||||
//------------------------------
|
||||
// Reset I2C Offset address
|
||||
// Note. 0x7F -> 0x00
|
||||
//------------------------------
|
||||
printk("%s() Reset i2c offset address \n", __FUNCTION__);
|
||||
buf[0] = 0x00;
|
||||
ts_bulk_write_normal(ts, 1, buf, 200*1000);
|
||||
mdelay(10);
|
||||
|
||||
//------------------------------
|
||||
// Read I2C Bus status
|
||||
//------------------------------
|
||||
printk("%s() Read i2c bus status \n", __FUNCTION__);
|
||||
ts_bulk_read_normal(ts, 1, buf, 200*1000);
|
||||
mdelay(10); // Delay 1 ms
|
||||
|
||||
// if return "AAH" then going next step
|
||||
if (buf[0] != 0xAA)
|
||||
{
|
||||
printk("%s() i2c bus status: 0x%x \n", __FUNCTION__, buf[0]);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
//------------------------------
|
||||
// Check incomplete flash erase
|
||||
//------------------------------
|
||||
printk("%s() Flash erase verify \n", __FUNCTION__);
|
||||
buf[0] = 0x00;
|
||||
buf[1] = 0x99; // Generate check sum command -->read flash, set addr
|
||||
buf[2] = 0x00; // define a flash address for CT36x to generate check sum
|
||||
buf[3] = 0x00; //
|
||||
buf[4] = 0x08; // Define a data length for CT36x to generate check sum
|
||||
|
||||
// Write Genertate check sum command to CT36x
|
||||
ts_bulk_write_normal(ts, 5, buf, 200*1000);
|
||||
mdelay(10); // Delay 10 ms
|
||||
|
||||
ts_bulk_read_normal(ts, 13, buf, 200*1000);
|
||||
mdelay(10); // Delay 10 ms
|
||||
|
||||
CheckSum[0] = buf[5];
|
||||
CheckSum[1] = buf[6];
|
||||
|
||||
buf[0] = 0x00;
|
||||
buf[1] = 0x99; // Generate check sum command -->read flash, set addr
|
||||
buf[2] = 0x3F; // define a flash address for CT36x to generate check sum
|
||||
buf[3] = 0xE0; //
|
||||
buf[4] = 0x08; // Define a data length for CT36x to generate check sum
|
||||
// Write Genertate check sum command to CT36x
|
||||
ts_bulk_write_normal(ts, 5, buf, 200*1000);
|
||||
mdelay(10); // Delay 10 ms
|
||||
|
||||
ts_bulk_read_normal(ts, 13, buf, 200*1000);
|
||||
mdelay(10);
|
||||
|
||||
CheckSum[2] = buf[5];
|
||||
CheckSum[3] = buf[6];
|
||||
|
||||
if ( (CheckSum[0] ^ CheckSum[2]) == 0xFF && (CheckSum[1] ^ CheckSum[3]) == 0xFF )
|
||||
goto FLASH_ERASE;
|
||||
|
||||
//------------------------------
|
||||
// check valid Vendor ID
|
||||
//------------------------------
|
||||
printk("%s() Vendor ID Check \n", __FUNCTION__);
|
||||
buf[0] = 0x00;
|
||||
buf[1] = 0x99; // Generate check sum command -->read flash, set addr
|
||||
buf[2] = 0x00; // define a flash address for CT365 to generate check sum
|
||||
buf[3] = 0x44; //
|
||||
buf[4] = 0x08; // Define a data length for CT365 to generate check sum
|
||||
|
||||
// Write Genertate check sum command to CT36x
|
||||
ts_bulk_write_normal(ts, 5, buf, 200*1000);
|
||||
mdelay(10); // Delay 10 ms
|
||||
|
||||
ts_bulk_read_normal(ts, 13, buf, 200*1000);
|
||||
mdelay(10); // Delay 10 ms
|
||||
|
||||
// Read check sum and flash data from CT36x
|
||||
if ( (buf[5] != 'V') || (buf[9] != 'T') )
|
||||
ver_chk_cnt++;
|
||||
|
||||
buf[0] = 0x00;
|
||||
buf[1] = 0x99; // Generate check sum command -->read flash,set addr
|
||||
buf[2] = 0x00; // define a flash address for CT365 to generate check sum
|
||||
buf[3] = 0xA4; //
|
||||
buf[4] = 0x08; // Define a data length for CT365 to generate check sum
|
||||
|
||||
// Write Genertate check sum command to CT365
|
||||
ts_bulk_write_normal(ts, 5, buf, 200*1000);
|
||||
mdelay(10); // Delay 10 ms
|
||||
|
||||
ts_bulk_read_normal(ts, 13, buf, 200*1000);
|
||||
mdelay(10); // Delay 10 ms
|
||||
|
||||
if ((buf[5] != 'V') || (buf[9] != 'T'))
|
||||
ver_chk_cnt++;
|
||||
|
||||
if ( ver_chk_cnt >= 2 ) {
|
||||
printk("%s() Invalid FW Version \n", __FUNCTION__);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
FLASH_ERASE:
|
||||
//-----------------------------------------------------
|
||||
// Step 2 : Erase 32K flash memory via Mass Erase (33H)
|
||||
// 0x7F --> 0x00 --> 0x33 --> 0x00;
|
||||
//-----------------------------------------------------
|
||||
printk("%s() Erase flash \n", __FUNCTION__);
|
||||
for(i = 0; i < 8; i++ ) {
|
||||
buf[0] = 0x00; // Offset address
|
||||
buf[1] = 0x33; // Mass Erase command
|
||||
buf[2] = 0x00 + (i * 8);
|
||||
ts_bulk_write_normal(ts, 3, buf, 200*1000);
|
||||
mdelay(120); // Delay 10 mS
|
||||
|
||||
//------------------------------
|
||||
// Reset I2C Offset address
|
||||
// Note. 0x7F -> 0x00
|
||||
//------------------------------
|
||||
buf[0] = 0x00;
|
||||
ts_bulk_write_normal(ts, 1, buf, 200*1000);
|
||||
mdelay(120); // Delay 10 mS
|
||||
|
||||
//------------------------------
|
||||
// Read I2C Bus status
|
||||
//------------------------------
|
||||
ts_bulk_read_normal(ts, 1, buf, 200*1000);
|
||||
mdelay(10); // Delay 1 ms
|
||||
|
||||
// if return "AAH" then going next step
|
||||
if( buf[0] != 0xAA )
|
||||
{
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
// Step3. Host write 128 bytes to CT36x
|
||||
// Step4. Host read checksum to verify ;
|
||||
// Write/Read for 256 times ( 32k Bytes )
|
||||
//----------------------------------------
|
||||
printk("%s() flash FW start \n", __FUNCTION__);
|
||||
for ( flash_addr = 0; flash_addr < 0x3FFF; flash_addr+=8 ) {
|
||||
// Step 3 : write binary data to CT36x
|
||||
buf[0] = 0x00; // Offset address
|
||||
buf[1] = 0x55; // Flash write command
|
||||
buf[2] = (char)(flash_addr >> 8); // Flash address [15:8]
|
||||
buf[3] = (char)(flash_addr & 0xFF); // Flash address [7:0]
|
||||
buf[4] = 0x08; // Data Length
|
||||
|
||||
if( flash_addr == 160 || flash_addr == 168 ) {
|
||||
buf[6] = ~Binary_Data_Ct360[flash_addr + 0]; // Binary data 1
|
||||
buf[7] = ~Binary_Data_Ct360[flash_addr + 1]; // Binary data 2
|
||||
buf[8] = ~Binary_Data_Ct360[flash_addr + 2]; // Binary data 3
|
||||
buf[9] = ~Binary_Data_Ct360[flash_addr + 3]; // Binary data 4
|
||||
buf[10] = ~Binary_Data_Ct360[flash_addr + 4]; // Binary data 5
|
||||
buf[11] = ~Binary_Data_Ct360[flash_addr + 5]; // Binary data 6
|
||||
buf[12] = ~Binary_Data_Ct360[flash_addr + 6]; // Binary data 7
|
||||
buf[13] = ~Binary_Data_Ct360[flash_addr + 7]; // Binary data 8
|
||||
} else {
|
||||
buf[6] = Binary_Data_Ct360[flash_addr + 0]; // Binary data 1
|
||||
buf[7] = Binary_Data_Ct360[flash_addr + 1]; // Binary data 2
|
||||
buf[8] = Binary_Data_Ct360[flash_addr + 2]; // Binary data 3
|
||||
buf[9] = Binary_Data_Ct360[flash_addr + 3]; // Binary data 4
|
||||
buf[10] = Binary_Data_Ct360[flash_addr + 4]; // Binary data 5
|
||||
buf[11] = Binary_Data_Ct360[flash_addr + 5]; // Binary data 6
|
||||
buf[12] = Binary_Data_Ct360[flash_addr + 6]; // Binary data 7
|
||||
buf[13] = Binary_Data_Ct360[flash_addr + 7]; // Binary data 8
|
||||
}
|
||||
// Calculate a check sum by Host controller.
|
||||
// Checksum = / (FLASH_ADRH+FLASH_ADRL+LENGTH+
|
||||
// Binary_Data_Ct3601+Binary_Data_Ct3602+Binary_Data_Ct3603+Binary_Data_Ct3604+
|
||||
// Binary_Data_Ct3605+Binary_Data_Ct3606+Binary_Data_Ct3607+Binary_Data_Ct3608) + 1
|
||||
CheckSum[0] = ~(buf[2] + buf[3] + buf[4] + buf[6] + buf[7] +
|
||||
buf[8] + buf[9] + buf[10] + buf[11] + buf[12] +
|
||||
buf[13]) + 1;
|
||||
|
||||
buf[5] = CheckSum[0]; // Load check sum to I2C Buffer
|
||||
|
||||
ts_bulk_write_normal(ts, 14, buf, 200*1000); // Host write I2C_Buf[0?K12] to CT365.
|
||||
mdelay(1); // 8 Bytes program --> Need 1 ms delay time
|
||||
|
||||
// Step4. Verify process
|
||||
//printk("%s(flash_addr:0x%04x) Verify FW \n", __FUNCTION__, flash_addr);
|
||||
//Step 4 : Force CT365 generate check sum for host to compare data.
|
||||
//Prepare get check sum from CT36x
|
||||
buf[0] = 0x00;
|
||||
buf[1] = 0x99; // Generate check sum command
|
||||
buf[2] = (char)(flash_addr >> 8); // define a flash address for NT1100x to generate check sum
|
||||
buf[3] = (char)(flash_addr & 0xFF); //
|
||||
buf[4] = 0x08; // Define a data length for CT36x to generate check sum
|
||||
|
||||
ts_bulk_write_normal(ts, 5, buf, 200*1000); // Write Genertate check sum command to CT365
|
||||
mdelay(1); // Delay 1 ms
|
||||
|
||||
ts_bulk_read_normal(ts, 13, buf, 200*1000); // Read check sum and flash data from CT365
|
||||
|
||||
// Compare host check sum with CT365 check sum(I2C_Buf[4])
|
||||
if ( buf[4] != CheckSum[0] ) {
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
printk("%s() flash FW complete \n", __FUNCTION__);
|
||||
|
||||
exit:
|
||||
ts->ops->slave_addr = slave_addr;
|
||||
if(ts->ops->active)
|
||||
ts->ops->active(ts, 0);
|
||||
if(ts->ops->active)
|
||||
ts->ops->active(ts, 1);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int ts_init(struct ts_private_data *ts)
|
||||
{
|
||||
int irq_pin = irq_to_gpio(ts->pdata->irq);
|
||||
int result = 0;
|
||||
int uc_reg_value ;
|
||||
|
||||
|
||||
char loader_buf[3] = {0xfF,0x0f,0x2A};
|
||||
|
||||
gpio_direction_output(ts->pdata->reset_pin, GPIO_LOW);
|
||||
mdelay(10);
|
||||
gpio_direction_output(ts->pdata->reset_pin, GPIO_HIGH);
|
||||
msleep(300);
|
||||
|
||||
//init some register
|
||||
//to do
|
||||
ts_bulk_write_normal(ts, 3, loader_buf, 200*1000);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int ts_report_value(struct ts_private_data *ts)
|
||||
{
|
||||
struct ts_platform_data *pdata = ts->pdata;
|
||||
struct ts_event *event = &ts->event;
|
||||
unsigned char buf[20] = {0};
|
||||
int result = 0 , i = 0, off = 0, id = 0;
|
||||
int syn_flag = 0;
|
||||
|
||||
result = ts_bulk_read(ts, (unsigned short)ts->ops->read_reg, ts->ops->read_len, buf);
|
||||
if(result < 0)
|
||||
{
|
||||
printk("%s:fail to init ts\n",__func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
//for(i=0; i<ts->ops->read_len; i++)
|
||||
//DBG("buf[%d]=0x%x\n",i,buf[i]);
|
||||
|
||||
for(i = 0; i<ts->ops->max_point; i++)
|
||||
{
|
||||
off = i*4;
|
||||
id = buf[off] >> 4;
|
||||
event->point[id].id = id;
|
||||
event->point[id].status = buf[off+0] & 0x0f;
|
||||
event->point[id].x = (((s16)buf[i+1] << 4)|((s16)buf[i+3] >> 4));
|
||||
event->point[id].y = (((s16)buf[i+2] << 4)|((s16)buf[i+3] & 0x0f));
|
||||
|
||||
if(ts->ops->xy_swap)
|
||||
{
|
||||
swap(event->point[id].x, event->point[id].y);
|
||||
}
|
||||
|
||||
if(ts->ops->x_revert)
|
||||
{
|
||||
event->point[id].x = ts->ops->range[0] - event->point[id].x;
|
||||
}
|
||||
|
||||
if(ts->ops->y_revert)
|
||||
{
|
||||
event->point[id].y = ts->ops->range[1] - event->point[id].y;
|
||||
}
|
||||
|
||||
if((event->point[id].status == 1) || (event->point[id].status == 2))
|
||||
{
|
||||
input_mt_slot(ts->input_dev, event->point[id].id);
|
||||
input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, event->point[id].id);
|
||||
input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 1);
|
||||
input_report_abs(ts->input_dev, ABS_MT_POSITION_X, event->point[id].x);
|
||||
input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, event->point[id].y);
|
||||
input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 1);
|
||||
syn_flag = 1;
|
||||
DBG("%s:%s press down,id=%d,x=%d,y=%d\n",__func__,ts->ops->name, event->point[id].id, event->point[id].x,event->point[id].y);
|
||||
}
|
||||
else if ((event->point[id].status == 3) || (event->point[id].status == 0))
|
||||
{
|
||||
input_mt_slot(ts->input_dev, event->point[id].id);
|
||||
input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, -1);
|
||||
input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false);
|
||||
syn_flag = 1;
|
||||
DBG("%s:%s press up,id=%d\n",__func__,ts->ops->name, event->point[id].id);
|
||||
}
|
||||
|
||||
event->point[id].last_status = event->point[id].status;
|
||||
|
||||
}
|
||||
|
||||
if(syn_flag)
|
||||
{
|
||||
syn_flag = 0;
|
||||
input_sync(ts->input_dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ts_suspend(struct ts_private_data *ts)
|
||||
{
|
||||
struct ts_platform_data *pdata = ts->pdata;
|
||||
|
||||
if(ts->ops->active)
|
||||
ts->ops->active(ts, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int ts_resume(struct ts_private_data *ts)
|
||||
{
|
||||
struct ts_platform_data *pdata = ts->pdata;
|
||||
|
||||
if(ts->ops->active)
|
||||
ts->ops->active(ts, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct ts_operate ts_ct360_ops = {
|
||||
.name = "ct360",
|
||||
.slave_addr = 0x01,
|
||||
.ts_id = TS_ID_CT360, //i2c id number
|
||||
.bus_type = TS_BUS_TYPE_I2C,
|
||||
.reg_size = 1,
|
||||
.id_reg = CT360_ID_REG,
|
||||
.id_data = TS_UNKNOW_DATA,
|
||||
.version_reg = TS_UNKNOW_DATA,
|
||||
.version_len = 0,
|
||||
.version_data = NULL,
|
||||
.read_reg = CT360_DATA_REG, //read data
|
||||
.read_len = 4*5, //data length
|
||||
.trig = IRQF_TRIGGER_FALLING,
|
||||
.max_point = 5,
|
||||
.xy_swap = 0,
|
||||
.x_revert = 0,
|
||||
.y_revert = 0,
|
||||
.range = {800,480},
|
||||
.irq_enable = 1,
|
||||
.poll_delay_ms = 0,
|
||||
.active = ts_active,
|
||||
.init = ts_init,
|
||||
.check_irq = NULL,
|
||||
.report = ts_report_value,
|
||||
.firmware = ts_firmware,
|
||||
.suspend = ts_suspend,
|
||||
.resume = ts_resume,
|
||||
};
|
||||
|
||||
/****************operate according to ts chip:end************/
|
||||
|
||||
//function name should not be changed
|
||||
static struct ts_operate *ts_get_ops(void)
|
||||
{
|
||||
return &ts_ct360_ops;
|
||||
}
|
||||
|
||||
|
||||
static int __init ts_ct360_init(void)
|
||||
{
|
||||
struct ts_operate *ops = ts_get_ops();
|
||||
int result = 0;
|
||||
result = ts_register_slave(NULL, NULL, ts_get_ops);
|
||||
DBG("%s\n",__func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit ts_ct360_exit(void)
|
||||
{
|
||||
struct ts_operate *ops = ts_get_ops();
|
||||
ts_unregister_slave(NULL, NULL, ts_get_ops);
|
||||
}
|
||||
|
||||
|
||||
subsys_initcall(ts_ct360_init);
|
||||
module_exit(ts_ct360_exit);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,270 +0,0 @@
|
||||
/* drivers/input/ts/chips/ts_ft5306.c
|
||||
*
|
||||
* Copyright (C) 2012-2015 ROCKCHIP.
|
||||
* Author: luowei <lw@rock-chips.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* 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/interrupt.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <linux/input/mt.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/board.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/ts-auto.h>
|
||||
|
||||
|
||||
#if 0
|
||||
#define DBG(x...) printk(x)
|
||||
#else
|
||||
#define DBG(x...)
|
||||
#endif
|
||||
|
||||
|
||||
#define FT5306_ID_REG 0x00
|
||||
#define FT5306_DEVID 0x00
|
||||
#define FT5306_DATA_REG 0x00
|
||||
|
||||
|
||||
/****************operate according to ts chip:start************/
|
||||
|
||||
static int ts_active(struct ts_private_data *ts, int enable)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if(enable)
|
||||
{
|
||||
gpio_direction_output(ts->pdata->reset_pin, GPIO_LOW);
|
||||
msleep(10);
|
||||
gpio_direction_output(ts->pdata->reset_pin, GPIO_HIGH);
|
||||
msleep(100);
|
||||
}
|
||||
else
|
||||
{
|
||||
gpio_direction_output(ts->pdata->reset_pin, GPIO_LOW);
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int ts_init(struct ts_private_data *ts)
|
||||
{
|
||||
int irq_pin = irq_to_gpio(ts->pdata->irq);
|
||||
int result = 0;
|
||||
|
||||
gpio_direction_output(ts->pdata->reset_pin, GPIO_LOW);
|
||||
mdelay(10);
|
||||
gpio_direction_output(ts->pdata->reset_pin, GPIO_HIGH);
|
||||
msleep(100);
|
||||
|
||||
//init some register
|
||||
//to do
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int ts_report_value(struct ts_private_data *ts)
|
||||
{
|
||||
struct ts_platform_data *pdata = ts->pdata;
|
||||
struct ts_event *event = &ts->event;
|
||||
unsigned char buf[32] = {0};
|
||||
int result = 0 , i = 0, off = 0, id = 0;
|
||||
|
||||
result = ts_bulk_read(ts, (unsigned short)ts->ops->read_reg, ts->ops->read_len, (unsigned short *)buf);
|
||||
if(result < 0)
|
||||
{
|
||||
printk("%s:fail to init ts\n",__func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
//for(i=0; i<ts->ops->read_len; i++)
|
||||
//DBG("buf[%d]=0x%x\n",i,buf[i]);
|
||||
|
||||
event->touch_point = buf[2] & 0x07;// 0000 1111
|
||||
|
||||
for(i=0; i<ts->ops->max_point; i++)
|
||||
{
|
||||
event->point[i].status = 0;
|
||||
event->point[i].x = 0;
|
||||
event->point[i].y = 0;
|
||||
}
|
||||
|
||||
if(event->touch_point == 0)
|
||||
{
|
||||
for(i=0; i<ts->ops->max_point; i++)
|
||||
{
|
||||
if(event->point[i].last_status != 0)
|
||||
{
|
||||
event->point[i].last_status = 0;
|
||||
input_mt_slot(ts->input_dev, event->point[i].id);
|
||||
input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, -1);
|
||||
input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false);
|
||||
DBG("%s:%s press up,id=%d\n",__func__,ts->ops->name, event->point[i].id);
|
||||
}
|
||||
}
|
||||
|
||||
input_sync(ts->input_dev);
|
||||
memset(event, 0x00, sizeof(struct ts_event));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(i = 0; i<event->touch_point; i++)
|
||||
{
|
||||
off = i*6+3;
|
||||
id = (buf[off+2] & 0xf0) >> 4;
|
||||
event->point[id].id = id;
|
||||
event->point[id].status = (buf[off+0] & 0xc0) >> 6;
|
||||
event->point[id].x = ((buf[off+0] & 0x0f)<<8) | buf[off+1];
|
||||
event->point[id].y = ((buf[off+2] & 0x0f)<<8) | buf[off+3];
|
||||
|
||||
if(ts->ops->xy_swap)
|
||||
{
|
||||
swap(event->point[id].x, event->point[id].y);
|
||||
}
|
||||
|
||||
if(ts->ops->x_revert)
|
||||
{
|
||||
event->point[id].x = ts->ops->range[0] - event->point[id].x;
|
||||
}
|
||||
|
||||
if(ts->ops->y_revert)
|
||||
{
|
||||
event->point[id].y = ts->ops->range[1] - event->point[id].y;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for(i=0; i<ts->ops->max_point; i++)
|
||||
{
|
||||
if(event->point[i].status != 0)
|
||||
{
|
||||
input_mt_slot(ts->input_dev, event->point[i].id);
|
||||
input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, event->point[i].id);
|
||||
input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 1);
|
||||
input_report_abs(ts->input_dev, ABS_MT_POSITION_X, event->point[i].x);
|
||||
input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, event->point[i].y);
|
||||
input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 1);
|
||||
DBG("%s:%s press down,id=%d,x=%d,y=%d\n",__func__,ts->ops->name, event->point[id].id, event->point[id].x,event->point[id].y);
|
||||
}
|
||||
else if ((event->point[i].status == 0) && (event->point[i].last_status != 0))
|
||||
{
|
||||
input_mt_slot(ts->input_dev, event->point[i].id);
|
||||
input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, -1);
|
||||
input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false);
|
||||
DBG("%s:%s press up1,id=%d\n",__func__,ts->ops->name, event->point[i].id);
|
||||
}
|
||||
|
||||
event->point[i].last_status = event->point[i].status;
|
||||
}
|
||||
input_sync(ts->input_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ts_suspend(struct ts_private_data *ts)
|
||||
{
|
||||
struct ts_platform_data *pdata = ts->pdata;
|
||||
|
||||
if(ts->ops->active)
|
||||
ts->ops->active(ts, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static int ts_resume(struct ts_private_data *ts)
|
||||
{
|
||||
struct ts_platform_data *pdata = ts->pdata;
|
||||
|
||||
if(ts->ops->active)
|
||||
ts->ops->active(ts, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
struct ts_operate ts_ft5306_ops = {
|
||||
.name = "ft5306",
|
||||
.slave_addr = 0x3e,
|
||||
.ts_id = TS_ID_FT5306, //i2c id number
|
||||
.bus_type = TS_BUS_TYPE_I2C,
|
||||
.reg_size = 1,
|
||||
.id_reg = FT5306_ID_REG,
|
||||
.id_data = TS_UNKNOW_DATA,
|
||||
.version_reg = TS_UNKNOW_DATA,
|
||||
.version_len = 0,
|
||||
.version_data = NULL,
|
||||
.read_reg = FT5306_DATA_REG, //read data
|
||||
.read_len = 32, //data length
|
||||
.trig = IRQF_TRIGGER_FALLING,
|
||||
.max_point = 5,
|
||||
.xy_swap = 1,
|
||||
.x_revert = 1,
|
||||
.y_revert = 0,
|
||||
.range = {1024,768},
|
||||
.irq_enable = 1,
|
||||
.poll_delay_ms = 0,
|
||||
.active = ts_active,
|
||||
.init = ts_init,
|
||||
.check_irq = NULL,
|
||||
.report = ts_report_value,
|
||||
.firmware = NULL,
|
||||
.suspend = ts_suspend,
|
||||
.resume = ts_resume,
|
||||
};
|
||||
|
||||
/****************operate according to ts chip:end************/
|
||||
|
||||
//function name should not be changed
|
||||
static struct ts_operate *ts_get_ops(void)
|
||||
{
|
||||
return &ts_ft5306_ops;
|
||||
}
|
||||
|
||||
|
||||
static int __init ts_ft5306_init(void)
|
||||
{
|
||||
struct ts_operate *ops = ts_get_ops();
|
||||
int result = 0;
|
||||
result = ts_register_slave(NULL, NULL, ts_get_ops);
|
||||
DBG("%s\n",__func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit ts_ft5306_exit(void)
|
||||
{
|
||||
struct ts_operate *ops = ts_get_ops();
|
||||
ts_unregister_slave(NULL, NULL, ts_get_ops);
|
||||
}
|
||||
|
||||
|
||||
subsys_initcall(ts_ft5306_init);
|
||||
module_exit(ts_ft5306_exit);
|
||||
|
||||
@@ -1,374 +0,0 @@
|
||||
/* drivers/input/ts/chips/gt8110.c
|
||||
*
|
||||
* Copyright (C) 2012-2015 ROCKCHIP.
|
||||
* Author: luowei <lw@rock-chips.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* 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/interrupt.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <linux/input/mt.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/board.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/ts-auto.h>
|
||||
|
||||
|
||||
#if 0
|
||||
#define DBG(x...) printk(x)
|
||||
#else
|
||||
#define DBG(x...)
|
||||
#endif
|
||||
|
||||
#define PEN_DOWN 1
|
||||
#define PEN_RELEASE 0
|
||||
#define PEN_DOWN_UP 2 //from down to up
|
||||
|
||||
|
||||
#define GT8110_ID_REG 0x00
|
||||
#define GT8110_DATA_REG 0x00
|
||||
|
||||
|
||||
/****************operate according to ts chip:start************/
|
||||
|
||||
static int ts_active(struct ts_private_data *ts, int enable)
|
||||
{
|
||||
unsigned char buf_suspend[2] = {0x38, 0x56}; //suspend cmd
|
||||
int result = 0;
|
||||
|
||||
if(enable)
|
||||
{
|
||||
gpio_direction_output(ts->pdata->reset_pin, GPIO_LOW);
|
||||
mdelay(10);
|
||||
gpio_direction_output(ts->pdata->reset_pin, GPIO_HIGH);
|
||||
msleep(200);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = ts_bulk_write(ts, (unsigned short )buf_suspend[0], 2, (unsigned short *)&buf_suspend[1]);
|
||||
if(result < 0)
|
||||
{
|
||||
printk("%s:fail to init ts\n",__func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
gpio_direction_output(ts->pdata->reset_pin, GPIO_LOW);
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int ts_init(struct ts_private_data *ts)
|
||||
{
|
||||
int irq_pin = irq_to_gpio(ts->pdata->irq);
|
||||
char version_data[18] = {240};
|
||||
char init_data[95] = {
|
||||
0x65,0x02,0x00,0x10,0x00,0x10,0x0A,0x62,0x4A,0x00,
|
||||
0x0F,0x28,0x02,0x10,0x10,0x00,0x00,0x20,0x00,0x00,
|
||||
0x10,0x10,0x10,0x00,0x37,0x00,0x00,0x00,0x01,0x02,
|
||||
0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,
|
||||
0x0D,0xFF,0xFF,0x00,0x01,0x02,0x03,0x04,0x05,0x06,
|
||||
0x07,0x08,0x09,0x0A,0x0B,0x0C,0xFF,0xFF,0xFF,0x00,
|
||||
0x00,0x3C,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00
|
||||
};
|
||||
int result = 0, i = 0;
|
||||
|
||||
//read version
|
||||
result = ts_bulk_read(ts, (unsigned short)version_data[0], 16, (unsigned short *)&version_data[1]);
|
||||
if(result < 0)
|
||||
{
|
||||
printk("%s:fail to init ts\n",__func__);
|
||||
return result;
|
||||
}
|
||||
version_data[17]='\0';
|
||||
|
||||
printk("%s:%s version is %s\n",__func__,ts->ops->name, version_data);
|
||||
#if 1
|
||||
//init some register
|
||||
result = ts_bulk_write(ts, (unsigned short )init_data[0], 94, (unsigned short *)&init_data[1]);
|
||||
if(result < 0)
|
||||
{
|
||||
printk("%s:fail to init ts\n",__func__);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
result = ts_bulk_read(ts, (unsigned short)init_data[0], 94, (unsigned short *)&init_data[1]);
|
||||
if(result < 0)
|
||||
{
|
||||
printk("%s:fail to init ts\n",__func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
DBG("%s:rx:",__func__);
|
||||
for(i=0; i<95; i++)
|
||||
DBG("0x%x,",init_data[i]);
|
||||
|
||||
DBG("\n");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool goodix_get_status(int *p1,int*p2)
|
||||
{
|
||||
bool status = PEN_DOWN;
|
||||
if((*p2==PEN_DOWN) && (*p1==PEN_RELEASE))
|
||||
{
|
||||
*p2 = PEN_DOWN_UP; //<2F>ոյ<D5B8><D5B5><EFBFBD>
|
||||
status = PEN_RELEASE;
|
||||
}
|
||||
else if((*p2==PEN_RELEASE) && (*p1==PEN_RELEASE))
|
||||
{
|
||||
*p2 = PEN_RELEASE;
|
||||
status = PEN_RELEASE;
|
||||
}
|
||||
else
|
||||
{
|
||||
*p2 = PEN_DOWN;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int ts_check_irq(struct ts_private_data *ts)
|
||||
{
|
||||
struct ts_platform_data *pdata = ts->pdata;
|
||||
struct ts_event *event = &ts->event;
|
||||
int gpio_level_no_int = GPIO_HIGH;
|
||||
int id = 0, i = 0;
|
||||
|
||||
if((ts->ops->trig & IRQF_TRIGGER_LOW) || (ts->ops->trig & IRQF_TRIGGER_FALLING))
|
||||
gpio_level_no_int = GPIO_HIGH;
|
||||
else
|
||||
gpio_level_no_int = GPIO_LOW;
|
||||
|
||||
if(gpio_get_value(ts->pdata->irq) == gpio_level_no_int)
|
||||
{
|
||||
for(i = 0; i<ts->ops->max_point; i++)
|
||||
{
|
||||
id = i;
|
||||
if(event->point[id].last_status != 0)
|
||||
{
|
||||
event->point[i].last_status = PEN_RELEASE;
|
||||
input_mt_slot(ts->input_dev, event->point[i].id);
|
||||
input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, -1);
|
||||
input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false);
|
||||
DBG("%s:%s press up,id=%d\n\n",__func__,ts->ops->name, event->point[i].id);
|
||||
}
|
||||
}
|
||||
|
||||
input_sync(ts->input_dev);
|
||||
memset(event, 0x00, sizeof(struct ts_event));
|
||||
enable_irq(ts->irq);
|
||||
}
|
||||
else
|
||||
schedule_delayed_work(&ts->delaywork, msecs_to_jiffies(ts->ops->poll_delay_ms));
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int ts_report_value(struct ts_private_data *ts)
|
||||
{
|
||||
struct ts_platform_data *pdata = ts->pdata;
|
||||
struct ts_event *event = &ts->event;
|
||||
unsigned char buf[54] = {0};
|
||||
int result = 0 , i = 0, j = 0, off = 0, id = 0;
|
||||
int temp = 0, num = 0;
|
||||
|
||||
result = ts_bulk_read(ts, ts->ops->read_reg, ts->ops->read_len, (unsigned short *)buf);
|
||||
if(result < 0)
|
||||
{
|
||||
printk("%s:fail to init ts\n",__func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
//for(i=0; i<ts->ops->read_len; i++)
|
||||
//DBG("buf[%d]=0x%x\n",i,buf[i]);
|
||||
|
||||
temp = (buf[1] << 8) | buf[0];
|
||||
|
||||
for(i=0; i<ts->ops->max_point; i++)
|
||||
{
|
||||
if(temp & (1 << i))
|
||||
{
|
||||
event->point[i].status = PEN_DOWN;
|
||||
num++;
|
||||
}
|
||||
}
|
||||
|
||||
if(num > event->touch_point)
|
||||
event->touch_point = num;
|
||||
|
||||
for(i = 0; i<event->touch_point; i++)
|
||||
{
|
||||
off = 2 + i*4;
|
||||
|
||||
id = i;
|
||||
event->point[id].id = id;
|
||||
|
||||
if(goodix_get_status(&event->point[id].status,&event->point[id].last_status))
|
||||
{
|
||||
event->point[id].x = (unsigned int)(buf[off+1]<<8) + (unsigned int)buf[off+0];
|
||||
event->point[id].y = (unsigned int)(buf[off+3]<<8) + (unsigned int)buf[off+2];
|
||||
}
|
||||
|
||||
if((event->point[id].x <= 0) || (event->point[id].x >= ts->ops->range[0]) || (event->point[id].y <= 0) || (event->point[id].y >= ts->ops->range[1]))
|
||||
{
|
||||
event->point[id].status = 0;
|
||||
continue;
|
||||
}
|
||||
//for(j=0; j<(2 + (i+1)*4); j++)
|
||||
//DBG("buf[%d]=0x%x\n",j,buf[j]);
|
||||
|
||||
if(ts->ops->xy_swap)
|
||||
{
|
||||
swap(event->point[id].x, event->point[id].y);
|
||||
}
|
||||
|
||||
if(ts->ops->x_revert)
|
||||
{
|
||||
event->point[id].x = ts->ops->range[0] - event->point[id].x;
|
||||
}
|
||||
|
||||
if(ts->ops->y_revert)
|
||||
{
|
||||
event->point[id].y = ts->ops->range[1] - event->point[id].y;
|
||||
}
|
||||
|
||||
|
||||
if(event->point[id].status==PEN_DOWN_UP)
|
||||
{
|
||||
event->point[id].status=PEN_RELEASE;
|
||||
input_mt_slot(ts->input_dev, event->point[i].id);
|
||||
input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, -1);
|
||||
input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false);
|
||||
DBG("%s:%s press is uping,id=%d\n\n",__func__,ts->ops->name, event->point[i].id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(event->point[id].status==PEN_DOWN)
|
||||
{
|
||||
input_mt_slot(ts->input_dev, event->point[id].id);
|
||||
input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, event->point[id].id);
|
||||
input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 1);
|
||||
input_report_abs(ts->input_dev, ABS_MT_POSITION_X, event->point[id].x);
|
||||
input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, event->point[id].y);
|
||||
input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 1);
|
||||
DBG("%s:%s press down,id=%d,x=%d,y=%d\n\n",__func__,ts->ops->name, event->point[id].id, event->point[id].x,event->point[id].y);
|
||||
}
|
||||
|
||||
event->point[id].last_status = event->point[id].status;
|
||||
}
|
||||
|
||||
input_sync(ts->input_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ts_suspend(struct ts_private_data *ts)
|
||||
{
|
||||
struct ts_platform_data *pdata = ts->pdata;
|
||||
|
||||
if(ts->ops->active)
|
||||
ts->ops->active(ts, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int ts_resume(struct ts_private_data *ts)
|
||||
{
|
||||
struct ts_platform_data *pdata = ts->pdata;
|
||||
|
||||
if(ts->ops->active)
|
||||
ts->ops->active(ts, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct ts_operate ts_gt8110_ops = {
|
||||
.name = "gt8110",
|
||||
.slave_addr = 0x5c,
|
||||
.ts_id = TS_ID_GT8110, //i2c id number
|
||||
.bus_type = TS_BUS_TYPE_I2C,
|
||||
.reg_size = 1,
|
||||
.id_reg = GT8110_ID_REG,
|
||||
.id_data = TS_UNKNOW_DATA,
|
||||
.version_reg = TS_UNKNOW_DATA,
|
||||
.version_len = 0,
|
||||
.version_data = NULL,
|
||||
.read_reg = GT8110_DATA_REG, //read data
|
||||
.read_len = 5*10+3+1, //data length
|
||||
.trig = IRQ_TYPE_LEVEL_LOW,
|
||||
.max_point = 10,
|
||||
.xy_swap = 0,
|
||||
.x_revert = 0,
|
||||
.y_revert = 0,
|
||||
.range = {4096,4096},
|
||||
.irq_enable = 1,
|
||||
.poll_delay_ms = 30,
|
||||
.active = ts_active,
|
||||
.init = ts_init,
|
||||
.check_irq = ts_check_irq,
|
||||
.report = ts_report_value,
|
||||
.firmware = NULL,
|
||||
.suspend = ts_suspend,
|
||||
.resume = ts_resume,
|
||||
};
|
||||
|
||||
/****************operate according to ts chip:end************/
|
||||
|
||||
//function name should not be changed
|
||||
static struct ts_operate *ts_get_ops(void)
|
||||
{
|
||||
return &ts_gt8110_ops;
|
||||
}
|
||||
|
||||
|
||||
static int __init ts_gt8110_init(void)
|
||||
{
|
||||
struct ts_operate *ops = ts_get_ops();
|
||||
int result = 0;
|
||||
result = ts_register_slave(NULL, NULL, ts_get_ops);
|
||||
DBG("%s\n",__func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit ts_gt8110_exit(void)
|
||||
{
|
||||
struct ts_operate *ops = ts_get_ops();
|
||||
ts_unregister_slave(NULL, NULL, ts_get_ops);
|
||||
}
|
||||
|
||||
|
||||
subsys_initcall(ts_gt8110_init);
|
||||
module_exit(ts_gt8110_exit);
|
||||
|
||||
@@ -1,391 +0,0 @@
|
||||
/* drivers/input/ts/chips/gt828.c
|
||||
*
|
||||
* Copyright (C) 2012-2015 ROCKCHIP.
|
||||
* Author: luowei <lw@rock-chips.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* 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/interrupt.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <linux/input/mt.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/board.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/ts-auto.h>
|
||||
|
||||
|
||||
#if 0
|
||||
#define DBG(x...) printk(x)
|
||||
#else
|
||||
#define DBG(x...)
|
||||
#endif
|
||||
|
||||
|
||||
//Register define
|
||||
#define GTP_READ_COOR_ADDR 0x0F40
|
||||
#define GTP_REG_SLEEP 0x0FF2
|
||||
#define GTP_REG_SENSOR_ID 0x0FF5
|
||||
#define GTP_REG_CONFIG_DATA 0x0F80
|
||||
#define GTP_REG_VERSION 0x0F7D
|
||||
|
||||
#define GTP_CONFIG_LENGTH 112
|
||||
#define TRIGGER_LOC 64
|
||||
|
||||
//STEP_1(REQUIRED):Change config table.
|
||||
/*TODO: puts the config info corresponded to your TP here, the following is just
|
||||
a sample config, send this config should cause the chip cannot work normally*/
|
||||
//default or float
|
||||
|
||||
u8 cfg_info_group[][GTP_CONFIG_LENGTH] =
|
||||
{
|
||||
{
|
||||
0x00,0x0F,0x01,0x10,0x02,0x11,0x03,0x12,0x04,0x13,
|
||||
0x05,0x14,0x06,0x15,0x07,0x16,0x08,0x17,0x09,0x18,
|
||||
0x0A,0x19,0x0B,0x1A,0x0C,0x1B,0x0D,0x1C,0xFF,0xFF,
|
||||
0x02,0x0C,0x03,0x0D,0x04,0x0E,0x05,0x0F,0x06,0x10,
|
||||
0x07,0x11,0x08,0x12,0x09,0x13,0xFF,0x11,0x12,0x13,
|
||||
0x0F,0x03,0x88,0x10,0x10,0x2A,0x00,0x00,0x00,0x00,
|
||||
0x00,0x0E,0x45,0x30,0x58,0x03,0x00,0x05,0x00,0x02,
|
||||
0x58,0x03,0x20,0x55,0x5E,0x50,0x58,0x27,0x00,0x05,
|
||||
0x19,0x05,0x14,0x10,0x00,0x05,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x40,0x30,0x30,0x3C,0x00,0x00,0x00,0x00,
|
||||
0x0F,0x88,0x28,0x05,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x01
|
||||
},
|
||||
{
|
||||
0x00,0x0F,0x01,0x10,0x02,0x11,0x03,0x12,0x04,0x13,
|
||||
0x05,0x14,0x06,0x15,0x07,0x16,0x08,0x17,0x09,0x18,
|
||||
0x0A,0x19,0x0B,0x1A,0x0C,0x1B,0x0D,0x1C,0xFF,0xFF,
|
||||
0x02,0x0C,0x03,0x0D,0x04,0x0E,0x05,0x0F,0x06,0x10,
|
||||
0x07,0x11,0x08,0x12,0x09,0x13,0xFF,0x11,0x12,0x13,
|
||||
0x0F,0x03,0x88,0x10,0x10,0x2A,0x00,0x00,0x00,0x00,
|
||||
0x00,0x0E,0x45,0x30,0x58,0x03,0x00,0x05,0x00,0x02,
|
||||
0x58,0x03,0x20,0x55,0x5E,0x50,0x58,0x27,0x00,0x05,
|
||||
0x19,0x05,0x14,0x10,0x00,0x05,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x40,0x30,0x30,0x3C,0x00,0x00,0x00,0x00,
|
||||
0x0F,0x88,0x28,0x05,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x01
|
||||
},
|
||||
|
||||
{
|
||||
0x00,0x0F,0x01,0x10,0x02,0x11,0x03,0x12,0x04,0x13,
|
||||
0x05,0x14,0x06,0x15,0x07,0x16,0x08,0x17,0x09,0x18,
|
||||
0x0A,0x19,0x0B,0x1A,0x0C,0x1B,0x0D,0x1C,0xFF,0xFF,
|
||||
0x02,0x0C,0x03,0x0D,0x04,0x0E,0x05,0x0F,0x06,0x10,
|
||||
0x07,0x11,0x08,0x12,0x09,0x13,0xFF,0x11,0x12,0x13,
|
||||
0x0F,0x03,0x88,0x10,0x10,0x2A,0x00,0x00,0x00,0x00,
|
||||
0x00,0x0E,0x45,0x30,0x58,0x03,0x00,0x05,0x00,0x02,
|
||||
0x58,0x03,0x20,0x55,0x5E,0x50,0x58,0x27,0x00,0x05,
|
||||
0x19,0x05,0x14,0x10,0x00,0x05,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x40,0x30,0x30,0x3C,0x00,0x00,0x00,0x00,
|
||||
0x0F,0x88,0x28,0x05,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x01
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
static u8 config[GTP_CONFIG_LENGTH+2] = {GTP_REG_CONFIG_DATA >> 8, GTP_REG_CONFIG_DATA & 0xff};
|
||||
|
||||
|
||||
/****************operate according to ts chip:start************/
|
||||
|
||||
int ts_i2c_end_cmd(struct ts_private_data *ts)
|
||||
{
|
||||
int result = -1;
|
||||
char end_cmd_data[2]={0x80, 0x00};
|
||||
|
||||
result = ts_reg_write(ts, end_cmd_data[0], end_cmd_data[1]);
|
||||
if(result < 0)
|
||||
{
|
||||
printk("%s:fail to init ts\n",__func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int ts_active(struct ts_private_data *ts, int enable)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if(enable)
|
||||
{
|
||||
gpio_direction_output(ts->pdata->reset_pin, GPIO_LOW);
|
||||
msleep(10);
|
||||
gpio_direction_output(ts->pdata->reset_pin, GPIO_HIGH);
|
||||
msleep(100);
|
||||
}
|
||||
else
|
||||
{
|
||||
gpio_direction_output(ts->pdata->reset_pin, GPIO_LOW);
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int ts_init(struct ts_private_data *ts)
|
||||
{
|
||||
int result = 0;
|
||||
char version_data[5] = {ts->ops->version_reg >> 8, ts->ops->version_reg & 0xff};
|
||||
u8 rd_cfg_buf[2];
|
||||
|
||||
//init some register
|
||||
result = ts_bulk_read(ts, ts->ops->version_reg, 1, rd_cfg_buf);
|
||||
if(result < 0)
|
||||
{
|
||||
printk("%s:fail to read rd_cfg_buf\n",__func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = ts_i2c_end_cmd(ts);
|
||||
if(result < 0)
|
||||
{
|
||||
printk("%s:fail to end cmd\n",__func__);
|
||||
rd_cfg_buf[0] = 0;
|
||||
//return result;
|
||||
}
|
||||
|
||||
rd_cfg_buf[0] &= 0x03;
|
||||
|
||||
printk("%s:%s id is %d\n",__func__,ts->ops->name, rd_cfg_buf[0]);
|
||||
|
||||
memcpy(&config[2], cfg_info_group[rd_cfg_buf[0]], GTP_CONFIG_LENGTH);
|
||||
|
||||
if((ts->ops->trig & IRQF_TRIGGER_FALLING) || (ts->ops->trig & IRQF_TRIGGER_LOW)) //FALLING
|
||||
{
|
||||
config[TRIGGER_LOC+2] &= 0xf7;
|
||||
}
|
||||
else if((ts->ops->trig & IRQF_TRIGGER_RISING) || (ts->ops->trig & IRQF_TRIGGER_HIGH)) //RISING
|
||||
{
|
||||
config[TRIGGER_LOC+2] |= 0x08;
|
||||
}
|
||||
|
||||
result = ts_bulk_write(ts, GTP_REG_CONFIG_DATA, GTP_CONFIG_LENGTH, config);
|
||||
if(result < 0)
|
||||
{
|
||||
printk("%s:fail to send config data\n",__func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = ts_i2c_end_cmd(ts);
|
||||
if(result < 0)
|
||||
{
|
||||
printk("%s:fail to end cmd\n",__func__);
|
||||
//return result;
|
||||
}
|
||||
|
||||
//read version
|
||||
result = ts_bulk_read(ts, ts->ops->version_reg, 4, version_data);
|
||||
if(result < 0)
|
||||
{
|
||||
printk("%s:fail to init ts\n",__func__);
|
||||
return result;
|
||||
}
|
||||
version_data[4]='\0';
|
||||
|
||||
result = ts_i2c_end_cmd(ts);
|
||||
if(result < 0)
|
||||
{
|
||||
printk("%s:fail to end cmd\n",__func__);
|
||||
//return result;
|
||||
}
|
||||
|
||||
printk("%s:%s version is %s\n",__func__,ts->ops->name, version_data);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int ts_report_value(struct ts_private_data *ts)
|
||||
{
|
||||
struct ts_platform_data *pdata = ts->pdata;
|
||||
struct ts_event *event = &ts->event;
|
||||
unsigned char buf[2 + 2 + 5 * 5 + 1] = {0};
|
||||
int result = 0 , i = 0, off = 0, id = 0;
|
||||
int finger = 0;
|
||||
int checksum = 0;
|
||||
|
||||
result = ts_bulk_read(ts, ts->ops->read_reg, ts->ops->read_len, buf);
|
||||
if(result < 0)
|
||||
{
|
||||
printk("%s:fail to init ts\n",__func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = ts_i2c_end_cmd(ts);
|
||||
if(result < 0)
|
||||
{
|
||||
printk("%s:fail to end ts\n",__func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
//for(i=0; i<ts->ops->read_len; i++)
|
||||
//DBG("buf[%d]=0x%x\n",i,buf[i]);
|
||||
finger = buf[0];
|
||||
if((finger & 0x80) != 0x80)
|
||||
{
|
||||
DBG("%s:data not ready!,finger=0x%x\n",__func__,finger);
|
||||
//return -1;
|
||||
}
|
||||
|
||||
for(i = 0; i<ts->ops->max_point; i++)
|
||||
{
|
||||
off = i*5+2;
|
||||
|
||||
id = i;
|
||||
event->point[id].id = id;
|
||||
event->point[id].status = !!(finger & (1 << i));
|
||||
event->point[id].x = (buf[off+0]<<8) | buf[off+1];
|
||||
event->point[id].y = (buf[off+2]<<8) | buf[off+3];
|
||||
event->point[id].press = buf[off+4];
|
||||
|
||||
DBG("data:0x%x,0x%x,0x%x,0x%x\n",buf[off+0],buf[off+1],buf[off+2],buf[off+3]);
|
||||
|
||||
if(ts->ops->xy_swap)
|
||||
{
|
||||
swap(event->point[id].x, event->point[id].y);
|
||||
}
|
||||
|
||||
if(ts->ops->x_revert)
|
||||
{
|
||||
event->point[id].x = ts->ops->range[0] - event->point[id].x;
|
||||
}
|
||||
|
||||
if(ts->ops->y_revert)
|
||||
{
|
||||
event->point[id].y = ts->ops->range[1] - event->point[id].y;
|
||||
}
|
||||
|
||||
if(event->point[id].status != 0)
|
||||
{
|
||||
input_mt_slot(ts->input_dev, event->point[id].id);
|
||||
input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, event->point[id].id);
|
||||
input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, event->point[id].press);
|
||||
input_report_abs(ts->input_dev, ABS_MT_POSITION_X, event->point[id].x);
|
||||
input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, event->point[id].y);
|
||||
input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 1);
|
||||
DBG("%s:%s press down,id=%d,x=%d,y=%d\n",__func__,ts->ops->name, event->point[id].id, event->point[id].x,event->point[id].y);
|
||||
}
|
||||
else if ((event->point[id].status == 0) && (event->point[id].last_status != 0))
|
||||
{
|
||||
input_mt_slot(ts->input_dev, event->point[i].id);
|
||||
input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, -1);
|
||||
input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false);
|
||||
DBG("%s:%s press up,id=%d\n",__func__,ts->ops->name, event->point[i].id);
|
||||
}
|
||||
|
||||
event->point[i].last_status = event->point[i].status;
|
||||
|
||||
}
|
||||
|
||||
input_sync(ts->input_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ts_suspend(struct ts_private_data *ts)
|
||||
{
|
||||
struct ts_platform_data *pdata = ts->pdata;
|
||||
|
||||
if(ts->ops->active)
|
||||
ts->ops->active(ts, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static int ts_resume(struct ts_private_data *ts)
|
||||
{
|
||||
struct ts_platform_data *pdata = ts->pdata;
|
||||
|
||||
if(ts->ops->active)
|
||||
ts->ops->active(ts, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
struct ts_operate ts_gt828_ops = {
|
||||
.name = "gt828",
|
||||
.slave_addr = 0x5d,
|
||||
.ts_id = TS_ID_GT828, //i2c id number
|
||||
.bus_type = TS_BUS_TYPE_I2C,
|
||||
.reg_size = 2,
|
||||
.id_reg = GTP_REG_SENSOR_ID,
|
||||
.id_data = TS_UNKNOW_DATA,
|
||||
.version_reg = 0x0F7D,
|
||||
.version_len = 0,
|
||||
.version_data = NULL,
|
||||
.read_reg = GTP_READ_COOR_ADDR, //read data
|
||||
.read_len = 2 + 2 + 5 * 5 + 1, //data length
|
||||
.trig = IRQF_TRIGGER_FALLING,
|
||||
.max_point = 5,
|
||||
.xy_swap = 0,
|
||||
.x_revert = 0,
|
||||
.y_revert = 0,
|
||||
.range = {800,1280},
|
||||
.irq_enable = 1,
|
||||
.poll_delay_ms = 0,
|
||||
.active = ts_active,
|
||||
.init = ts_init,
|
||||
.check_irq = NULL,
|
||||
.report = ts_report_value,
|
||||
.firmware = NULL,
|
||||
.suspend = ts_suspend,
|
||||
.resume = ts_resume,
|
||||
};
|
||||
|
||||
/****************operate according to ts chip:end************/
|
||||
|
||||
//function name should not be changed
|
||||
static struct ts_operate *ts_get_ops(void)
|
||||
{
|
||||
return &ts_gt828_ops;
|
||||
}
|
||||
|
||||
|
||||
static int __init ts_gt828_init(void)
|
||||
{
|
||||
struct ts_operate *ops = ts_get_ops();
|
||||
int result = 0;
|
||||
result = ts_register_slave(NULL, NULL, ts_get_ops);
|
||||
DBG("%s\n",__func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit ts_gt828_exit(void)
|
||||
{
|
||||
struct ts_operate *ops = ts_get_ops();
|
||||
ts_unregister_slave(NULL, NULL, ts_get_ops);
|
||||
}
|
||||
|
||||
|
||||
subsys_initcall(ts_gt828_init);
|
||||
module_exit(ts_gt828_exit);
|
||||
|
||||
@@ -1,610 +0,0 @@
|
||||
/* drivers/input/ts/ts-auto.c - handle all touchscreen in this file
|
||||
*
|
||||
* Copyright (C) 2012-2015 ROCKCHIP.
|
||||
* Author: luowei <lw@rock-chips.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* 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/interrupt.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <linux/input/mt.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/board.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
|
||||
#include <linux/ts-auto.h>
|
||||
|
||||
|
||||
#if 0
|
||||
#define DBG(x...) printk(x)
|
||||
#else
|
||||
#define DBG(x...)
|
||||
#endif
|
||||
|
||||
struct ts_private_data *g_ts;
|
||||
static struct class *g_ts_class;
|
||||
static struct ts_operate *g_ts_ops[TS_NUM_ID];
|
||||
|
||||
|
||||
/**
|
||||
* ts_reg_read: Read a single ts register.
|
||||
*
|
||||
* @ts: Device to read from.
|
||||
* @reg: Register to read.
|
||||
*/
|
||||
int ts_reg_read(struct ts_private_data *ts, unsigned short reg)
|
||||
{
|
||||
unsigned short val;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ts->io_lock);
|
||||
|
||||
ret = ts->read_dev(ts, reg, ts->ops->reg_size, &val, ts->ops->reg_size);
|
||||
|
||||
mutex_unlock(&ts->io_lock);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
else
|
||||
return val;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ts_reg_read);
|
||||
|
||||
/**
|
||||
* ts_bulk_read: Read multiple ts registers
|
||||
*
|
||||
* @ts: Device to read from
|
||||
* @reg: First register
|
||||
* @count: Number of registers
|
||||
* @buf: Buffer to fill.
|
||||
*/
|
||||
int ts_bulk_read(struct ts_private_data *ts, unsigned short reg,
|
||||
int count, unsigned char *buf)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ts->io_lock);
|
||||
|
||||
ret = ts->read_dev(ts, reg, count, buf, ts->ops->reg_size);
|
||||
|
||||
mutex_unlock(&ts->io_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ts_bulk_read);
|
||||
|
||||
|
||||
/**
|
||||
* ts_reg_write: Write a single ts register.
|
||||
*
|
||||
* @ts: Device to write to.
|
||||
* @reg: Register to write to.
|
||||
* @val: Value to write.
|
||||
*/
|
||||
int ts_reg_write(struct ts_private_data *ts, unsigned short reg,
|
||||
unsigned short val)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ts->io_lock);
|
||||
|
||||
ret = ts->write_dev(ts, reg, ts->ops->reg_size, &val, ts->ops->reg_size);
|
||||
|
||||
mutex_unlock(&ts->io_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ts_reg_write);
|
||||
|
||||
|
||||
int ts_bulk_write(struct ts_private_data *ts, unsigned short reg,
|
||||
int count, unsigned char *buf)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ts->io_lock);
|
||||
|
||||
ret = ts->write_dev(ts, reg, count, buf, ts->ops->reg_size);
|
||||
|
||||
mutex_unlock(&ts->io_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ts_bulk_write);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* ts_set_bits: Set the value of a bitfield in a ts register
|
||||
*
|
||||
* @ts: Device to write to.
|
||||
* @reg: Register to write to.
|
||||
* @mask: Mask of bits to set.
|
||||
* @val: Value to set (unshifted)
|
||||
*/
|
||||
int ts_set_bits(struct ts_private_data *ts, unsigned short reg,
|
||||
unsigned short mask, unsigned short val)
|
||||
{
|
||||
int ret;
|
||||
u16 r;
|
||||
|
||||
mutex_lock(&ts->io_lock);
|
||||
|
||||
ret = ts->read_dev(ts, reg, ts->ops->reg_size, &r, ts->ops->reg_size);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
r &= ~mask;
|
||||
r |= val;
|
||||
|
||||
ret = ts->write_dev(ts, reg, ts->ops->reg_size, &r, ts->ops->reg_size);
|
||||
|
||||
out:
|
||||
mutex_unlock(&ts->io_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ts_set_bits);
|
||||
|
||||
static int ts_get_id(struct ts_operate *ops, struct ts_private_data *ts, int *value)
|
||||
{
|
||||
int result = 0;
|
||||
char temp[4] = {ops->id_reg & 0xff};
|
||||
int i = 0;
|
||||
|
||||
DBG("%s:start\n",__func__);
|
||||
if(ops->id_reg >= 0)
|
||||
{
|
||||
for(i=0; i<2; i++)
|
||||
{
|
||||
if(ops->reg_size == 2)
|
||||
{
|
||||
temp[0] = ops->id_reg >> 8;
|
||||
temp[1] = ops->id_reg & 0xff;
|
||||
result = ts->read_dev(ts, ops->id_reg, 2, temp, ops->reg_size);
|
||||
*value = (temp[0] << 8) | temp[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
result = ts->read_dev(ts, ops->id_reg, 1, temp, ops->reg_size);
|
||||
*value = temp[0];
|
||||
}
|
||||
if(!result)
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
if((ops->id_data != TS_UNKNOW_DATA)&&(ops->id_data != *value))
|
||||
{
|
||||
printk("%s:id=0x%x is not 0x%x\n",__func__,*value, ops->id_data);
|
||||
result = -1;
|
||||
}
|
||||
|
||||
DBG("%s:devid=0x%x\n",__func__,*value);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int ts_get_version(struct ts_operate *ops, struct ts_private_data *ts)
|
||||
{
|
||||
int result = 0;
|
||||
char temp[TS_MAX_VER_LEN + 1] = {0};
|
||||
int i = 0;
|
||||
|
||||
DBG("%s:start\n",__func__);
|
||||
|
||||
if(ops->version_reg >= 0)
|
||||
{
|
||||
if((ops->version_len < 0) || (ops->version_len > TS_MAX_VER_LEN))
|
||||
{
|
||||
printk("%s:version_len %d is error\n",__func__,ops->version_len);
|
||||
ops->version_len = TS_MAX_VER_LEN;
|
||||
}
|
||||
|
||||
result = ts->read_dev(ts, ops->version_reg, ops->version_len, temp, ops->reg_size);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
if(ops->version_data)
|
||||
{
|
||||
for(i=0; i<ops->version_len; i++)
|
||||
{
|
||||
if(temp[i] == ops->version_data[i])
|
||||
continue;
|
||||
printk("%s:version %s is not %s\n",__func__,temp, ops->version_data);
|
||||
result = -1;
|
||||
}
|
||||
}
|
||||
|
||||
DBG("%s:%s version: %s\n",__func__,ops->name, temp);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int ts_chip_init(struct ts_private_data *ts, int type)
|
||||
{
|
||||
struct ts_operate *ops = NULL;
|
||||
int result = 0;
|
||||
int i = 0;
|
||||
|
||||
if((type <= TS_BUS_TYPE_INVALID) || (type >= TS_BUS_TYPE_NUM_ID))
|
||||
{
|
||||
printk("%s:type=%d is error\n",__func__,type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(ts->pdata->init_platform_hw)
|
||||
ts->pdata->init_platform_hw();
|
||||
|
||||
for(i=TS_ID_INVALID+1; i<TS_NUM_ID; i++)
|
||||
{
|
||||
ops = g_ts_ops[i];
|
||||
if(!ops)
|
||||
{
|
||||
printk("%s:error:%p\n",__func__,ops);
|
||||
result = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(ops->bus_type == type)
|
||||
{
|
||||
|
||||
if(!ops->init || !ops->report)
|
||||
{
|
||||
printk("%s:error:%p,%p\n",__func__,ops->init,ops->report);
|
||||
result = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
ts->ops = ops; //save ops
|
||||
|
||||
result = ts_get_id(ops, ts, &ts->devid);//get id
|
||||
if(result < 0)
|
||||
{
|
||||
printk("%s:fail to read %s devid:0x%x\n",__func__, ops->name, ts->devid);
|
||||
continue;
|
||||
}
|
||||
|
||||
result = ts_get_version(ops, ts); //get version
|
||||
if(result < 0)
|
||||
{
|
||||
printk("%s:fail to read %s version\n",__func__, ops->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
result = ops->init(ts);
|
||||
if(result < 0)
|
||||
{
|
||||
printk("%s:fail to init ts\n",__func__);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(ops->firmware)
|
||||
{
|
||||
result = ops->firmware(ts);
|
||||
if(result < 0)
|
||||
{
|
||||
printk("%s:fail to updata firmware ts\n",__func__);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
printk("%s:%s devid:0x%x\n",__func__, ts->ops->name, ts->devid);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
static int ts_get_data(struct ts_private_data *ts)
|
||||
{
|
||||
return ts->ops->report(ts);
|
||||
}
|
||||
|
||||
|
||||
static void ts_delaywork_func(struct work_struct *work)
|
||||
{
|
||||
struct delayed_work *delaywork = container_of(work, struct delayed_work, work);
|
||||
struct ts_private_data *ts = container_of(delaywork, struct ts_private_data, delaywork);
|
||||
|
||||
mutex_lock(&ts->ts_lock);
|
||||
if (ts_get_data(ts) < 0)
|
||||
DBG(KERN_ERR "%s: Get data failed\n",__func__);
|
||||
|
||||
if(!ts->ops->irq_enable)//restart work while polling
|
||||
schedule_delayed_work(&ts->delaywork, msecs_to_jiffies(ts->ops->poll_delay_ms));
|
||||
else
|
||||
{
|
||||
if(ts->ops->check_irq)
|
||||
{
|
||||
ts->ops->check_irq(ts);
|
||||
}
|
||||
else
|
||||
{
|
||||
if((ts->ops->trig & IRQF_TRIGGER_LOW) || (ts->ops->trig & IRQF_TRIGGER_HIGH))
|
||||
enable_irq(ts->irq);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&ts->ts_lock);
|
||||
|
||||
DBG("%s:%s\n",__func__,ts->i2c_id->name);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a threaded IRQ handler so can access I2C/SPI. Since all
|
||||
* interrupts are clear on read the IRQ line will be reasserted and
|
||||
* the physical IRQ will be handled again if another interrupt is
|
||||
* asserted while we run - in the normal course of events this is a
|
||||
* rare occurrence so we save I2C/SPI reads. We're also assuming that
|
||||
* it's rare to get lots of interrupts firing simultaneously so try to
|
||||
* minimise I/O.
|
||||
*/
|
||||
static irqreturn_t ts_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct ts_private_data *ts = (struct ts_private_data *)dev_id;
|
||||
|
||||
//use threaded IRQ
|
||||
//if (ts_get_data(ts->client) < 0)
|
||||
// DBG(KERN_ERR "%s: Get data failed\n",__func__);
|
||||
//msleep(ts->ops->poll_delay_ms);
|
||||
if(ts->ops->check_irq)
|
||||
{
|
||||
disable_irq_nosync(irq);
|
||||
}
|
||||
else
|
||||
{
|
||||
if((ts->ops->trig & IRQF_TRIGGER_LOW) || (ts->ops->trig & IRQF_TRIGGER_HIGH))
|
||||
disable_irq_nosync(irq);
|
||||
}
|
||||
schedule_delayed_work(&ts->delaywork, msecs_to_jiffies(ts->ops->poll_delay_ms));
|
||||
DBG("%s:irq=%d\n",__func__,irq);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
||||
static int ts_irq_init(struct ts_private_data *ts)
|
||||
{
|
||||
int result = 0;
|
||||
int irq;
|
||||
if((ts->ops->irq_enable)&&(ts->ops->trig != TS_UNKNOW_DATA))
|
||||
{
|
||||
INIT_DELAYED_WORK(&ts->delaywork, ts_delaywork_func);
|
||||
if(ts->ops->poll_delay_ms < 0)
|
||||
ts->ops->poll_delay_ms = 30;
|
||||
|
||||
//result = gpio_request(ts->irq, ts->i2c_id->name);
|
||||
//if (result)
|
||||
//{
|
||||
// printk("%s:fail to request gpio :%d\n",__func__,ts->irq);
|
||||
//}
|
||||
|
||||
gpio_pull_updown(ts->irq, PullEnable);
|
||||
irq = gpio_to_irq(ts->irq);
|
||||
result = request_irq(irq, ts_interrupt, ts->ops->trig, ts->ops->name, ts);
|
||||
//result = request_threaded_irq(irq, NULL, ts_interrupt, ts->ops->trig, ts->ops->name, ts);
|
||||
if (result) {
|
||||
printk(KERN_ERR "%s:fail to request irq = %d, ret = 0x%x\n",__func__, irq, result);
|
||||
goto error;
|
||||
}
|
||||
ts->irq = irq;
|
||||
printk("%s:use irq=%d\n",__func__,irq);
|
||||
}
|
||||
else if(!ts->ops->irq_enable)
|
||||
{
|
||||
INIT_DELAYED_WORK(&ts->delaywork, ts_delaywork_func);
|
||||
if(ts->ops->poll_delay_ms < 0)
|
||||
ts->ops->poll_delay_ms = 30;
|
||||
|
||||
schedule_delayed_work(&ts->delaywork, msecs_to_jiffies(ts->ops->poll_delay_ms));
|
||||
printk("%s:use polling,delay=%d ms\n",__func__,ts->ops->poll_delay_ms);
|
||||
}
|
||||
|
||||
error:
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int ts_device_init(struct ts_private_data *ts, int type, int irq)
|
||||
{
|
||||
struct ts_platform_data *pdata = ts->dev->platform_data;
|
||||
int result = -1, i;
|
||||
|
||||
mutex_init(&ts->io_lock);
|
||||
mutex_init(&ts->ts_lock);
|
||||
dev_set_drvdata(ts->dev, ts);
|
||||
|
||||
ts->pdata = pdata;
|
||||
result = ts_chip_init(ts, type);
|
||||
if(result < 0)
|
||||
{
|
||||
printk("%s:touch screen with bus type %d is not exist\n",__func__,type);
|
||||
goto out_free_memory;
|
||||
}
|
||||
|
||||
ts->input_dev = input_allocate_device();
|
||||
if (!ts->input_dev) {
|
||||
result = -ENOMEM;
|
||||
dev_err(ts->dev,
|
||||
"Failed to allocate input device %s\n", ts->input_dev->name);
|
||||
goto out_free_memory;
|
||||
}
|
||||
|
||||
ts->input_dev->dev.parent = ts->dev;
|
||||
ts->input_dev->name = ts->ops->name;
|
||||
|
||||
result = input_register_device(ts->input_dev);
|
||||
if (result) {
|
||||
dev_err(ts->dev,
|
||||
"Unable to register input device %s\n", ts->input_dev->name);
|
||||
goto out_input_register_device_failed;
|
||||
}
|
||||
|
||||
result = ts_irq_init(ts);
|
||||
if (result) {
|
||||
dev_err(ts->dev,
|
||||
"fail to init ts irq,ret=%d\n",result);
|
||||
goto out_input_register_device_failed;
|
||||
}
|
||||
|
||||
__set_bit(EV_ABS, ts->input_dev->evbit);
|
||||
__set_bit(EV_KEY, ts->input_dev->evbit);
|
||||
__set_bit(EV_REP, ts->input_dev->evbit);
|
||||
__set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit);
|
||||
set_bit(ABS_MT_POSITION_X, ts->input_dev->absbit);
|
||||
set_bit(ABS_MT_POSITION_Y, ts->input_dev->absbit);
|
||||
set_bit(ABS_MT_TOUCH_MAJOR, ts->input_dev->absbit);
|
||||
set_bit(ABS_MT_WIDTH_MAJOR, ts->input_dev->absbit);
|
||||
|
||||
if(ts->ops->max_point <= 0)
|
||||
ts->ops->max_point = 1;
|
||||
|
||||
input_mt_init_slots(ts->input_dev, ts->ops->max_point);
|
||||
|
||||
if((ts->ops->range[0] <= 0) || (ts->ops->range[1] <= 0))
|
||||
{
|
||||
ts->ops->range[0] = 1024;
|
||||
ts->ops->range[1] = 600;
|
||||
}
|
||||
|
||||
input_set_abs_params(ts->input_dev,ABS_MT_POSITION_X, 0, ts->ops->range[0], 0, 0);
|
||||
input_set_abs_params(ts->input_dev,ABS_MT_POSITION_Y, 0, ts->ops->range[1], 0, 0);
|
||||
input_set_abs_params(ts->input_dev,ABS_MT_TOUCH_MAJOR, 0, 10, 0, 0);
|
||||
input_set_abs_params(ts->input_dev,ABS_MT_WIDTH_MAJOR, 0, 10, 0, 0);
|
||||
|
||||
g_ts = ts;
|
||||
|
||||
printk("%s:initialized ok,ts name:%s,devid=%d\n\n",__func__,ts->ops->name,ts->devid);
|
||||
|
||||
return result;
|
||||
|
||||
out_misc_device_register_device_failed:
|
||||
input_unregister_device(ts->input_dev);
|
||||
out_input_register_device_failed:
|
||||
input_free_device(ts->input_dev);
|
||||
out_free_memory:
|
||||
kfree(ts);
|
||||
|
||||
printk("%s:line=%d\n",__func__,__LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void ts_device_exit(struct ts_private_data *ts)
|
||||
{
|
||||
if(!ts->ops->irq_enable)
|
||||
cancel_delayed_work_sync(&ts->delaywork);
|
||||
input_unregister_device(ts->input_dev);
|
||||
input_free_device(ts->input_dev);
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
if((ts->ops->suspend) && (ts->ops->resume))
|
||||
unregister_early_suspend(&ts->early_suspend);
|
||||
#endif
|
||||
kfree(ts);
|
||||
}
|
||||
|
||||
|
||||
int ts_device_suspend(struct ts_private_data *ts)
|
||||
{
|
||||
if(ts->ops->suspend)
|
||||
ts->ops->suspend(ts);
|
||||
|
||||
if(ts->ops->irq_enable)
|
||||
disable_irq_nosync(ts->irq);
|
||||
else
|
||||
cancel_delayed_work_sync(&ts->delaywork);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int ts_device_resume(struct ts_private_data *ts)
|
||||
{
|
||||
if(ts->ops->resume)
|
||||
ts->ops->resume(ts);
|
||||
|
||||
if(ts->ops->irq_enable)
|
||||
enable_irq(ts->irq);
|
||||
else
|
||||
{
|
||||
PREPARE_DELAYED_WORK(&ts->delaywork, ts_delaywork_func);
|
||||
schedule_delayed_work(&ts->delaywork, msecs_to_jiffies(ts->ops->poll_delay_ms));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int ts_register_slave(struct ts_private_data *ts,
|
||||
struct ts_platform_data *slave_pdata,
|
||||
struct ts_operate *(*get_ts_ops)(void))
|
||||
{
|
||||
int result = 0;
|
||||
struct ts_operate *ops = get_ts_ops();
|
||||
if((ops->ts_id >= TS_NUM_ID) || (ops->ts_id <= TS_ID_INVALID))
|
||||
{
|
||||
printk("%s:%s id is error %d\n", __func__, ops->name, ops->ts_id);
|
||||
return -1;
|
||||
}
|
||||
g_ts_ops[ops->ts_id] = ops;
|
||||
printk("%s:%s,id=%d\n",__func__,g_ts_ops[ops->ts_id]->name, ops->ts_id);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int ts_unregister_slave(struct ts_private_data *ts,
|
||||
struct ts_platform_data *slave_pdata,
|
||||
struct ts_operate *(*get_ts_ops)(void))
|
||||
{
|
||||
int result = 0;
|
||||
struct ts_operate *ops = get_ts_ops();
|
||||
if((ops->ts_id >= TS_NUM_ID) || (ops->ts_id <= TS_ID_INVALID))
|
||||
{
|
||||
printk("%s:%s id is error %d\n", __func__, ops->name, ops->ts_id);
|
||||
return -1;
|
||||
}
|
||||
printk("%s:%s,id=%d\n",__func__,g_ts_ops[ops->ts_id]->name, ops->ts_id);
|
||||
g_ts_ops[ops->ts_id] = NULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
MODULE_AUTHOR("ROCKCHIP Corporation:lw@rock-chips.com");
|
||||
MODULE_DESCRIPTION("device interface for auto touch screen");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
|
||||
@@ -1,302 +0,0 @@
|
||||
/* drivers/input/ts/ts-i2c.c - touchscreen i2c handle
|
||||
*
|
||||
* Copyright (C) 2012-2015 ROCKCHIP.
|
||||
* Author: luowei <lw@rock-chips.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* 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/interrupt.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/board.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/ts-auto.h>
|
||||
|
||||
#define TS_I2C_RATE 200*1000
|
||||
|
||||
#if 0
|
||||
#define TS_DEBUG_ENABLE
|
||||
#define DBG(x...) printk(x)
|
||||
#else
|
||||
#define DBG(x...)
|
||||
#endif
|
||||
|
||||
|
||||
static int ts_i2c_read_device(struct ts_private_data *ts, unsigned short reg,
|
||||
int bytes, void *dest, int reg_size)
|
||||
{
|
||||
struct i2c_client *client = ts->control_data;
|
||||
struct i2c_adapter *i2c_adap = client->adapter;
|
||||
struct i2c_msg msgs[2];
|
||||
int i,res;
|
||||
|
||||
if (!dest || !i2c_adap) {
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
client->addr = ts->ops->slave_addr;
|
||||
|
||||
msgs[0].addr = client->addr;
|
||||
msgs[0].flags = 0; /* write */
|
||||
msgs[0].buf = (unsigned char *)®
|
||||
if(reg_size == 2)
|
||||
msgs[0].len = 2;
|
||||
else
|
||||
msgs[0].len = 1;
|
||||
msgs[0].scl_rate = TS_I2C_RATE;
|
||||
|
||||
msgs[1].addr = client->addr;
|
||||
msgs[1].flags = I2C_M_RD;
|
||||
msgs[1].buf = dest;
|
||||
msgs[1].len = bytes;
|
||||
msgs[1].scl_rate = TS_I2C_RATE;
|
||||
|
||||
res = i2c_transfer(i2c_adap, msgs, 2);
|
||||
if (res == 2)
|
||||
return 0;
|
||||
else if(res == 0)
|
||||
return -EBUSY;
|
||||
else
|
||||
return res;
|
||||
|
||||
#ifdef TS_DEBUG_ENABLE
|
||||
DBG("%s:reg=0x%x,len=%d,rxdata:",__func__, reg, bytes);
|
||||
for(i=0; i<bytes; i++)
|
||||
DBG("0x%x,",(unsigned char *)dest[i]);
|
||||
DBG("\n");
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* Currently we allocate the write buffer on the stack; this is OK for
|
||||
* small writes - if we need to do large writes this will need to be
|
||||
* revised.
|
||||
*/
|
||||
static int ts_i2c_write_device(struct ts_private_data *ts, unsigned short reg,
|
||||
int bytes, void *src, int reg_size)
|
||||
{
|
||||
struct i2c_client *client = ts->control_data;
|
||||
struct i2c_adapter *i2c_adap = client->adapter;
|
||||
struct i2c_msg msgs[1];
|
||||
int res;
|
||||
unsigned char buf[bytes + 2];
|
||||
|
||||
if (!src || !i2c_adap) {
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
client->addr = ts->ops->slave_addr;
|
||||
|
||||
if(ts->ops->reg_size == 2)
|
||||
{
|
||||
buf[0] = (reg & 0xff00) >> 8;
|
||||
buf[1] = (reg & 0x00ff) & 0xff;
|
||||
memcpy(&buf[2], src, bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
buf[0] = reg & 0xff;
|
||||
memcpy(&buf[1], src, bytes);
|
||||
}
|
||||
|
||||
#ifdef TS_DEBUG_ENABLE
|
||||
int i = 0;
|
||||
DBG("%s:reg=0x%x,len=%d,txdata:",__func__, reg, bytes);
|
||||
for(i=0; i<length; i++)
|
||||
DBG("0x%x,",buf[i]);
|
||||
DBG("\n");
|
||||
#endif
|
||||
|
||||
if (!src || !i2c_adap) {
|
||||
printk("%s:line=%d,error\n",__func__,__LINE__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
msgs[0].addr = client->addr;
|
||||
msgs[0].flags = 0; /* write */
|
||||
msgs[0].buf = buf;
|
||||
if(ts->ops->reg_size == 2)
|
||||
msgs[0].len = bytes+2;
|
||||
else
|
||||
msgs[0].len = bytes+1;
|
||||
msgs[0].scl_rate = TS_I2C_RATE;
|
||||
|
||||
res = i2c_transfer(i2c_adap, msgs, 1);
|
||||
if (res == 1)
|
||||
return 0;
|
||||
else if(res == 0)
|
||||
return -EBUSY;
|
||||
else
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
int ts_bulk_read_normal(struct ts_private_data *ts,
|
||||
int count, unsigned char *buf, int rate)
|
||||
{
|
||||
int ret;
|
||||
unsigned short reg;
|
||||
struct i2c_client *client = ts->control_data;
|
||||
client->addr = ts->ops->slave_addr;
|
||||
|
||||
mutex_lock(&ts->io_lock);
|
||||
ret = i2c_master_normal_recv(client, buf, count, rate);
|
||||
if(ret == 1)
|
||||
ret = 0;
|
||||
mutex_unlock(&ts->io_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ts_bulk_read_normal);
|
||||
|
||||
|
||||
int ts_bulk_write_normal(struct ts_private_data *ts, int count, unsigned char *buf, int rate)
|
||||
{
|
||||
int ret;
|
||||
unsigned short reg;
|
||||
struct i2c_client *client = ts->control_data;
|
||||
client->addr = ts->ops->slave_addr;
|
||||
|
||||
mutex_lock(&ts->io_lock);
|
||||
ret = i2c_master_normal_send(client, buf, count, rate);
|
||||
if(ret == 1)
|
||||
ret = 0;
|
||||
mutex_unlock(&ts->io_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ts_bulk_write_normal);
|
||||
|
||||
|
||||
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
static void ts_suspend(struct early_suspend *h)
|
||||
{
|
||||
struct ts_private_data *ts =
|
||||
container_of(h, struct ts_private_data, early_suspend);
|
||||
|
||||
return ts_device_suspend(ts);
|
||||
}
|
||||
|
||||
static void ts_resume(struct early_suspend *h)
|
||||
{
|
||||
struct ts_private_data *ts =
|
||||
container_of(h, struct ts_private_data, early_suspend);
|
||||
|
||||
return ts_device_resume(ts);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int ts_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct ts_private_data *ts;
|
||||
int ret,gpio,irq;
|
||||
int type = TS_BUS_TYPE_I2C;
|
||||
|
||||
if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C)) {
|
||||
dev_err(&i2c->adapter->dev, "%s failed\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ts = kzalloc(sizeof(struct ts_private_data), GFP_KERNEL);
|
||||
if (ts == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(i2c, ts);
|
||||
|
||||
ts->irq = i2c->irq;
|
||||
ts->dev = &i2c->dev;
|
||||
ts->control_data = i2c;
|
||||
ts->read_dev = ts_i2c_read_device;
|
||||
ts->write_dev = ts_i2c_write_device;
|
||||
|
||||
ret = ts_device_init(ts, type, ts->irq);
|
||||
if(ret)
|
||||
{
|
||||
printk("%s:fail to regist touch, type is %d\n",__func__, type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
if((ts->ops->suspend) && (ts->ops->resume))
|
||||
{
|
||||
ts->early_suspend.suspend = ts_suspend;
|
||||
ts->early_suspend.resume = ts_resume;
|
||||
ts->early_suspend.level = 0x02;
|
||||
register_early_suspend(&ts->early_suspend);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ts_i2c_remove(struct i2c_client *i2c)
|
||||
{
|
||||
struct ts_private_data *ts = i2c_get_clientdata(i2c);
|
||||
|
||||
ts_device_exit(ts);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static const struct i2c_device_id ts_i2c_id[] = {
|
||||
{"auto_ts_i2c", 0},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ts_i2c_id);
|
||||
|
||||
static struct i2c_driver ts_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "auto_ts_i2c",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = ts_i2c_probe,
|
||||
.remove = ts_i2c_remove,
|
||||
.id_table = ts_i2c_id,
|
||||
};
|
||||
|
||||
static int __init ts_i2c_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
printk("%s\n", __FUNCTION__);
|
||||
ret = i2c_add_driver(&ts_i2c_driver);
|
||||
if (ret != 0)
|
||||
pr_err("Failed to register ts I2C driver: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
subsys_initcall_sync(ts_i2c_init);
|
||||
|
||||
static void __exit ts_i2c_exit(void)
|
||||
{
|
||||
i2c_del_driver(&ts_i2c_driver);
|
||||
}
|
||||
module_exit(ts_i2c_exit);
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
//to do
|
||||
@@ -1,2 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
//to do
|
||||
@@ -1,152 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __TS_AUTO_H
|
||||
#define __TS_AUTO_H
|
||||
#include <linux/miscdevice.h>
|
||||
|
||||
#define TS_ENABLE 1
|
||||
#define TS_DISABLE 0
|
||||
#define TS_UNKNOW_DATA -1
|
||||
#define TS_MAX_POINT 20
|
||||
#define TS_MAX_VER_LEN 64
|
||||
|
||||
struct ts_private_data;
|
||||
|
||||
enum ts_bus_type{
|
||||
TS_BUS_TYPE_INVALID = 0,
|
||||
|
||||
TS_BUS_TYPE_I2C,
|
||||
TS_BUS_TYPE_SPI,
|
||||
TS_BUS_TYPE_SERIAL,
|
||||
|
||||
TS_BUS_TYPE_NUM_ID,
|
||||
};
|
||||
|
||||
enum ts_id {
|
||||
TS_ID_INVALID = 0,
|
||||
|
||||
TS_ID_FT5306,
|
||||
TS_ID_CT360,
|
||||
TS_ID_GT8110,
|
||||
TS_ID_GT828,
|
||||
TS_ID_GT8005,
|
||||
|
||||
TS_NUM_ID,
|
||||
};
|
||||
|
||||
struct point_data {
|
||||
int status;
|
||||
int id;
|
||||
int x;
|
||||
int y;
|
||||
int press;
|
||||
int last_status;
|
||||
};
|
||||
|
||||
struct ts_event {
|
||||
int touch_point;
|
||||
struct point_data point[TS_MAX_POINT];
|
||||
};
|
||||
|
||||
|
||||
/* Platform data for the auto touchscreen */
|
||||
struct ts_platform_data {
|
||||
unsigned char slave_addr;
|
||||
int irq;
|
||||
int power_pin;
|
||||
int reset_pin;
|
||||
|
||||
int (*init_platform_hw)(void);
|
||||
};
|
||||
|
||||
struct ts_max_pixel{
|
||||
int max_x;
|
||||
int max_y;
|
||||
};
|
||||
|
||||
struct ts_operate {
|
||||
char *name;
|
||||
char slave_addr;
|
||||
int ts_id;
|
||||
int bus_type;
|
||||
struct ts_max_pixel pixel;
|
||||
int reg_size;
|
||||
int id_reg;
|
||||
int id_data;
|
||||
int version_reg;
|
||||
char *version_data;
|
||||
int version_len; //<64
|
||||
int read_reg;
|
||||
int read_len;
|
||||
int trig; //intterupt trigger
|
||||
int max_point;
|
||||
int xy_swap;
|
||||
int x_revert;
|
||||
int y_revert;
|
||||
int range[2];
|
||||
int irq_enable; //if irq_enable=1 then use irq else use polling
|
||||
int poll_delay_ms; //polling
|
||||
int gpio_level_no_int;
|
||||
int (*active)(struct ts_private_data *ts, int enable);
|
||||
int (*init)(struct ts_private_data *ts);
|
||||
int (*check_irq)(struct ts_private_data *ts);
|
||||
int (*report)(struct ts_private_data *ts);
|
||||
int (*firmware)(struct ts_private_data *ts);
|
||||
int (*suspend)(struct ts_private_data *ts);
|
||||
int (*resume)(struct ts_private_data *ts);
|
||||
struct miscdevice *misc_dev;
|
||||
};
|
||||
|
||||
|
||||
struct ts_private_data {
|
||||
struct mutex io_lock;
|
||||
struct device *dev;
|
||||
int (*read_dev)(struct ts_private_data *ts, unsigned short reg,
|
||||
int bytes, void *dest, int reg_size);
|
||||
int (*write_dev)(struct ts_private_data *ts, unsigned short reg,
|
||||
int bytes, void *src, int reg_size);
|
||||
void *control_data;
|
||||
int irq;
|
||||
//struct i2c_client *client;
|
||||
struct input_dev *input_dev;
|
||||
struct ts_event event;
|
||||
struct work_struct work;
|
||||
struct delayed_work delaywork; /*report second event*/
|
||||
struct delayed_work poll_work; /*poll at last*/
|
||||
char ts_data[40]; //max support40 bytes data
|
||||
struct mutex data_mutex;
|
||||
struct mutex ts_lock;
|
||||
int devid;
|
||||
struct i2c_device_id *i2c_id;
|
||||
struct ts_platform_data *pdata;
|
||||
struct ts_operate *ops;
|
||||
struct file_operations fops;
|
||||
struct miscdevice miscdev;
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
struct early_suspend early_suspend;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern int ts_device_init(struct ts_private_data *ts, int type, int irq);
|
||||
extern void ts_device_exit(struct ts_private_data *ts);
|
||||
extern int ts_register_slave(struct ts_private_data *ts,
|
||||
struct ts_platform_data *slave_pdata,
|
||||
struct ts_operate *(*get_ts_ops)(void));
|
||||
extern int ts_unregister_slave(struct ts_private_data *ts,
|
||||
struct ts_platform_data *slave_pdata,
|
||||
struct ts_operate *(*get_ts_ops)(void));
|
||||
extern int ts_reg_read(struct ts_private_data *ts, unsigned short reg);
|
||||
extern int ts_reg_write(struct ts_private_data *ts, unsigned short reg,
|
||||
unsigned short val);
|
||||
extern int ts_bulk_read(struct ts_private_data *ts, unsigned short reg,
|
||||
int count, unsigned char *buf);
|
||||
extern int ts_bulk_read_normal(struct ts_private_data *ts, int count, unsigned char *buf, int rate);
|
||||
extern int ts_bulk_write(struct ts_private_data *ts, unsigned short reg,
|
||||
int count, unsigned char *buf);
|
||||
extern int ts_bulk_write_normal(struct ts_private_data *ts, int count, unsigned char *buf, int rate);
|
||||
extern int ts_set_bits(struct ts_private_data *ts, unsigned short reg,
|
||||
unsigned short mask, unsigned short val);
|
||||
extern int ts_device_suspend(struct ts_private_data *ts);
|
||||
|
||||
extern int ts_device_resume(struct ts_private_data *ts);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user