1121 lines
28 KiB
C
1121 lines
28 KiB
C
/*
|
|
* Copyright (C) 2012, Samsung Electronics Co. Ltd. All Rights Reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
*/
|
|
#include "ssp.h"
|
|
|
|
#define LIMIT_DELAY_CNT 200
|
|
#define RECEIVEBUFFERSIZE 12
|
|
#define DEBUG_SHOW_DATA 0
|
|
|
|
void clean_msg(struct ssp_msg *msg)
|
|
{
|
|
if (msg->free_buffer)
|
|
kfree(msg->buffer);
|
|
kfree(msg);
|
|
}
|
|
|
|
static int do_transfer(struct ssp_data *data, struct ssp_msg *msg,
|
|
struct completion *done, int timeout)
|
|
{
|
|
return bbd_do_transfer(data, msg, done, timeout);
|
|
}
|
|
|
|
int ssp_spi_async(struct ssp_data *data, struct ssp_msg *msg)
|
|
{
|
|
int status = 0;
|
|
u64 diff = get_current_timestamp() - data->resumeTimestamp;
|
|
int timeout = diff < 5000000000ULL ? 400 : 1000; // unit: ms
|
|
|
|
if (msg->length)
|
|
return ssp_spi_sync(data, msg, timeout);
|
|
|
|
status = do_transfer(data, msg, NULL, 0);
|
|
|
|
return status;
|
|
}
|
|
|
|
int ssp_spi_sync(struct ssp_data *data, struct ssp_msg *msg, int timeout)
|
|
{
|
|
DECLARE_COMPLETION_ONSTACK(done);
|
|
int status = 0;
|
|
|
|
if (msg->length == 0) {
|
|
pr_err("[SSP]: %s length must not be 0\n", __func__);
|
|
clean_msg(msg);
|
|
return status;
|
|
}
|
|
|
|
status = do_transfer(data, msg, &done, timeout);
|
|
|
|
return status;
|
|
}
|
|
|
|
int select_irq_msg(struct ssp_data *data)
|
|
{
|
|
struct ssp_msg *msg, *n;
|
|
bool found = false;
|
|
u16 chLength = 0, msg_options = 0;
|
|
u8 msg_type = 0;
|
|
int iRet = 0;
|
|
char *buffer;
|
|
char chTempBuf[4] = { -1 };
|
|
|
|
data->bHandlingIrq = true;
|
|
iRet = spi_read(data->spi, chTempBuf, sizeof(chTempBuf));
|
|
if (iRet < 0) {
|
|
pr_err("[SSP] %s spi_read fail, ret = %d\n", __func__, iRet);
|
|
data->bHandlingIrq = false;
|
|
return iRet;
|
|
}
|
|
|
|
memcpy(&msg_options, &chTempBuf[0], 2);
|
|
msg_type = msg_options & SSP_SPI_MASK;
|
|
memcpy(&chLength, &chTempBuf[2], 2);
|
|
|
|
switch (msg_type) {
|
|
case AP2HUB_READ:
|
|
case AP2HUB_WRITE:
|
|
mutex_lock(&data->pending_mutex);
|
|
if (!list_empty(&data->pending_list)) {
|
|
list_for_each_entry_safe(msg, n,
|
|
&data->pending_list, list) {
|
|
|
|
if (msg->options == msg_options) {
|
|
list_del(&msg->list);
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!found) {
|
|
pr_err("[SSP]: %s %d - Not match error\n",
|
|
__func__, msg_options);
|
|
goto exit;
|
|
}
|
|
|
|
if (msg->dead && !msg->free_buffer) {
|
|
msg->buffer = kzalloc(msg->length, GFP_KERNEL);
|
|
msg->free_buffer = 1;
|
|
} /* For dead msg, make a temporary buffer to read. */
|
|
|
|
if (msg_type == AP2HUB_READ) {
|
|
iRet = spi_read(data->spi,
|
|
msg->buffer, msg->length);
|
|
}
|
|
if (msg_type == AP2HUB_WRITE) {
|
|
iRet = spi_write(data->spi,
|
|
msg->buffer, msg->length);
|
|
|
|
if (msg_options & AP2HUB_RETURN) {
|
|
msg->options = AP2HUB_READ
|
|
| AP2HUB_RETURN;
|
|
msg->length = 1;
|
|
list_add_tail(&msg->list,
|
|
&data->pending_list);
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
if (msg->done != NULL && !completion_done(msg->done))
|
|
complete(msg->done);
|
|
if (msg->dead_hook != NULL)
|
|
*(msg->dead_hook) = true;
|
|
|
|
clean_msg(msg);
|
|
} else
|
|
pr_err("[SSP]List empty error(%d)\n", msg_type);
|
|
exit:
|
|
mutex_unlock(&data->pending_mutex);
|
|
break;
|
|
case HUB2AP_WRITE:
|
|
buffer = kzalloc(chLength, GFP_KERNEL);
|
|
iRet = spi_read(data->spi, buffer, chLength);
|
|
if (iRet < 0)
|
|
pr_err("[SSP] %s spi_read fail\n", __func__);
|
|
else
|
|
parse_dataframe(data, buffer, chLength);
|
|
kfree(buffer);
|
|
break;
|
|
default:
|
|
pr_err("[SSP]No type error(%d)\n", msg_type);
|
|
break;
|
|
}
|
|
|
|
if (iRet < 0) {
|
|
pr_err("[SSP]: %s - MSG2SSP_SSD error %d\n", __func__, iRet);
|
|
data->bHandlingIrq = false;
|
|
return ERROR;
|
|
}
|
|
|
|
data->bHandlingIrq = false;
|
|
return SUCCESS;
|
|
}
|
|
|
|
void clean_pending_list(struct ssp_data *data)
|
|
{
|
|
struct ssp_msg *msg, *n;
|
|
|
|
mutex_lock(&data->pending_mutex);
|
|
list_for_each_entry_safe(msg, n, &data->pending_list, list) {
|
|
list_del(&msg->list);
|
|
if (msg->done != NULL && !completion_done(msg->done))
|
|
complete(msg->done);
|
|
if (msg->dead_hook != NULL)
|
|
*(msg->dead_hook) = true;
|
|
|
|
clean_msg(msg);
|
|
}
|
|
mutex_unlock(&data->pending_mutex);
|
|
}
|
|
|
|
int ssp_send_cmd(struct ssp_data *data, char command, int arg)
|
|
{
|
|
int iRet = 0;
|
|
struct ssp_msg *msg = kzalloc(sizeof(*msg), GFP_KERNEL);
|
|
|
|
if (msg == NULL) {
|
|
iRet = -ENOMEM;
|
|
pr_err("[SSP] %s, failed to alloc memory for ssp_msg\n",
|
|
__func__);
|
|
return iRet;
|
|
}
|
|
msg->cmd = command;
|
|
msg->length = 0;
|
|
msg->options = AP2HUB_WRITE;
|
|
msg->data = arg;
|
|
msg->free_buffer = 0;
|
|
|
|
iRet = ssp_spi_async(data, msg);
|
|
if (iRet != SUCCESS) {
|
|
pr_err("[SSP]: %s - command 0x%x failed %d\n",
|
|
__func__, command, iRet);
|
|
return ERROR;
|
|
}
|
|
|
|
ssp_dbg("[SSP]: %s - command 0x%x %d\n", __func__, command, arg);
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
int send_instruction(struct ssp_data *data, u8 uInst,
|
|
u8 uSensorType, u8 *uSendBuf, u16 uLength)
|
|
{
|
|
char command;
|
|
int iRet = 0;
|
|
struct ssp_msg *msg;
|
|
|
|
//u64 current_Ts = 0;
|
|
#ifdef CONFIG_SENSORS_SSP_HIFI_BATCHING
|
|
u64 timestamp;
|
|
#endif
|
|
|
|
if ((!(data->uSensorState & (1ULL << uSensorType)))
|
|
&& (uInst <= CHANGE_DELAY)) {
|
|
pr_err("[SSP]: %s - Bypass Inst Skip! - %u\n",
|
|
__func__, uSensorType);
|
|
return FAIL;
|
|
}
|
|
|
|
if (uSensorType >= SENSOR_MAX && (uInst == ADD_SENSOR || uInst == CHANGE_DELAY)){
|
|
pr_err("[SSP]: %s - Invalid SensorType! - %u\n",
|
|
__func__, uSensorType);
|
|
return FAIL;
|
|
}
|
|
|
|
switch (uInst) {
|
|
case REMOVE_SENSOR:
|
|
command = MSG2SSP_INST_BYPASS_SENSOR_REMOVE;
|
|
break;
|
|
case ADD_SENSOR:
|
|
command = MSG2SSP_INST_BYPASS_SENSOR_ADD;
|
|
#ifdef CONFIG_SENSORS_SSP_HIFI_BATCHING
|
|
timestamp = get_current_timestamp();
|
|
data->lastTimestamp[uSensorType] = data->LastSensorTimeforReset[uSensorType] = timestamp;
|
|
data->ts_avg_buffer_idx[uSensorType] = 0;
|
|
data->ts_avg_buffer_cnt[uSensorType] = 0;
|
|
data->ts_avg_buffer_sum[uSensorType] = 0;
|
|
data->ts_prev_index[uSensorType] = 0;
|
|
data->ts_avg_skip_cnt[uSensorType] = SKIP_CNT_MOVING_AVG_ADD;
|
|
data->ts_last_enable_cmd_time = timestamp;
|
|
memset(data->ts_avg_buffer[uSensorType], 0,
|
|
sizeof(u64)*SIZE_MOVING_AVG_BUFFER);
|
|
#endif
|
|
data->first_sensor_data[uSensorType] = true;
|
|
break;
|
|
case CHANGE_DELAY:
|
|
command = MSG2SSP_INST_CHANGE_DELAY;
|
|
#ifdef CONFIG_SENSORS_SSP_HIFI_BATCHING
|
|
timestamp = get_current_timestamp();
|
|
data->LastSensorTimeforReset[uSensorType] = timestamp;
|
|
data->ts_avg_buffer_idx[uSensorType] = 0;
|
|
data->ts_avg_buffer_cnt[uSensorType] = 0;
|
|
data->ts_avg_buffer_sum[uSensorType] = 0;
|
|
data->ts_prev_index[uSensorType] = 0;
|
|
data->ts_avg_skip_cnt[uSensorType] = SKIP_CNT_MOVING_AVG_CHANGE;
|
|
memset(data->ts_avg_buffer[uSensorType], 0,
|
|
sizeof(u64)*SIZE_MOVING_AVG_BUFFER);
|
|
#endif
|
|
data->first_sensor_data[uSensorType] = true;
|
|
break;
|
|
case GO_SLEEP:
|
|
command = MSG2SSP_AP_STATUS_SLEEP;
|
|
data->uLastAPState = MSG2SSP_AP_STATUS_SLEEP;
|
|
break;
|
|
case REMOVE_LIBRARY:
|
|
command = MSG2SSP_INST_LIBRARY_REMOVE;
|
|
break;
|
|
case ADD_LIBRARY:
|
|
command = MSG2SSP_INST_LIBRARY_ADD;
|
|
break;
|
|
default:
|
|
command = uInst;
|
|
break;
|
|
}
|
|
|
|
msg = kzalloc(sizeof(*msg), GFP_KERNEL);
|
|
if (msg == NULL) {
|
|
iRet = -ENOMEM;
|
|
pr_err("[SSP] %s, failed to alloc memory for ssp_msg\n",
|
|
__func__);
|
|
return iRet;
|
|
}
|
|
msg->cmd = command;
|
|
msg->length = uLength + 1;
|
|
msg->options = AP2HUB_WRITE;
|
|
msg->buffer = kzalloc(uLength + 1, GFP_KERNEL);
|
|
msg->free_buffer = 1;
|
|
|
|
msg->buffer[0] = uSensorType;
|
|
memcpy(&msg->buffer[1], uSendBuf, uLength);
|
|
|
|
ssp_dbg("[SSP]: %s - Inst = 0x%x, Sensor Type = 0x%x, data = %u\n",
|
|
__func__, command, uSensorType, msg->buffer[1]);
|
|
|
|
iRet = ssp_spi_async(data, msg);
|
|
|
|
if (iRet != SUCCESS) {
|
|
pr_err("[SSP]: %s - Instruction CMD Fail %d\n", __func__, iRet);
|
|
return ERROR;
|
|
}
|
|
|
|
if (uInst == ADD_SENSOR || uInst == CHANGE_DELAY) {
|
|
unsigned int BatchTimeforReset = 0;
|
|
//current_Ts = get_current_timestamp();
|
|
if (uLength >= 9)
|
|
BatchTimeforReset = *(unsigned int *)(&uSendBuf[4]);// Add / change normal case, not factory.
|
|
//pr_info("[SSP] %s timeForRest %d", __func__, BatchTimeforReset);
|
|
data->IsBypassMode[uSensorType] = (BatchTimeforReset == 0);
|
|
//pr_info("[SSP] sensor%d mode%d Time %lld\n", uSensorType, data->IsBypassMode[uSensorType], current_Ts);
|
|
}
|
|
return iRet;
|
|
}
|
|
|
|
int send_instruction_sync(struct ssp_data *data, u8 uInst,
|
|
u8 uSensorType, u8 *uSendBuf, u16 uLength)
|
|
{
|
|
char command;
|
|
int iRet = 0;
|
|
char buffer[10] = { 0, };
|
|
struct ssp_msg *msg;
|
|
|
|
//u64 current_Ts = 0;
|
|
#ifdef CONFIG_SENSORS_SSP_HIFI_BATCHING
|
|
u64 timestamp;
|
|
#endif
|
|
|
|
if ((!(data->uSensorState & (1ULL << uSensorType)))
|
|
&& (uInst <= CHANGE_DELAY)) {
|
|
pr_err("[SSP]: %s - Bypass Inst Skip! - %u\n",
|
|
__func__, uSensorType);
|
|
return FAIL;
|
|
}
|
|
|
|
switch (uInst) {
|
|
case REMOVE_SENSOR:
|
|
command = MSG2SSP_INST_BYPASS_SENSOR_REMOVE;
|
|
break;
|
|
case ADD_SENSOR:
|
|
command = MSG2SSP_INST_BYPASS_SENSOR_ADD;
|
|
#ifdef CONFIG_SENSORS_SSP_HIFI_BATCHING
|
|
timestamp = get_current_timestamp();
|
|
data->lastTimestamp[uSensorType] = data->LastSensorTimeforReset[uSensorType] = timestamp;
|
|
data->ts_avg_buffer_idx[uSensorType] = 0;
|
|
data->ts_avg_buffer_cnt[uSensorType] = 0;
|
|
data->ts_avg_buffer_sum[uSensorType] = 0;
|
|
data->ts_prev_index[uSensorType] = 0;
|
|
data->ts_avg_skip_cnt[uSensorType] = SKIP_CNT_MOVING_AVG_ADD;
|
|
data->ts_last_enable_cmd_time = timestamp;
|
|
memset(data->ts_avg_buffer[uSensorType], 0,
|
|
sizeof(u64)*SIZE_MOVING_AVG_BUFFER);
|
|
#endif
|
|
data->first_sensor_data[uSensorType] = true;
|
|
break;
|
|
case CHANGE_DELAY:
|
|
command = MSG2SSP_INST_CHANGE_DELAY;
|
|
#ifdef CONFIG_SENSORS_SSP_HIFI_BATCHING
|
|
timestamp = get_current_timestamp();
|
|
data->LastSensorTimeforReset[uSensorType] = timestamp;
|
|
data->ts_avg_buffer_idx[uSensorType] = 0;
|
|
data->ts_avg_buffer_cnt[uSensorType] = 0;
|
|
data->ts_avg_buffer_sum[uSensorType] = 0;
|
|
data->ts_prev_index[uSensorType] = 0;
|
|
data->ts_avg_skip_cnt[uSensorType] = SKIP_CNT_MOVING_AVG_CHANGE;
|
|
memset(data->ts_avg_buffer[uSensorType], 0,
|
|
sizeof(u64)*SIZE_MOVING_AVG_BUFFER);
|
|
#endif
|
|
data->first_sensor_data[uSensorType] = true;
|
|
break;
|
|
case GO_SLEEP:
|
|
command = MSG2SSP_AP_STATUS_SLEEP;
|
|
data->uLastAPState = MSG2SSP_AP_STATUS_SLEEP;
|
|
break;
|
|
case REMOVE_LIBRARY:
|
|
command = MSG2SSP_INST_LIBRARY_REMOVE;
|
|
break;
|
|
case ADD_LIBRARY:
|
|
command = MSG2SSP_INST_LIBRARY_ADD;
|
|
break;
|
|
default:
|
|
command = uInst;
|
|
break;
|
|
}
|
|
|
|
msg = kzalloc(sizeof(*msg), GFP_KERNEL);
|
|
if (msg == NULL) {
|
|
iRet = -ENOMEM;
|
|
pr_err("[SSP] %s, failed to alloc memory for ssp_msg\n",
|
|
__func__);
|
|
return iRet;
|
|
}
|
|
msg->cmd = command;
|
|
msg->length = uLength + 1;
|
|
msg->options = AP2HUB_WRITE | AP2HUB_RETURN;
|
|
msg->buffer = buffer;
|
|
msg->free_buffer = 0;
|
|
|
|
msg->buffer[0] = uSensorType;
|
|
memcpy(&msg->buffer[1], uSendBuf, uLength);
|
|
|
|
ssp_dbg("[SSP]: %s - Inst Sync = 0x%x, Sensor Type = %u, data = %u\n",
|
|
__func__, command, uSensorType, msg->buffer[0]);
|
|
|
|
iRet = ssp_spi_sync(data, msg, 1000);
|
|
|
|
if (iRet != SUCCESS) {
|
|
pr_err("[SSP]: %s - Instruction CMD Fail %d\n", __func__, iRet);
|
|
return ERROR;
|
|
}
|
|
|
|
if (uInst == ADD_SENSOR || uInst == CHANGE_DELAY) {
|
|
unsigned int BatchTimeforReset = 0;
|
|
//current_Ts = get_current_timestamp();
|
|
if (uLength >= 9)
|
|
BatchTimeforReset = *(unsigned int *)(&uSendBuf[4]);// Add / change normal case, not factory.
|
|
//pr_info("[SSP] %s timeForRest %d", __func__, BatchTimeforReset);
|
|
data->IsBypassMode[uSensorType] = (BatchTimeforReset == 0);
|
|
//pr_info("[SSP] sensor%d mode%d Time %lld\n", uSensorType, data->IsBypassMode[uSensorType], current_Ts);
|
|
}
|
|
return buffer[0];
|
|
}
|
|
|
|
int flush(struct ssp_data *data, u8 uSensorType)
|
|
{
|
|
int iRet = 0;
|
|
char buffer = 0;
|
|
struct ssp_msg *msg = kzalloc(sizeof(*msg), GFP_KERNEL);
|
|
|
|
if (msg == NULL) {
|
|
iRet = -ENOMEM;
|
|
pr_err("[SSP] %s, failed to alloc memory for ssp_msg\n",
|
|
__func__);
|
|
return iRet;
|
|
}
|
|
msg->cmd = MSG2SSP_AP_MCU_BATCH_FLUSH;
|
|
msg->length = 1;
|
|
msg->options = AP2HUB_READ;
|
|
msg->data = uSensorType;
|
|
msg->buffer = &buffer;
|
|
msg->free_buffer = 0;
|
|
|
|
iRet = ssp_spi_sync(data, msg, 1000);
|
|
|
|
if (iRet != SUCCESS) {
|
|
pr_err("[SSP]: %s - fail %d\n", __func__, iRet);
|
|
return ERROR;
|
|
}
|
|
|
|
ssp_dbg("[SSP]: %s Sensor Type = 0x%x, data = %u\n",
|
|
__func__, uSensorType, buffer);
|
|
|
|
return buffer ? 0 : -1;
|
|
}
|
|
|
|
int get_batch_count(struct ssp_data *data, u8 uSensorType)
|
|
{
|
|
int iRet = 0;
|
|
s32 result = 0;
|
|
char buffer[4] = {0, };
|
|
struct ssp_msg *msg = kzalloc(sizeof(*msg), GFP_KERNEL);
|
|
|
|
if (msg == NULL) {
|
|
iRet = -ENOMEM;
|
|
pr_err("[SSP] %s, failed to alloc memory for ssp_msg\n",
|
|
__func__);
|
|
return iRet;
|
|
}
|
|
msg->cmd = MSG2SSP_AP_MCU_BATCH_COUNT;
|
|
msg->length = 4;
|
|
msg->options = AP2HUB_READ;
|
|
msg->data = uSensorType;
|
|
msg->buffer = buffer;
|
|
msg->free_buffer = 0;
|
|
|
|
iRet = ssp_spi_sync(data, msg, 1000);
|
|
|
|
if (iRet != SUCCESS) {
|
|
pr_err("[SSP]: %s - fail %d\n", __func__, iRet);
|
|
return ERROR;
|
|
}
|
|
|
|
memcpy(&result, buffer, 4);
|
|
|
|
ssp_dbg("[SSP]: %s Sensor Type = 0x%x, data = %u\n",
|
|
__func__, uSensorType, result);
|
|
|
|
return result;
|
|
}
|
|
|
|
int get_chipid(struct ssp_data *data)
|
|
{
|
|
int iRet, iReties = 0;
|
|
char buffer = 0;
|
|
struct ssp_msg *msg;
|
|
|
|
retries:
|
|
msg = kzalloc(sizeof(*msg), GFP_KERNEL);
|
|
if (msg == NULL) {
|
|
iRet = -ENOMEM;
|
|
pr_err("[SSP] %s, failed to alloc memory for ssp_msg\n",
|
|
__func__);
|
|
return iRet;
|
|
}
|
|
msg->cmd = MSG2SSP_AP_WHOAMI;
|
|
msg->length = 1;
|
|
msg->options = AP2HUB_READ;
|
|
msg->buffer = &buffer;
|
|
msg->free_buffer = 0;
|
|
|
|
iRet = ssp_spi_sync(data, msg, 1000);
|
|
|
|
if (buffer != DEVICE_ID && iReties++ < 2) {
|
|
mdelay(5);
|
|
pr_err("[SSP] %s - get chip ID retry\n", __func__);
|
|
goto retries;
|
|
}
|
|
|
|
if (iRet == SUCCESS)
|
|
return buffer;
|
|
|
|
pr_err("[SSP] %s - get chip ID failed %d\n", __func__, iRet);
|
|
return ERROR;
|
|
}
|
|
|
|
int set_sensor_position(struct ssp_data *data)
|
|
{
|
|
int iRet = 0;
|
|
struct ssp_msg *msg = kzalloc(sizeof(*msg), GFP_KERNEL);
|
|
|
|
if (msg == NULL) {
|
|
iRet = -ENOMEM;
|
|
pr_err("[SSP] %s, failed to alloc memory for ssp_msg\n",
|
|
__func__);
|
|
return iRet;
|
|
}
|
|
msg->cmd = MSG2SSP_AP_SENSOR_FORMATION;
|
|
msg->length = 3;
|
|
msg->options = AP2HUB_WRITE;
|
|
msg->buffer = kzalloc(3, GFP_KERNEL);
|
|
msg->free_buffer = 1;
|
|
|
|
msg->buffer[0] = data->accel_position;
|
|
msg->buffer[1] = data->accel_position;
|
|
msg->buffer[2] = data->mag_position;
|
|
|
|
iRet = ssp_spi_async(data, msg);
|
|
|
|
pr_info("[SSP] Sensor Posision A : %u, G : %u, M: %u, P: %u\n",
|
|
data->accel_position,
|
|
data->accel_position,
|
|
data->mag_position, 0);
|
|
|
|
if (iRet != SUCCESS) {
|
|
pr_err("[SSP] %s -fail to %s %d\n",
|
|
__func__, __func__, iRet);
|
|
iRet = ERROR;
|
|
}
|
|
|
|
return iRet;
|
|
}
|
|
|
|
#ifdef CONFIG_SENSORS_MULTIPLE_GLASS_TYPE
|
|
int set_glass_type(struct ssp_data *data)
|
|
{
|
|
int iRet = 0;
|
|
struct ssp_msg *msg = kzalloc(sizeof(*msg), GFP_KERNEL);
|
|
|
|
if (msg == NULL) {
|
|
iRet = -ENOMEM;
|
|
pr_err("[SSP] %s, failed to alloc memory for ssp_msg\n",
|
|
__func__);
|
|
return iRet;
|
|
}
|
|
msg->cmd = MSG2SSP_AP_GLASS_TYPE;
|
|
msg->length = 1;
|
|
msg->options = AP2HUB_WRITE;
|
|
msg->buffer = kzalloc(1, GFP_KERNEL);
|
|
msg->free_buffer = 1;
|
|
|
|
msg->buffer[0] = data->glass_type;
|
|
|
|
iRet = ssp_spi_async(data, msg);
|
|
|
|
pr_info("[SSP] glass_type : %u\n", data->glass_type);
|
|
|
|
if (iRet != SUCCESS) {
|
|
pr_err("[SSP] %s -fail to %s %d\n",
|
|
__func__, __func__, iRet);
|
|
iRet = ERROR;
|
|
}
|
|
|
|
return iRet;
|
|
}
|
|
#endif
|
|
|
|
int set_magnetic_static_matrix(struct ssp_data *data)
|
|
{
|
|
int iRet = 0;
|
|
struct ssp_msg *msg = kzalloc(sizeof(*msg), GFP_KERNEL);
|
|
|
|
if (msg == NULL) {
|
|
iRet = -ENOMEM;
|
|
pr_err("[SSP] %s, failed to alloc memory for ssp_msg\n",
|
|
__func__);
|
|
return iRet;
|
|
}
|
|
msg->cmd = MSG2SSP_AP_SET_MAGNETIC_STATIC_MATRIX;
|
|
msg->length = data->mag_matrix_size;
|
|
msg->options = AP2HUB_WRITE;
|
|
msg->buffer = kzalloc(data->mag_matrix_size, GFP_KERNEL);
|
|
msg->free_buffer = 1;
|
|
|
|
memcpy(msg->buffer, data->mag_matrix, data->mag_matrix_size);
|
|
|
|
iRet = ssp_spi_async(data, msg);
|
|
if (iRet != SUCCESS) {
|
|
pr_err("[SSP] %s -fail to %s %d\n",
|
|
__func__, __func__, iRet);
|
|
iRet = ERROR;
|
|
}
|
|
|
|
return iRet;
|
|
}
|
|
|
|
void set_proximity_threshold(struct ssp_data *data)
|
|
{
|
|
int iRet = 0;
|
|
|
|
struct ssp_msg *msg;
|
|
|
|
if (!(data->uSensorState & (1 << PROXIMITY_SENSOR))) {
|
|
pr_info("[SSP]: %s - Skip this function!!!,proximity sensor is not connected(0x%llx)\n",
|
|
__func__, data->uSensorState);
|
|
return;
|
|
}
|
|
|
|
msg = kzalloc(sizeof(*msg), GFP_KERNEL);
|
|
#if defined(CONFIG_SENSORS_SSP_TMG399x)
|
|
msg->cmd = MSG2SSP_AP_SENSOR_PROXTHRESHOLD;
|
|
msg->length = 2;
|
|
msg->options = AP2HUB_WRITE;
|
|
msg->buffer = kzalloc(2, GFP_KERNEL);
|
|
msg->free_buffer = 1;
|
|
|
|
msg->buffer[0] = (char)data->uProxHiThresh;
|
|
msg->buffer[1] = (char)data->uProxLoThresh;
|
|
#elif defined(CONFIG_SENSORS_SSP_PROX_AUTOCAL_AMS)
|
|
msg->cmd = MSG2SSP_AP_SENSOR_PROXTHRESHOLD;
|
|
msg->length = 8;
|
|
msg->options = AP2HUB_WRITE;
|
|
msg->buffer = kzalloc(8, GFP_KERNEL);
|
|
msg->free_buffer = 1;
|
|
|
|
msg->buffer[0] = ((char) (data->uProxHiThresh >> 8) & 0xff);
|
|
msg->buffer[1] = (char) data->uProxHiThresh;
|
|
msg->buffer[2] = ((char) (data->uProxLoThresh >> 8) & 0xff);
|
|
msg->buffer[3] = (char) data->uProxLoThresh;
|
|
msg->buffer[4] = ((char) (data->uProxHiThresh_detect >> 8) & 0xff);
|
|
msg->buffer[5] = (char) data->uProxHiThresh_detect;
|
|
msg->buffer[6] = ((char) (data->uProxLoThresh_detect >> 8) & 0xff);
|
|
msg->buffer[7] = (char) data->uProxLoThresh_detect;
|
|
#else /* CONFIG_SENSORS_SSP_PROX_FACTORYCAL */
|
|
msg->cmd = MSG2SSP_AP_SENSOR_PROXTHRESHOLD;
|
|
msg->length = 4;
|
|
msg->options = AP2HUB_WRITE;
|
|
msg->buffer = kzalloc(4, GFP_KERNEL);
|
|
msg->free_buffer = 1;
|
|
|
|
msg->buffer[0] = ((char) (data->uProxHiThresh >> 8) & 0xff);
|
|
msg->buffer[1] = (char) data->uProxHiThresh;
|
|
msg->buffer[2] = ((char) (data->uProxLoThresh >> 8) & 0xff);
|
|
msg->buffer[3] = (char) data->uProxLoThresh;
|
|
#endif
|
|
|
|
iRet = ssp_spi_async(data, msg);
|
|
|
|
if (iRet != SUCCESS) {
|
|
pr_err("[SSP]: %s - SENSOR_PROXTHRESHOLD CMD fail %d\n",
|
|
__func__, iRet);
|
|
return;
|
|
}
|
|
|
|
#if defined(CONFIG_SENSORS_SSP_PROX_AUTOCAL_AMS)
|
|
pr_info("[SSP]: Proximity Threshold - %u, %u, %u, %u\n",
|
|
data->uProxHiThresh, data->uProxLoThresh,
|
|
data->uProxHiThresh_detect, data->uProxLoThresh_detect);
|
|
#else
|
|
pr_info("[SSP]: Proximity Threshold - %u, %u\n",
|
|
data->uProxHiThresh, data->uProxLoThresh);
|
|
#endif
|
|
}
|
|
|
|
void set_proximity_alert_threshold(struct ssp_data *data)
|
|
{
|
|
int iRet = 0;
|
|
|
|
struct ssp_msg *msg;
|
|
|
|
if (!(data->uSensorState & (1 << PROXIMITY_ALERT_SENSOR))) {
|
|
pr_info("[SSP]: %s - Skip this function!!!,proximity alert sensor is not connected(0x%llx)\n",
|
|
__func__, data->uSensorState);
|
|
return;
|
|
}
|
|
|
|
msg = kzalloc(sizeof(*msg), GFP_KERNEL);
|
|
|
|
msg->cmd = MSG2SSP_AP_SENSOR_PROX_ALERT_THRESHOLD;
|
|
msg->length = 2;
|
|
msg->options = AP2HUB_WRITE;
|
|
msg->buffer = kzalloc(2, GFP_KERNEL);
|
|
msg->free_buffer = 1;
|
|
|
|
msg->buffer[0] = ((char) (data->uProxAlertHiThresh >> 8) & 0xff);
|
|
msg->buffer[1] = (char) data->uProxAlertHiThresh;
|
|
|
|
iRet = ssp_spi_async(data, msg);
|
|
|
|
if (iRet != SUCCESS) {
|
|
pr_err("[SSP]: %s - SENSOR_PROX_ALERT_THRESHOLD CMD fail %d\n",
|
|
__func__, iRet);
|
|
return;
|
|
}
|
|
|
|
pr_info("[SSP]: %s Proximity alert Threshold - %u\n",
|
|
__func__, data->uProxAlertHiThresh);
|
|
}
|
|
|
|
void set_light_coef(struct ssp_data *data)
|
|
{
|
|
int iRet = 0;
|
|
struct ssp_msg *msg;
|
|
|
|
if (!(data->uSensorState & (1 << LIGHT_SENSOR))) {
|
|
pr_info("[SSP]: %s - Skip this function!!!,light sensor is not connected(0x%llx)\n",
|
|
__func__, data->uSensorState);
|
|
return;
|
|
}
|
|
|
|
msg = kzalloc(sizeof(*msg), GFP_KERNEL);
|
|
|
|
msg->cmd = MSG2SSP_AP_SET_LIGHT_COEF;
|
|
msg->length = sizeof(data->light_coef);
|
|
msg->options = AP2HUB_WRITE;
|
|
msg->buffer = kzalloc(sizeof(data->light_coef), GFP_KERNEL);
|
|
msg->free_buffer = 1;
|
|
|
|
memcpy(msg->buffer, data->light_coef, sizeof(data->light_coef));
|
|
|
|
iRet = ssp_spi_async(data, msg);
|
|
|
|
if (iRet != SUCCESS) {
|
|
pr_err("[SSP]: %s - MSG2SSP_AP_SET_LIGHT_COEF CMD fail %d\n",
|
|
__func__, iRet);
|
|
return;
|
|
}
|
|
|
|
pr_info("[SSP]: %s - %d %d %d %d %d %d %d\n", __func__,
|
|
data->light_coef[0], data->light_coef[1], data->light_coef[2],
|
|
data->light_coef[3], data->light_coef[4], data->light_coef[5], data->light_coef[6]);
|
|
}
|
|
|
|
void set_proximity_barcode_enable(struct ssp_data *data, bool bEnable)
|
|
{
|
|
int iRet = 0;
|
|
struct ssp_msg *msg = kzalloc(sizeof(*msg), GFP_KERNEL);
|
|
|
|
msg->cmd = MSG2SSP_AP_SENSOR_BARCODE_EMUL;
|
|
msg->length = 1;
|
|
msg->options = AP2HUB_WRITE;
|
|
msg->buffer = kzalloc(1, GFP_KERNEL);
|
|
msg->free_buffer = 1;
|
|
|
|
data->bBarcodeEnabled = bEnable;
|
|
msg->buffer[0] = bEnable;
|
|
|
|
iRet = ssp_spi_async(data, msg);
|
|
if (iRet != SUCCESS) {
|
|
pr_err("[SSP]: %s - SENSOR_BARCODE_EMUL CMD fail %d\n",
|
|
__func__, iRet);
|
|
return;
|
|
}
|
|
|
|
pr_info("[SSP] Proximity Barcode En : %u\n", bEnable);
|
|
}
|
|
|
|
void set_gesture_current(struct ssp_data *data, unsigned char uData1)
|
|
{
|
|
int iRet = 0;
|
|
struct ssp_msg *msg = kzalloc(sizeof(*msg), GFP_KERNEL);
|
|
|
|
msg->cmd = MSG2SSP_AP_SENSOR_GESTURE_CURRENT;
|
|
msg->length = 1;
|
|
msg->options = AP2HUB_WRITE;
|
|
msg->buffer = kzalloc(1, GFP_KERNEL);
|
|
msg->free_buffer = 1;
|
|
|
|
msg->buffer[0] = uData1;
|
|
iRet = ssp_spi_async(data, msg);
|
|
if (iRet != SUCCESS) {
|
|
pr_err("[SSP]: %s - SENSOR_GESTURE_CURRENT CMD fail %d\n",
|
|
__func__, iRet);
|
|
return;
|
|
}
|
|
|
|
pr_info("[SSP]: Gesture Current Setting - %u\n", uData1);
|
|
}
|
|
|
|
int set_hall_threshold(struct ssp_data *data)
|
|
{
|
|
int iRet = 0;
|
|
struct ssp_msg *msg = kzalloc(sizeof(*msg), GFP_KERNEL);
|
|
|
|
if (msg == NULL) {
|
|
iRet = -ENOMEM;
|
|
pr_err("[SSP]: %s - failed to alloc memory for ssp_msg\n",
|
|
__func__);
|
|
return iRet;
|
|
}
|
|
|
|
msg->cmd = MSG2SSP_AP_SET_HALL_THRESHOLD;
|
|
msg->length = sizeof(data->hall_threshold);
|
|
msg->options = AP2HUB_WRITE;
|
|
msg->buffer = kzalloc(sizeof(data->hall_threshold), GFP_KERNEL);
|
|
msg->free_buffer = 1;
|
|
|
|
memcpy(msg->buffer, data->hall_threshold,
|
|
sizeof(data->hall_threshold));
|
|
|
|
iRet = ssp_spi_async(data, msg);
|
|
if (iRet != SUCCESS) {
|
|
pr_err("[SSP]: %s - fail to %s %d\n",
|
|
__func__, __func__, iRet);
|
|
iRet = ERROR;
|
|
}
|
|
|
|
return iRet;
|
|
}
|
|
|
|
u64 get_sensor_scanning_info(struct ssp_data *data)
|
|
{
|
|
int iRet = 0, z = 0;
|
|
u64 result = 0;
|
|
struct ssp_msg *msg = kzalloc(sizeof(*msg), GFP_KERNEL);
|
|
|
|
if (msg == NULL) {
|
|
iRet = -ENOMEM;
|
|
pr_err("[SSP] %s, failed to alloc memory for ssp_msg\n",
|
|
__func__);
|
|
return iRet;
|
|
}
|
|
msg->cmd = MSG2SSP_AP_SENSOR_SCANNING;
|
|
msg->length = 8;
|
|
msg->options = AP2HUB_READ;
|
|
msg->buffer = (char *) &result;
|
|
msg->free_buffer = 0;
|
|
|
|
iRet = ssp_spi_sync(data, msg, 1000);
|
|
|
|
if (iRet != SUCCESS)
|
|
pr_err("[SSP]: %s - i2c fail %d\n", __func__, iRet);
|
|
|
|
data->sensor_state[SENSOR_MAX] = '\0';
|
|
for (z = 0; z < SENSOR_MAX; z++)
|
|
data->sensor_state[SENSOR_MAX - 1 - z] = (result & (1ULL << z)) ? '1' : '0';
|
|
pr_err("[SSP]: state: %s\n", data->sensor_state);
|
|
|
|
return result;
|
|
}
|
|
|
|
unsigned int get_firmware_rev(struct ssp_data *data)
|
|
{
|
|
int iRet;
|
|
u32 result = SSP_INVALID_REVISION;
|
|
struct ssp_msg *msg = kzalloc(sizeof(*msg), GFP_KERNEL);
|
|
|
|
if (msg == NULL) {
|
|
iRet = -ENOMEM;
|
|
pr_err("[SSP] %s, failed to alloc memory for ssp_msg\n",
|
|
__func__);
|
|
return iRet;
|
|
}
|
|
msg->cmd = MSG2SSP_AP_FIRMWARE_REV;
|
|
msg->length = 4;
|
|
msg->options = AP2HUB_READ;
|
|
msg->buffer = (char *) &result;
|
|
msg->free_buffer = 0;
|
|
|
|
iRet = ssp_spi_sync(data, msg, 1000);
|
|
if (iRet != SUCCESS)
|
|
pr_err("[SSP]: %s - transfer fail %d\n", __func__, iRet);
|
|
|
|
return result;
|
|
}
|
|
|
|
int set_big_data_start(struct ssp_data *data, u8 type, u32 length)
|
|
{
|
|
int iRet = 0;
|
|
struct ssp_msg *msg = kzalloc(sizeof(*msg), GFP_KERNEL);
|
|
|
|
if (msg == NULL) {
|
|
iRet = -ENOMEM;
|
|
pr_err("[SSP] %s, failed to alloc memory for ssp_msg\n",
|
|
__func__);
|
|
return iRet;
|
|
}
|
|
msg->cmd = MSG2SSP_AP_START_BIG_DATA;
|
|
msg->length = 5;
|
|
msg->options = AP2HUB_WRITE;
|
|
msg->buffer = kzalloc(5, GFP_KERNEL);
|
|
msg->free_buffer = 1;
|
|
|
|
msg->buffer[0] = type;
|
|
memcpy(&msg->buffer[1], &length, 4);
|
|
|
|
iRet = ssp_spi_async(data, msg);
|
|
|
|
if (iRet != SUCCESS) {
|
|
pr_err("[SSP]: %s - i2c fail %d\n", __func__, iRet);
|
|
iRet = ERROR;
|
|
}
|
|
|
|
return iRet;
|
|
}
|
|
|
|
int set_time(struct ssp_data *data)
|
|
{
|
|
int iRet;
|
|
struct ssp_msg *msg;
|
|
struct timespec ts;
|
|
struct rtc_time tm;
|
|
|
|
getnstimeofday(&ts);
|
|
rtc_time_to_tm(ts.tv_sec, &tm);
|
|
pr_info("[SSP]: %s %d-%02d-%02d %02d:%02d:%02d.%09lu UTC\n",
|
|
__func__,
|
|
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
|
|
tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec);
|
|
|
|
msg = kzalloc(sizeof(*msg), GFP_KERNEL);
|
|
if (msg == NULL) {
|
|
iRet = -ENOMEM;
|
|
pr_err("[SSP] %s, failed to alloc memory for ssp_msg\n",
|
|
__func__);
|
|
return iRet;
|
|
}
|
|
msg->cmd = MSG2SSP_AP_MCU_SET_TIME;
|
|
msg->length = 12;
|
|
msg->options = AP2HUB_WRITE;
|
|
msg->buffer = kzalloc(12, GFP_KERNEL);
|
|
msg->free_buffer = 1;
|
|
|
|
msg->buffer[0] = tm.tm_hour;
|
|
msg->buffer[1] = tm.tm_min;
|
|
msg->buffer[2] = tm.tm_sec;
|
|
msg->buffer[3] = tm.tm_hour > 11 ? 64 : 0;
|
|
msg->buffer[4] = tm.tm_wday;
|
|
msg->buffer[5] = tm.tm_mon + 1;
|
|
msg->buffer[6] = tm.tm_mday;
|
|
msg->buffer[7] = tm.tm_year % 100;
|
|
memcpy(&msg->buffer[8], &ts.tv_nsec, 4);
|
|
|
|
iRet = ssp_spi_async(data, msg);
|
|
|
|
if (iRet != SUCCESS) {
|
|
pr_err("[SSP]: %s - i2c fail %d\n", __func__, iRet);
|
|
iRet = ERROR;
|
|
}
|
|
|
|
return iRet;
|
|
}
|
|
|
|
int get_time(struct ssp_data *data)
|
|
{
|
|
int iRet;
|
|
char buffer[12] = { 0, };
|
|
struct ssp_msg *msg;
|
|
struct timespec ts;
|
|
struct rtc_time tm;
|
|
|
|
getnstimeofday(&ts);
|
|
rtc_time_to_tm(ts.tv_sec, &tm);
|
|
pr_info("[SSP]: %s ap %d-%02d-%02d %02d:%02d:%02d.%09lu UTC\n",
|
|
__func__,
|
|
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
|
|
tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec);
|
|
|
|
msg = kzalloc(sizeof(*msg), GFP_KERNEL);
|
|
if (msg == NULL) {
|
|
iRet = -ENOMEM;
|
|
pr_err("[SSP] %s, failed to alloc memory for ssp_msg\n",
|
|
__func__);
|
|
return iRet;
|
|
}
|
|
msg->cmd = MSG2SSP_AP_MCU_GET_TIME;
|
|
msg->length = 12;
|
|
msg->options = AP2HUB_READ;
|
|
msg->buffer = buffer;
|
|
msg->free_buffer = 0;
|
|
|
|
iRet = ssp_spi_sync(data, msg, 1000);
|
|
|
|
if (iRet != SUCCESS) {
|
|
pr_err("[SSP]: %s - i2c failed %d\n", __func__, iRet);
|
|
return 0;
|
|
}
|
|
|
|
tm.tm_hour = buffer[0];
|
|
tm.tm_min = buffer[1];
|
|
tm.tm_sec = buffer[2];
|
|
tm.tm_mon = msg->buffer[5] - 1;
|
|
tm.tm_mday = buffer[6];
|
|
tm.tm_year = buffer[7] + 100;
|
|
rtc_tm_to_time(&tm, &ts.tv_sec);
|
|
memcpy(&ts.tv_nsec, &msg->buffer[8], 4);
|
|
|
|
rtc_time_to_tm(ts.tv_sec, &tm);
|
|
pr_info("[SSP]: %s mcu %d-%02d-%02d %02d:%02d:%02d.%09lu UTC\n",
|
|
__func__,
|
|
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
|
|
tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec);
|
|
|
|
return iRet;
|
|
}
|
|
|
|
void set_gyro_cal_lib_enable(struct ssp_data *data, bool bEnable)
|
|
{
|
|
int iRet = 0;
|
|
u8 cmd;
|
|
struct ssp_msg *msg;
|
|
|
|
pr_info("[SSP] %s - enable %d(cur %d)\n", __func__, bEnable, data->gyro_lib_state);
|
|
|
|
if (bEnable)
|
|
cmd = SH_MSG2AP_GYRO_CALIBRATION_START;
|
|
else
|
|
cmd = SH_MSG2AP_GYRO_CALIBRATION_STOP;
|
|
|
|
msg = kzalloc(sizeof(*msg), GFP_KERNEL);
|
|
|
|
msg->cmd = cmd;
|
|
msg->length = 1;
|
|
msg->options = AP2HUB_WRITE;
|
|
msg->buffer = kzalloc(1, GFP_KERNEL);
|
|
msg->free_buffer = 1;
|
|
|
|
msg->buffer[0] = bEnable;
|
|
|
|
iRet = ssp_spi_async(data, msg);
|
|
|
|
if (iRet == SUCCESS) {
|
|
if (bEnable)
|
|
data->gyro_lib_state = GYRO_CALIBRATION_STATE_REGISTERED;
|
|
else
|
|
data->gyro_lib_state = GYRO_CALIBRATION_STATE_DONE;
|
|
} else
|
|
pr_err("[SSP] %s - gyro lib enable cmd fail\n", __func__);
|
|
|
|
}
|
|
|
|
#if defined(CONFIG_SSP_MOTOR_CALLBACK)
|
|
int send_motor_state(struct ssp_data *data)
|
|
{
|
|
int iRet = 0;
|
|
struct ssp_msg *msg;
|
|
|
|
msg = kzalloc(sizeof(*msg), GFP_KERNEL);
|
|
|
|
msg->cmd = MSG2SSP_AP_MCU_SET_MOTOR_STATUS;
|
|
msg->length = 1;
|
|
msg->options = AP2HUB_WRITE;
|
|
msg->buffer = kzalloc(1, GFP_KERNEL);
|
|
msg->free_buffer = 1;
|
|
|
|
/*if 1: start, 0: stop*/
|
|
msg->buffer[0] = data->motor_state;
|
|
|
|
iRet = ssp_spi_async(data, msg);
|
|
if (iRet != SUCCESS) {
|
|
pr_err("[SSP]: %s - fail %d\n",
|
|
__func__, iRet);
|
|
return iRet;
|
|
}
|
|
pr_info("[SSP] %s - En : %u\n", __func__, data->motor_state);
|
|
return data->motor_state;
|
|
}
|
|
#endif
|
|
u8 get_accel_range(struct ssp_data *data)
|
|
{
|
|
int iRet = 0;
|
|
struct ssp_msg *msg;
|
|
u8 rxbuffer[1] = {0x00};
|
|
|
|
msg = kzalloc(sizeof(*msg), GFP_KERNEL);
|
|
|
|
msg->cmd = MSG2SSP_AP_MCU_GET_ACCEL_RANGE;
|
|
msg->length = 1;
|
|
msg->options = AP2HUB_READ;
|
|
msg->buffer = rxbuffer;
|
|
msg->free_buffer = 0;
|
|
|
|
iRet = ssp_spi_sync(data, msg, 1000);
|
|
if (iRet != SUCCESS) {
|
|
pr_err("[SSP]: %s - fail %d\n",
|
|
__func__, iRet);
|
|
return iRet;
|
|
}
|
|
|
|
pr_info("[SSP] %s - Range : %u\n", __func__, rxbuffer[0]);
|
|
return rxbuffer[0];
|
|
}
|
|
|
|
|