Files
android_kernel_samsung_sm86…/st/fts_lib/ftsFrame.c
Fei Mao cb9d543e8a touch: add drivers
Add all drivers for new platforms.

Change-Id: Ie9947b0c6f8ddfee7dab6dfa80d6aca62323f4da
Signed-off-by: Fei Mao <feim1@codeaurora.org>
2021-10-22 18:18:20 +08:00

520 baris
13 KiB
C

// SPDX-License-Identifier: GPL-2.0-only
/*
* FTS Capacitive touch screen controller (FingerTipS)
*
* Copyright (C) 2016-2019, STMicroelectronics Limited.
* Authors: AMG(Analog Mems Group) <marco.cali@st.com>
*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
*
**************************************************************************
** STMicroelectronics **
**************************************************************************
** marco.cali@st.com **
**************************************************************************
* *
* FTS functions for getting frames *
* *
**************************************************************************
**************************************************************************
*/
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <stdarg.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/serio.h>
#include <linux/time.h>
#include <linux/pm.h>
#include <linux/delay.h>
#include <linux/ctype.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/power_supply.h>
#include <linux/firmware.h>
#include <linux/regulator/consumer.h>
#include <linux/of_gpio.h>
//#include <linux/sec_sysfs.h>
#include "ftsCrossCompile.h"
#include "ftsCompensation.h"
#include "ftsError.h"
#include "ftsFrame.h"
#include "ftsHardware.h"
#include "ftsIO.h"
#include "ftsSoftware.h"
#include "ftsTool.h"
#include "ftsTime.h"
#include "../fts.h"
static char tag[8] = "[ FTS ]\0";
static int sense_len, force_len;
int getOffsetFrame(u16 address, u16 *offset)
{
u8 data[2];
u8 cmd = { FTS_CMD_FRAMEBUFFER_R };
char *temp = NULL;
if (readCmdU16(cmd, address, data, OFFSET_LENGTH,
DUMMY_FRAMEBUFFER) < 0) {
logError(1, "%s %S: ERROR %02X\n", tag, __func__, ERROR_I2C_R);
return ERROR_I2C_R;
}
u8ToU16(data, offset);
temp = printHex("Offest = ", data, OFFSET_LENGTH);
if (temp != NULL)
logError(0, "%s %s", tag, temp);
kfree(temp);
return OK;
}
int getChannelsLength(void)
{
int ret;
u8 *data = (u8 *)kmalloc_array(2, sizeof(u8), GFP_KERNEL);
if (data == NULL) {
logError(1, "%s %s: ERROR %02X\n",
tag, __func__, ERROR_ALLOC);
return ERROR_ALLOC;
}
ret = readB2(ADDR_SENSE_LEN, data, 2);
if (ret < OK) {
logError(1, "%s %s: ERROR %02X\n",
tag, __func__, ERROR_READ_B2);
kfree(data);
return (ret|ERROR_READ_B2);
}
sense_len = (int)data[0];
force_len = (int)data[1];
logError(0, "%s Force_len = %d Sense_Len = %d\n",
tag, force_len, sense_len);
kfree(data);
return OK;
}
int getFrameData(u16 address, int size, short **frame)
{
int i, j, ret;
u8 *data = (u8 *)kmalloc_array(size, sizeof(u8), GFP_KERNEL);
if (data == NULL) {
logError(1, "%s %s: ERROR %02X\n",
tag, __func__, ERROR_ALLOC);
return ERROR_ALLOC;
}
ret = readCmdU16(FTS_CMD_FRAMEBUFFER_R, address,
data, size, DUMMY_FRAMEBUFFER);
if (ret < OK) {
logError(1, "%s %s: ERROR %02X\n",
tag, __func__, ERROR_I2C_R);
kfree(data);
return ERROR_I2C_R;
}
j = 0;
for (i = 0; i < size; i += 2) {
(*frame)[j] = (short)((data[i + 1] << 8) + data[i]);
j++;
}
kfree(data);
return OK;
}
int getMSFrame(u16 type, struct MutualSenseFrame *frame, int keep_first_row)
{
u16 offset;
int ret;
if (getSenseLen() == 0 || getForceLen() == 0) {
ret = getChannelsLength();
if (ret < OK) {
logError(1, "%s %s: ERROR %02X\n",
tag, __func__, ERROR_CH_LEN);
return (ret|ERROR_CH_LEN);
}
}
ret = getOffsetFrame(type, &offset);
if (ret < OK) {
logError(1, "%s %s: ERROR %02X\n",
tag, __func__, ERROR_GET_OFFSET);
return (ret | ERROR_GET_OFFSET);
}
switch (type) {
case ADDR_RAW_TOUCH:
case ADDR_FILTER_TOUCH:
case ADDR_NORM_TOUCH:
case ADDR_CALIB_TOUCH:
if (keep_first_row == 1) {
frame->node_data_size = ((force_len + 1) * sense_len);
frame->header.force_node = force_len + 1;
} else {
frame->node_data_size = ((force_len) * sense_len);
offset += (sense_len * BYTES_PER_NODE);
frame->header.force_node = force_len;
}
frame->header.sense_node = sense_len;
break;
case ADDR_NORM_MS_KEY:
case ADDR_RAW_MS_KEY:
frame->header.force_node = 1;
frame->header.sense_node = ftsInfo.u8_msKeyLen;
frame->node_data_size = ftsInfo.u8_msKeyLen;
break;
default:
logError(1, "%s %s: ERROR % 02X\n",
tag, __func__, ERROR_OP_NOT_ALLOW);
return ERROR_OP_NOT_ALLOW;
}
frame->node_data = (short *)kmalloc_array(frame->node_data_size,
sizeof(short), GFP_KERNEL);
if (frame->node_data == NULL) {
logError(1, "%s %s: ERROR %02X\n",
tag, __func__, ERROR_ALLOC);
return ERROR_ALLOC;
}
ret = getFrameData(offset,
frame->node_data_size * BYTES_PER_NODE,
&(frame->node_data));
if (ret < OK) {
logError(1, "%s %s: ERROR %02X\n",
tag, __func__, ERROR_GET_FRAME_DATA);
kfree(frame->node_data);
return (ret | ERROR_GET_FRAME_DATA);
}
// if you want to access one node i,j,
//you should compute the offset like:
//offset = i * columns + j => frame[i, j]
logError(0, "%s Frame acquired!\n", tag);
//return the number of data put inside frame
return frame->node_data_size;
}
int getSenseLen(void)
{
int ret;
if (sense_len != 0)
return sense_len;
if (ftsInfo.u8_scrSenseLen != 0) {
sense_len = ftsInfo.u8_scrSenseLen;
} else {
ret = getChannelsLength();
if (ret < OK)
return ret;
}
return sense_len;
}
int getForceLen(void)
{
int ret;
if (force_len != 0)
return force_len;
if (ftsInfo.u8_scrForceLen != 0) {
force_len = ftsInfo.u8_scrForceLen;
} else {
ret = getChannelsLength();
if (ret < OK)
return ret;
}
return force_len;
}
int requestFrame(u16 type)
{
int retry = 0;
int ret;
u16 answer;
char *temp = NULL;
int event_to_search[1];
u8 readEvent[FIFO_EVENT_SIZE];
u8 cmd[3] = { FTS_CMD_REQU_FRAME_DATA, 0x00, 0x00};
// B7 is the command for asking frame data
event_to_search[0] = (int)EVENTID_FRAME_DATA_READ;
u16ToU8(type, &cmd[1]);
while (retry < FRAME_DATA_READ_RETRY) {
temp = printHex("Command = ", cmd, 3);
if (temp != NULL)
logError(0, "%s %s", tag, temp);
kfree(temp);
//send the request to the chip to load in memory the Frame Data
ret = fts_writeFwCmd(cmd, 3);
if (ret < OK) {
logError(1, "%s %s: ERROR %02X\n",
tag, __func__, ERROR_I2C_W);
return ERROR_I2C_W;
}
ret = pollForEvent(event_to_search,
1,
readEvent,
TIMEOUT_REQU_COMP_DATA);
if (ret < OK) {
logError(0, "%s Event did not Found at %d attemp!\n",
tag, retry + 1);
retry += 1;
} else {
retry = 0;
break;
}
}
if (retry == FRAME_DATA_READ_RETRY) {
logError(1, "%s %s: ERROR %02X\n",
tag, __func__, ERROR_TIMEOUT);
return ERROR_TIMEOUT;
}
u8ToU16_le(&readEvent[1], &answer);
if (answer == type)
return OK;
logError(1, "%s The event found has a different type of ", tag);
logError(1, "Frame data:%02X\n", ERROR_DIFF_COMP_TYPE);
return ERROR_DIFF_COMP_TYPE;
}
int readFrameDataHeader(u16 type, struct DataHeader *header)
{
u16 offset = ADDR_FRAMEBUFFER_DATA;
u16 answer;
u8 data[FRAME_DATA_HEADER];
if (readCmdU16(FTS_CMD_FRAMEBUFFER_R, offset, data,
FRAME_DATA_HEADER, DUMMY_FRAMEBUFFER) < 0) {
logError(1, "%s %s: ERROR %02X\n",
tag, __func__, ERROR_I2C_R);
return ERROR_I2C_R;
}
logError(0, "%s Read Data Header done!\n", tag);
if (data[0] != FRAME_HEADER_SIGNATURE) {
logError(1, "%s %s %02X Wrong Header Signature !%02X != %02X\n",
tag, __func__, ERROR_WRONG_COMP_SIGN, data[0],
HEADER_SIGNATURE);
return ERROR_WRONG_COMP_SIGN;
}
u8ToU16_le(&data[1], &answer);
if (answer != type) {
logError(1, "%s %s: ERROR %02X\n",
tag, __func__, ERROR_DIFF_COMP_TYPE);
return ERROR_DIFF_COMP_TYPE;
}
logError(0, "%s Type of Frame data OK!\n", tag);
header->type = type;
header->force_node = (int)data[4];
header->sense_node = (int)data[5];
return OK;
}
int getMSFrame2(u16 type, struct MutualSenseFrame *frame)
{
u16 offset = ADDR_FRAMEBUFFER_DATA+FRAME_DATA_HEADER;
int size, ret;
frame->node_data = NULL;
if (!(type == MS_TOUCH_ACTIVE || type == MS_TOUCH_LOW_POWER
|| type == MS_TOUCH_ULTRA_LOW_POWER
|| type == MS_KEY)) {
logError(1, "%s %s:Choose a MS type of frame data ERROR %02X\n",
tag, __func__, ERROR_OP_NOT_ALLOW);
return ERROR_OP_NOT_ALLOW;
}
ret = requestFrame(type);
if (ret < 0) {
logError(1, "%s readMutualSenseCompensation:ERROR %02X\n",
tag, ERROR_REQU_COMP_DATA);
return (ret | ERROR_REQU_COMP_DATA);
}
ret = readFrameDataHeader(type, &(frame->header));
if (ret < 0) {
logError(1, "%s readMutualSenseCompensationData:ERROR %02X\n",
tag, ERROR_COMP_DATA_HEADER);
return (ret | ERROR_COMP_DATA_HEADER);
}
switch (type) {
case MS_TOUCH_ACTIVE:
case MS_TOUCH_LOW_POWER:
case MS_TOUCH_ULTRA_LOW_POWER:
size = frame->header.force_node * frame->header.sense_node;
break;
case MS_KEY:
//or use directly the number in the ftsChip
if (frame->header.force_node > frame->header.sense_node)
size = frame->header.force_node;
else
size = frame->header.sense_node;
frame->header.force_node = 1;
frame->header.sense_node = size;
break;
default:
logError(1, "%s %s: ERROR % 02X\n",
tag, __func__, ERROR_OP_NOT_ALLOW);
return ERROR_OP_NOT_ALLOW;
}
frame->node_data = (short *)kmalloc_array(size,
sizeof(short), GFP_KERNEL);
if (frame->node_data == NULL) {
logError(1, "%s %s: ERROR %02X\n", tag, __func__, ERROR_ALLOC);
return ERROR_ALLOC;
}
ret = getFrameData(offset, size*BYTES_PER_NODE, &(frame->node_data));
if (ret < OK) {
logError(1, "%s %s: ERROR %02X\n",
tag, __func__, ERROR_GET_FRAME_DATA);
kfree(frame->node_data);
return (ret | ERROR_GET_FRAME_DATA);
}
// if you want to access one node i,j,
//you should compute the offset like:
//offset = i * columns + j = > frame[i, j]
logError(0, "%s Frame acquired!\n", tag);
frame->node_data_size = size;
return size;//return the number of data put inside frame
}
int getSSFrame2(u16 type, struct SelfSenseFrame *frame)
{
u16 offset = ADDR_FRAMEBUFFER_DATA + FRAME_DATA_HEADER;
int size, ret;
short *temp = NULL;
frame->force_data = NULL;
frame->sense_data = NULL;
if (!(type == SS_TOUCH || type == SS_KEY || type == SS_HOVER
|| type == SS_PROXIMITY)) {
logError(1, "%s %s:Choose a SS type of frame data ERROR %02X\n",
tag, __func__, ERROR_OP_NOT_ALLOW);
return ERROR_OP_NOT_ALLOW;
}
ret = requestFrame(type);
if (ret < 0) {
logError(1, "%s %s: ERROR %02X\n",
tag, __func__, ERROR_REQU_COMP_DATA);
return (ret | ERROR_REQU_COMP_DATA);
}
ret = readFrameDataHeader(type, &(frame->header));
if (ret < 0) {
logError(1, "%s %s: ERROR %02X\n",
tag, __func__, ERROR_COMP_DATA_HEADER);
return (ret | ERROR_COMP_DATA_HEADER);
}
switch (type) {
case SS_TOUCH:
case SS_HOVER:
case SS_PROXIMITY:
size = frame->header.force_node + frame->header.sense_node;
break;
default:
logError(1, "%s %s: ERROR % 02X\n",
tag, __func__, ERROR_OP_NOT_ALLOW);
return ERROR_OP_NOT_ALLOW;
}
temp = (short *)kmalloc_array(size, sizeof(short), GFP_KERNEL);
if (temp == NULL) {
logError(1, "%s %s: temp ERROR %02X\n",
tag, __func__, ERROR_ALLOC);
return ERROR_ALLOC;
}
ret = getFrameData(offset, size*BYTES_PER_NODE, &temp);
if (ret < OK) {
logError(1, "%s %s: ERROR %02X\n",
tag, __func__, ERROR_GET_FRAME_DATA);
kfree(temp);
return (ret | ERROR_GET_FRAME_DATA);
}
frame->force_data = (short *)kmalloc_array(frame->header.force_node,
sizeof(short), GFP_KERNEL);
if (frame->force_data == NULL) {
logError(1, "%s %s: frame->force_data ERROR %02X\n",
tag, __func__, ERROR_ALLOC);
kfree(temp);
return ERROR_ALLOC;
}
memcpy(frame->force_data, temp,
frame->header.force_node * sizeof(short));
frame->sense_data = (short *)kmalloc_array(frame->header.sense_node,
sizeof(short), GFP_KERNEL);
if (frame->sense_data == NULL) {
logError(1, "%s %s: frame->sense_data ERROR %02X\n",
tag, __func__, ERROR_ALLOC);
kfree(temp);
kfree(frame->force_data);
return ERROR_ALLOC;
}
memcpy(frame->sense_data, &temp[frame->header.force_node],
frame->header.sense_node * sizeof(short));
logError(0, "%s Frame acquired!\n", tag);
kfree(temp);
return size; //return the number of data put inside frame
}