Input: cyapa - add gen5 trackpad read baseline support
Add read baseline function support for gen5 trackpad device, it can be used through sysfs baseline interface. Signed-off-by: Dudley Du <dudl@cypress.com> Tested-by: Jeremiah Mahler <jmmahler@gmail.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
This commit is contained in:
parent
5812d30672
commit
6499d390a1
|
@ -263,6 +263,8 @@ struct cyapa {
|
|||
u8 y_origin; /* Y Axis Origin: 0 = top; 1 = bottom. */
|
||||
int electrodes_x; /* Number of electrodes on the X Axis*/
|
||||
int electrodes_y; /* Number of electrodes on the Y Axis*/
|
||||
int electrodes_rx; /* Number of Rx electrodes */
|
||||
int aligned_electrodes_rx; /* 4 aligned */
|
||||
int max_z;
|
||||
|
||||
/*
|
||||
|
|
|
@ -363,6 +363,12 @@ struct gen5_app_get_parameter_data {
|
|||
u8 parameter_id;
|
||||
} __packed;
|
||||
|
||||
struct gen5_retrieve_panel_scan_data {
|
||||
__le16 read_offset;
|
||||
__le16 read_elements;
|
||||
u8 data_id;
|
||||
} __packed;
|
||||
|
||||
/* Variables to record latest gen5 trackpad power states. */
|
||||
#define GEN5_DEV_SET_PWR_STATE(cyapa, s) ((cyapa)->dev_pwr_mode = (s))
|
||||
#define GEN5_DEV_GET_PWR_STATE(cyapa) ((cyapa)->dev_pwr_mode)
|
||||
|
@ -1661,6 +1667,638 @@ static int cyapa_gen5_set_power_mode(struct cyapa *cyapa,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cyapa_gen5_resume_scanning(struct cyapa *cyapa)
|
||||
{
|
||||
u8 cmd[] = { 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x04 };
|
||||
u8 resp_data[6];
|
||||
int resp_len;
|
||||
int error;
|
||||
|
||||
/* Try to dump all buffered data before doing command. */
|
||||
cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);
|
||||
|
||||
resp_len = sizeof(resp_data);
|
||||
error = cyapa_i2c_pip_cmd_irq_sync(cyapa,
|
||||
cmd, sizeof(cmd),
|
||||
resp_data, &resp_len,
|
||||
500, cyapa_gen5_sort_tsg_pip_app_resp_data, true);
|
||||
if (error || !VALID_CMD_RESP_HEADER(resp_data, 0x04))
|
||||
return -EINVAL;
|
||||
|
||||
/* Try to dump all buffered data when resuming scanning. */
|
||||
cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cyapa_gen5_suspend_scanning(struct cyapa *cyapa)
|
||||
{
|
||||
u8 cmd[] = { 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x03 };
|
||||
u8 resp_data[6];
|
||||
int resp_len;
|
||||
int error;
|
||||
|
||||
/* Try to dump all buffered data before doing command. */
|
||||
cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);
|
||||
|
||||
resp_len = sizeof(resp_data);
|
||||
error = cyapa_i2c_pip_cmd_irq_sync(cyapa,
|
||||
cmd, sizeof(cmd),
|
||||
resp_data, &resp_len,
|
||||
500, cyapa_gen5_sort_tsg_pip_app_resp_data, true);
|
||||
if (error || !VALID_CMD_RESP_HEADER(resp_data, 0x03))
|
||||
return -EINVAL;
|
||||
|
||||
/* Try to dump all buffered data when suspending scanning. */
|
||||
cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static s32 twos_complement_to_s32(s32 value, int num_bits)
|
||||
{
|
||||
if (value >> (num_bits - 1))
|
||||
value |= -1 << num_bits;
|
||||
return value;
|
||||
}
|
||||
|
||||
static s32 cyapa_parse_structure_data(u8 data_format, u8 *buf, int buf_len)
|
||||
{
|
||||
int data_size;
|
||||
bool big_endian;
|
||||
bool unsigned_type;
|
||||
s32 value;
|
||||
|
||||
data_size = (data_format & 0x07);
|
||||
big_endian = ((data_format & 0x10) == 0x00);
|
||||
unsigned_type = ((data_format & 0x20) == 0x00);
|
||||
|
||||
if (buf_len < data_size)
|
||||
return 0;
|
||||
|
||||
switch (data_size) {
|
||||
case 1:
|
||||
value = buf[0];
|
||||
break;
|
||||
case 2:
|
||||
if (big_endian)
|
||||
value = get_unaligned_be16(buf);
|
||||
else
|
||||
value = get_unaligned_le16(buf);
|
||||
break;
|
||||
case 4:
|
||||
if (big_endian)
|
||||
value = get_unaligned_be32(buf);
|
||||
else
|
||||
value = get_unaligned_le32(buf);
|
||||
break;
|
||||
default:
|
||||
/* Should not happen, just as default case here. */
|
||||
value = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!unsigned_type)
|
||||
value = twos_complement_to_s32(value, data_size * 8);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static void cyapa_gen5_guess_electrodes(struct cyapa *cyapa,
|
||||
int *electrodes_rx, int *electrodes_tx)
|
||||
{
|
||||
if (cyapa->electrodes_rx != 0) {
|
||||
*electrodes_rx = cyapa->electrodes_rx;
|
||||
*electrodes_tx = (cyapa->electrodes_x == *electrodes_rx) ?
|
||||
cyapa->electrodes_y : cyapa->electrodes_x;
|
||||
} else {
|
||||
*electrodes_tx = min(cyapa->electrodes_x, cyapa->electrodes_y);
|
||||
*electrodes_rx = max(cyapa->electrodes_x, cyapa->electrodes_y);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read all the global mutual or self idac data or mutual or self local PWC
|
||||
* data based on the @idac_data_type.
|
||||
* If the input value of @data_size is 0, then means read global mutual or
|
||||
* self idac data. For read global mutual idac data, @idac_max, @idac_min and
|
||||
* @idac_ave are in order used to return the max value of global mutual idac
|
||||
* data, the min value of global mutual idac and the average value of the
|
||||
* global mutual idac data. For read global self idac data, @idac_max is used
|
||||
* to return the global self cap idac data in Rx direction, @idac_min is used
|
||||
* to return the global self cap idac data in Tx direction. @idac_ave is not
|
||||
* used.
|
||||
* If the input value of @data_size is not 0, than means read the mutual or
|
||||
* self local PWC data. The @idac_max, @idac_min and @idac_ave are used to
|
||||
* return the max, min and average value of the mutual or self local PWC data.
|
||||
* Note, in order to raed mutual local PWC data, must read invoke this function
|
||||
* to read the mutual global idac data firstly to set the correct Rx number
|
||||
* value, otherwise, the read mutual idac and PWC data may not correct.
|
||||
*/
|
||||
static int cyapa_gen5_read_idac_data(struct cyapa *cyapa,
|
||||
u8 cmd_code, u8 idac_data_type, int *data_size,
|
||||
int *idac_max, int *idac_min, int *idac_ave)
|
||||
{
|
||||
struct gen5_app_cmd_head *cmd_head;
|
||||
u8 cmd[12];
|
||||
u8 resp_data[256];
|
||||
int resp_len;
|
||||
int read_len;
|
||||
int value;
|
||||
u16 offset;
|
||||
int read_elements;
|
||||
bool read_global_idac;
|
||||
int sum, count, max_element_cnt;
|
||||
int tmp_max, tmp_min, tmp_ave, tmp_sum, tmp_count;
|
||||
int electrodes_rx, electrodes_tx;
|
||||
int i;
|
||||
int error;
|
||||
|
||||
if (cmd_code != GEN5_CMD_RETRIEVE_DATA_STRUCTURE ||
|
||||
(idac_data_type != GEN5_RETRIEVE_MUTUAL_PWC_DATA &&
|
||||
idac_data_type != GEN5_RETRIEVE_SELF_CAP_PWC_DATA) ||
|
||||
!data_size || !idac_max || !idac_min || !idac_ave)
|
||||
return -EINVAL;
|
||||
|
||||
*idac_max = INT_MIN;
|
||||
*idac_min = INT_MAX;
|
||||
sum = count = tmp_count = 0;
|
||||
electrodes_rx = electrodes_tx = 0;
|
||||
if (*data_size == 0) {
|
||||
/*
|
||||
* Read global idac values firstly.
|
||||
* Currently, no idac data exceed 4 bytes.
|
||||
*/
|
||||
read_global_idac = true;
|
||||
offset = 0;
|
||||
*data_size = 4;
|
||||
tmp_max = INT_MIN;
|
||||
tmp_min = INT_MAX;
|
||||
tmp_ave = tmp_sum = tmp_count = 0;
|
||||
|
||||
if (idac_data_type == GEN5_RETRIEVE_MUTUAL_PWC_DATA) {
|
||||
if (cyapa->aligned_electrodes_rx == 0) {
|
||||
cyapa_gen5_guess_electrodes(cyapa,
|
||||
&electrodes_rx, &electrodes_tx);
|
||||
cyapa->aligned_electrodes_rx =
|
||||
(electrodes_rx + 3) & ~3u;
|
||||
}
|
||||
max_element_cnt =
|
||||
(cyapa->aligned_electrodes_rx + 7) & ~7u;
|
||||
} else {
|
||||
max_element_cnt = 2;
|
||||
}
|
||||
} else {
|
||||
read_global_idac = false;
|
||||
if (*data_size > 4)
|
||||
*data_size = 4;
|
||||
/* Calculate the start offset in bytes of local PWC data. */
|
||||
if (idac_data_type == GEN5_RETRIEVE_MUTUAL_PWC_DATA) {
|
||||
offset = cyapa->aligned_electrodes_rx * (*data_size);
|
||||
if (cyapa->electrodes_rx == cyapa->electrodes_x)
|
||||
electrodes_tx = cyapa->electrodes_y;
|
||||
else
|
||||
electrodes_tx = cyapa->electrodes_x;
|
||||
max_element_cnt = ((cyapa->aligned_electrodes_rx + 7) &
|
||||
~7u) * electrodes_tx;
|
||||
} else if (idac_data_type == GEN5_RETRIEVE_SELF_CAP_PWC_DATA) {
|
||||
offset = 2;
|
||||
max_element_cnt = cyapa->electrodes_x +
|
||||
cyapa->electrodes_y;
|
||||
max_element_cnt = (max_element_cnt + 3) & ~3u;
|
||||
}
|
||||
}
|
||||
|
||||
memset(cmd, 0, sizeof(cmd));
|
||||
cmd_head = (struct gen5_app_cmd_head *)cmd;
|
||||
put_unaligned_le16(GEN5_OUTPUT_REPORT_ADDR, &cmd_head->addr);
|
||||
put_unaligned_le16(sizeof(cmd) - 2, &cmd_head->length);
|
||||
cmd_head->report_id = GEN5_APP_CMD_REPORT_ID;
|
||||
cmd_head->cmd_code = cmd_code;
|
||||
do {
|
||||
read_elements = (256 - GEN5_RESP_DATA_STRUCTURE_OFFSET) /
|
||||
(*data_size);
|
||||
read_elements = min(read_elements, max_element_cnt - count);
|
||||
read_len = read_elements * (*data_size);
|
||||
|
||||
put_unaligned_le16(offset, &cmd_head->parameter_data[0]);
|
||||
put_unaligned_le16(read_len, &cmd_head->parameter_data[2]);
|
||||
cmd_head->parameter_data[4] = idac_data_type;
|
||||
resp_len = GEN5_RESP_DATA_STRUCTURE_OFFSET + read_len;
|
||||
error = cyapa_i2c_pip_cmd_irq_sync(cyapa,
|
||||
cmd, sizeof(cmd),
|
||||
resp_data, &resp_len,
|
||||
500, cyapa_gen5_sort_tsg_pip_app_resp_data,
|
||||
true);
|
||||
if (error || resp_len < GEN5_RESP_DATA_STRUCTURE_OFFSET ||
|
||||
!VALID_CMD_RESP_HEADER(resp_data, cmd_code) ||
|
||||
!GEN5_CMD_COMPLETE_SUCCESS(resp_data[5]) ||
|
||||
resp_data[6] != idac_data_type)
|
||||
return (error < 0) ? error : -EAGAIN;
|
||||
read_len = get_unaligned_le16(&resp_data[7]);
|
||||
if (read_len == 0)
|
||||
break;
|
||||
|
||||
*data_size = (resp_data[9] & GEN5_PWC_DATA_ELEMENT_SIZE_MASK);
|
||||
if (read_len < *data_size)
|
||||
return -EINVAL;
|
||||
|
||||
if (read_global_idac &&
|
||||
idac_data_type == GEN5_RETRIEVE_SELF_CAP_PWC_DATA) {
|
||||
/* Rx's self global idac data. */
|
||||
*idac_max = cyapa_parse_structure_data(
|
||||
resp_data[9],
|
||||
&resp_data[GEN5_RESP_DATA_STRUCTURE_OFFSET],
|
||||
*data_size);
|
||||
/* Tx's self global idac data. */
|
||||
*idac_min = cyapa_parse_structure_data(
|
||||
resp_data[9],
|
||||
&resp_data[GEN5_RESP_DATA_STRUCTURE_OFFSET +
|
||||
*data_size],
|
||||
*data_size);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Read mutual global idac or local mutual/self PWC data. */
|
||||
offset += read_len;
|
||||
for (i = 10; i < (read_len + GEN5_RESP_DATA_STRUCTURE_OFFSET);
|
||||
i += *data_size) {
|
||||
value = cyapa_parse_structure_data(resp_data[9],
|
||||
&resp_data[i], *data_size);
|
||||
*idac_min = min(value, *idac_min);
|
||||
*idac_max = max(value, *idac_max);
|
||||
|
||||
if (idac_data_type == GEN5_RETRIEVE_MUTUAL_PWC_DATA &&
|
||||
tmp_count < cyapa->aligned_electrodes_rx &&
|
||||
read_global_idac) {
|
||||
/*
|
||||
* The value gap betwen global and local mutual
|
||||
* idac data must bigger than 50%.
|
||||
* Normally, global value bigger than 50,
|
||||
* local values less than 10.
|
||||
*/
|
||||
if (!tmp_ave || value > tmp_ave / 2) {
|
||||
tmp_min = min(value, tmp_min);
|
||||
tmp_max = max(value, tmp_max);
|
||||
tmp_sum += value;
|
||||
tmp_count++;
|
||||
|
||||
tmp_ave = tmp_sum / tmp_count;
|
||||
}
|
||||
}
|
||||
|
||||
sum += value;
|
||||
count++;
|
||||
|
||||
if (count >= max_element_cnt)
|
||||
goto out;
|
||||
}
|
||||
} while (true);
|
||||
|
||||
out:
|
||||
*idac_ave = count ? (sum / count) : 0;
|
||||
|
||||
if (read_global_idac &&
|
||||
idac_data_type == GEN5_RETRIEVE_MUTUAL_PWC_DATA) {
|
||||
if (tmp_count == 0)
|
||||
return 0;
|
||||
|
||||
if (tmp_count == cyapa->aligned_electrodes_rx) {
|
||||
cyapa->electrodes_rx = cyapa->electrodes_rx ?
|
||||
cyapa->electrodes_rx : electrodes_rx;
|
||||
} else if (tmp_count == electrodes_rx) {
|
||||
cyapa->electrodes_rx = cyapa->electrodes_rx ?
|
||||
cyapa->electrodes_rx : electrodes_rx;
|
||||
cyapa->aligned_electrodes_rx = electrodes_rx;
|
||||
} else {
|
||||
cyapa->electrodes_rx = cyapa->electrodes_rx ?
|
||||
cyapa->electrodes_rx : electrodes_tx;
|
||||
cyapa->aligned_electrodes_rx = tmp_count;
|
||||
}
|
||||
|
||||
*idac_min = tmp_min;
|
||||
*idac_max = tmp_max;
|
||||
*idac_ave = tmp_ave;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cyapa_gen5_read_mutual_idac_data(struct cyapa *cyapa,
|
||||
int *gidac_mutual_max, int *gidac_mutual_min, int *gidac_mutual_ave,
|
||||
int *lidac_mutual_max, int *lidac_mutual_min, int *lidac_mutual_ave)
|
||||
{
|
||||
int data_size;
|
||||
int error;
|
||||
|
||||
*gidac_mutual_max = *gidac_mutual_min = *gidac_mutual_ave = 0;
|
||||
*lidac_mutual_max = *lidac_mutual_min = *lidac_mutual_ave = 0;
|
||||
|
||||
data_size = 0;
|
||||
error = cyapa_gen5_read_idac_data(cyapa,
|
||||
GEN5_CMD_RETRIEVE_DATA_STRUCTURE,
|
||||
GEN5_RETRIEVE_MUTUAL_PWC_DATA,
|
||||
&data_size,
|
||||
gidac_mutual_max, gidac_mutual_min, gidac_mutual_ave);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = cyapa_gen5_read_idac_data(cyapa,
|
||||
GEN5_CMD_RETRIEVE_DATA_STRUCTURE,
|
||||
GEN5_RETRIEVE_MUTUAL_PWC_DATA,
|
||||
&data_size,
|
||||
lidac_mutual_max, lidac_mutual_min, lidac_mutual_ave);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int cyapa_gen5_read_self_idac_data(struct cyapa *cyapa,
|
||||
int *gidac_self_rx, int *gidac_self_tx,
|
||||
int *lidac_self_max, int *lidac_self_min, int *lidac_self_ave)
|
||||
{
|
||||
int data_size;
|
||||
int error;
|
||||
|
||||
*gidac_self_rx = *gidac_self_tx = 0;
|
||||
*lidac_self_max = *lidac_self_min = *lidac_self_ave = 0;
|
||||
|
||||
data_size = 0;
|
||||
error = cyapa_gen5_read_idac_data(cyapa,
|
||||
GEN5_CMD_RETRIEVE_DATA_STRUCTURE,
|
||||
GEN5_RETRIEVE_SELF_CAP_PWC_DATA,
|
||||
&data_size,
|
||||
lidac_self_max, lidac_self_min, lidac_self_ave);
|
||||
if (error)
|
||||
return error;
|
||||
*gidac_self_rx = *lidac_self_max;
|
||||
*gidac_self_tx = *lidac_self_min;
|
||||
|
||||
error = cyapa_gen5_read_idac_data(cyapa,
|
||||
GEN5_CMD_RETRIEVE_DATA_STRUCTURE,
|
||||
GEN5_RETRIEVE_SELF_CAP_PWC_DATA,
|
||||
&data_size,
|
||||
lidac_self_max, lidac_self_min, lidac_self_ave);
|
||||
return error;
|
||||
}
|
||||
|
||||
static ssize_t cyapa_gen5_execute_panel_scan(struct cyapa *cyapa)
|
||||
{
|
||||
struct gen5_app_cmd_head *app_cmd_head;
|
||||
u8 cmd[7];
|
||||
u8 resp_data[6];
|
||||
int resp_len;
|
||||
int error;
|
||||
|
||||
memset(cmd, 0, sizeof(cmd));
|
||||
app_cmd_head = (struct gen5_app_cmd_head *)cmd;
|
||||
put_unaligned_le16(GEN5_OUTPUT_REPORT_ADDR, &app_cmd_head->addr);
|
||||
put_unaligned_le16(sizeof(cmd) - 2, &app_cmd_head->length);
|
||||
app_cmd_head->report_id = GEN5_APP_CMD_REPORT_ID;
|
||||
app_cmd_head->cmd_code = GEN5_CMD_EXECUTE_PANEL_SCAN;
|
||||
resp_len = sizeof(resp_data);
|
||||
error = cyapa_i2c_pip_cmd_irq_sync(cyapa,
|
||||
cmd, sizeof(cmd),
|
||||
resp_data, &resp_len,
|
||||
500, cyapa_gen5_sort_tsg_pip_app_resp_data, true);
|
||||
if (error || resp_len != sizeof(resp_data) ||
|
||||
!VALID_CMD_RESP_HEADER(resp_data,
|
||||
GEN5_CMD_EXECUTE_PANEL_SCAN) ||
|
||||
!GEN5_CMD_COMPLETE_SUCCESS(resp_data[5]))
|
||||
return error ? error : -EAGAIN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cyapa_gen5_read_panel_scan_raw_data(struct cyapa *cyapa,
|
||||
u8 cmd_code, u8 raw_data_type, int raw_data_max_num,
|
||||
int *raw_data_max, int *raw_data_min, int *raw_data_ave,
|
||||
u8 *buffer)
|
||||
{
|
||||
struct gen5_app_cmd_head *app_cmd_head;
|
||||
struct gen5_retrieve_panel_scan_data *panel_sacn_data;
|
||||
u8 cmd[12];
|
||||
u8 resp_data[256]; /* Max bytes can transfer one time. */
|
||||
int resp_len;
|
||||
int read_elements;
|
||||
int read_len;
|
||||
u16 offset;
|
||||
s32 value;
|
||||
int sum, count;
|
||||
int data_size;
|
||||
s32 *intp;
|
||||
int i;
|
||||
int error;
|
||||
|
||||
if (cmd_code != GEN5_CMD_RETRIEVE_PANEL_SCAN ||
|
||||
(raw_data_type > GEN5_PANEL_SCAN_SELF_DIFFCOUNT) ||
|
||||
!raw_data_max || !raw_data_min || !raw_data_ave)
|
||||
return -EINVAL;
|
||||
|
||||
intp = (s32 *)buffer;
|
||||
*raw_data_max = INT_MIN;
|
||||
*raw_data_min = INT_MAX;
|
||||
sum = count = 0;
|
||||
offset = 0;
|
||||
/* Assume max element size is 4 currently. */
|
||||
read_elements = (256 - GEN5_RESP_DATA_STRUCTURE_OFFSET) / 4;
|
||||
read_len = read_elements * 4;
|
||||
app_cmd_head = (struct gen5_app_cmd_head *)cmd;
|
||||
put_unaligned_le16(GEN5_OUTPUT_REPORT_ADDR, &app_cmd_head->addr);
|
||||
put_unaligned_le16(sizeof(cmd) - 2, &app_cmd_head->length);
|
||||
app_cmd_head->report_id = GEN5_APP_CMD_REPORT_ID;
|
||||
app_cmd_head->cmd_code = cmd_code;
|
||||
panel_sacn_data = (struct gen5_retrieve_panel_scan_data *)
|
||||
app_cmd_head->parameter_data;
|
||||
do {
|
||||
put_unaligned_le16(offset, &panel_sacn_data->read_offset);
|
||||
put_unaligned_le16(read_elements,
|
||||
&panel_sacn_data->read_elements);
|
||||
panel_sacn_data->data_id = raw_data_type;
|
||||
|
||||
resp_len = GEN5_RESP_DATA_STRUCTURE_OFFSET + read_len;
|
||||
error = cyapa_i2c_pip_cmd_irq_sync(cyapa,
|
||||
cmd, sizeof(cmd),
|
||||
resp_data, &resp_len,
|
||||
500, cyapa_gen5_sort_tsg_pip_app_resp_data, true);
|
||||
if (error || resp_len < GEN5_RESP_DATA_STRUCTURE_OFFSET ||
|
||||
!VALID_CMD_RESP_HEADER(resp_data, cmd_code) ||
|
||||
!GEN5_CMD_COMPLETE_SUCCESS(resp_data[5]) ||
|
||||
resp_data[6] != raw_data_type)
|
||||
return error ? error : -EAGAIN;
|
||||
|
||||
read_elements = get_unaligned_le16(&resp_data[7]);
|
||||
if (read_elements == 0)
|
||||
break;
|
||||
|
||||
data_size = (resp_data[9] & GEN5_PWC_DATA_ELEMENT_SIZE_MASK);
|
||||
offset += read_elements;
|
||||
if (read_elements) {
|
||||
for (i = GEN5_RESP_DATA_STRUCTURE_OFFSET;
|
||||
i < (read_elements * data_size +
|
||||
GEN5_RESP_DATA_STRUCTURE_OFFSET);
|
||||
i += data_size) {
|
||||
value = cyapa_parse_structure_data(resp_data[9],
|
||||
&resp_data[i], data_size);
|
||||
*raw_data_min = min(value, *raw_data_min);
|
||||
*raw_data_max = max(value, *raw_data_max);
|
||||
|
||||
if (intp)
|
||||
put_unaligned_le32(value, &intp[count]);
|
||||
|
||||
sum += value;
|
||||
count++;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (count >= raw_data_max_num)
|
||||
break;
|
||||
|
||||
read_elements = (sizeof(resp_data) -
|
||||
GEN5_RESP_DATA_STRUCTURE_OFFSET) / data_size;
|
||||
read_len = read_elements * data_size;
|
||||
} while (true);
|
||||
|
||||
*raw_data_ave = count ? (sum / count) : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t cyapa_gen5_show_baseline(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct cyapa *cyapa = dev_get_drvdata(dev);
|
||||
int gidac_mutual_max, gidac_mutual_min, gidac_mutual_ave;
|
||||
int lidac_mutual_max, lidac_mutual_min, lidac_mutual_ave;
|
||||
int gidac_self_rx, gidac_self_tx;
|
||||
int lidac_self_max, lidac_self_min, lidac_self_ave;
|
||||
int raw_cap_mutual_max, raw_cap_mutual_min, raw_cap_mutual_ave;
|
||||
int raw_cap_self_max, raw_cap_self_min, raw_cap_self_ave;
|
||||
int mutual_diffdata_max, mutual_diffdata_min, mutual_diffdata_ave;
|
||||
int self_diffdata_max, self_diffdata_min, self_diffdata_ave;
|
||||
int mutual_baseline_max, mutual_baseline_min, mutual_baseline_ave;
|
||||
int self_baseline_max, self_baseline_min, self_baseline_ave;
|
||||
int error, resume_error;
|
||||
int size;
|
||||
|
||||
if (cyapa->state != CYAPA_STATE_GEN5_APP)
|
||||
return -EBUSY;
|
||||
|
||||
/* 1. Suspend Scanning*/
|
||||
error = cyapa_gen5_suspend_scanning(cyapa);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/* 2. Read global and local mutual IDAC data. */
|
||||
gidac_self_rx = gidac_self_tx = 0;
|
||||
error = cyapa_gen5_read_mutual_idac_data(cyapa,
|
||||
&gidac_mutual_max, &gidac_mutual_min,
|
||||
&gidac_mutual_ave, &lidac_mutual_max,
|
||||
&lidac_mutual_min, &lidac_mutual_ave);
|
||||
if (error)
|
||||
goto resume_scanning;
|
||||
|
||||
/* 3. Read global and local self IDAC data. */
|
||||
error = cyapa_gen5_read_self_idac_data(cyapa,
|
||||
&gidac_self_rx, &gidac_self_tx,
|
||||
&lidac_self_max, &lidac_self_min,
|
||||
&lidac_self_ave);
|
||||
if (error)
|
||||
goto resume_scanning;
|
||||
|
||||
/* 4. Execuate panel scan. It must be executed before read data. */
|
||||
error = cyapa_gen5_execute_panel_scan(cyapa);
|
||||
if (error)
|
||||
goto resume_scanning;
|
||||
|
||||
/* 5. Retrieve panel scan, mutual cap raw data. */
|
||||
error = cyapa_gen5_read_panel_scan_raw_data(cyapa,
|
||||
GEN5_CMD_RETRIEVE_PANEL_SCAN,
|
||||
GEN5_PANEL_SCAN_MUTUAL_RAW_DATA,
|
||||
cyapa->electrodes_x * cyapa->electrodes_y,
|
||||
&raw_cap_mutual_max, &raw_cap_mutual_min,
|
||||
&raw_cap_mutual_ave,
|
||||
NULL);
|
||||
if (error)
|
||||
goto resume_scanning;
|
||||
|
||||
/* 6. Retrieve panel scan, self cap raw data. */
|
||||
error = cyapa_gen5_read_panel_scan_raw_data(cyapa,
|
||||
GEN5_CMD_RETRIEVE_PANEL_SCAN,
|
||||
GEN5_PANEL_SCAN_SELF_RAW_DATA,
|
||||
cyapa->electrodes_x + cyapa->electrodes_y,
|
||||
&raw_cap_self_max, &raw_cap_self_min,
|
||||
&raw_cap_self_ave,
|
||||
NULL);
|
||||
if (error)
|
||||
goto resume_scanning;
|
||||
|
||||
/* 7. Retrieve panel scan, mutual cap diffcount raw data. */
|
||||
error = cyapa_gen5_read_panel_scan_raw_data(cyapa,
|
||||
GEN5_CMD_RETRIEVE_PANEL_SCAN,
|
||||
GEN5_PANEL_SCAN_MUTUAL_DIFFCOUNT,
|
||||
cyapa->electrodes_x * cyapa->electrodes_y,
|
||||
&mutual_diffdata_max, &mutual_diffdata_min,
|
||||
&mutual_diffdata_ave,
|
||||
NULL);
|
||||
if (error)
|
||||
goto resume_scanning;
|
||||
|
||||
/* 8. Retrieve panel scan, self cap diffcount raw data. */
|
||||
error = cyapa_gen5_read_panel_scan_raw_data(cyapa,
|
||||
GEN5_CMD_RETRIEVE_PANEL_SCAN,
|
||||
GEN5_PANEL_SCAN_SELF_DIFFCOUNT,
|
||||
cyapa->electrodes_x + cyapa->electrodes_y,
|
||||
&self_diffdata_max, &self_diffdata_min,
|
||||
&self_diffdata_ave,
|
||||
NULL);
|
||||
if (error)
|
||||
goto resume_scanning;
|
||||
|
||||
/* 9. Retrieve panel scan, mutual cap baseline raw data. */
|
||||
error = cyapa_gen5_read_panel_scan_raw_data(cyapa,
|
||||
GEN5_CMD_RETRIEVE_PANEL_SCAN,
|
||||
GEN5_PANEL_SCAN_MUTUAL_BASELINE,
|
||||
cyapa->electrodes_x * cyapa->electrodes_y,
|
||||
&mutual_baseline_max, &mutual_baseline_min,
|
||||
&mutual_baseline_ave,
|
||||
NULL);
|
||||
if (error)
|
||||
goto resume_scanning;
|
||||
|
||||
/* 10. Retrieve panel scan, self cap baseline raw data. */
|
||||
error = cyapa_gen5_read_panel_scan_raw_data(cyapa,
|
||||
GEN5_CMD_RETRIEVE_PANEL_SCAN,
|
||||
GEN5_PANEL_SCAN_SELF_BASELINE,
|
||||
cyapa->electrodes_x + cyapa->electrodes_y,
|
||||
&self_baseline_max, &self_baseline_min,
|
||||
&self_baseline_ave,
|
||||
NULL);
|
||||
if (error)
|
||||
goto resume_scanning;
|
||||
|
||||
resume_scanning:
|
||||
/* 11. Resume Scanning*/
|
||||
resume_error = cyapa_gen5_resume_scanning(cyapa);
|
||||
if (resume_error || error)
|
||||
return resume_error ? resume_error : error;
|
||||
|
||||
/* 12. Output data strings */
|
||||
size = scnprintf(buf, PAGE_SIZE, "%d %d %d %d %d %d %d %d %d %d %d ",
|
||||
gidac_mutual_min, gidac_mutual_max, gidac_mutual_ave,
|
||||
lidac_mutual_min, lidac_mutual_max, lidac_mutual_ave,
|
||||
gidac_self_rx, gidac_self_tx,
|
||||
lidac_self_min, lidac_self_max, lidac_self_ave);
|
||||
size += scnprintf(buf + size, PAGE_SIZE - size,
|
||||
"%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
|
||||
raw_cap_mutual_min, raw_cap_mutual_max, raw_cap_mutual_ave,
|
||||
raw_cap_self_min, raw_cap_self_max, raw_cap_self_ave,
|
||||
mutual_diffdata_min, mutual_diffdata_max, mutual_diffdata_ave,
|
||||
self_diffdata_min, self_diffdata_max, self_diffdata_ave,
|
||||
mutual_baseline_min, mutual_baseline_max, mutual_baseline_ave,
|
||||
self_baseline_min, self_baseline_max, self_baseline_ave);
|
||||
return size;
|
||||
}
|
||||
|
||||
static bool cyapa_gen5_sort_system_info_data(struct cyapa *cyapa,
|
||||
u8 *buf, int len)
|
||||
{
|
||||
|
@ -2057,6 +2695,8 @@ const struct cyapa_dev_ops cyapa_gen5_ops = {
|
|||
.bl_activate = cyapa_gen5_bl_activate,
|
||||
.bl_deactivate = cyapa_gen5_bl_deactivate,
|
||||
|
||||
.show_baseline = cyapa_gen5_show_baseline,
|
||||
|
||||
.initialize = cyapa_gen5_initialize,
|
||||
|
||||
.state_parse = cyapa_gen5_state_parse,
|
||||
|
|
Loading…
Reference in New Issue