blob: 37e1522ee2d2531bc21f0d06f4adb34895b69ec5 [file] [log] [blame]
/*
* 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_ap_information(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_INFORMATION;
msg->length = 2;
msg->options = AP2HUB_WRITE;
msg->buffer = kzalloc(2, GFP_KERNEL);
msg->free_buffer = 1;
msg->buffer[0] = (char)data->ap_type;
msg->buffer[1] = (char)data->ap_rev;
iRet = ssp_spi_async(data, msg);
pr_info("[SSP] AP TYPE = %d AP REV = %d\n", data->ap_type, data->ap_rev);
if (iRet != SUCCESS) {
pr_err("[SSP] %s -fail to %s %d\n",
__func__, __func__, iRet);
iRet = ERROR;
}
return iRet;
}
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, efs file status %d\n",
data->uProxHiThresh, data->uProxLoThresh,
data->uProxHiThresh_detect, data->uProxLoThresh_detect, data->light_efs_file_status);
#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, cnt = 1;
u64 result = 0, len = sizeof(data->sensor_state);
struct ssp_msg *msg = kzalloc(sizeof(*msg), GFP_KERNEL);
#if defined (CONFIG_SENSORS_SSP_DAVINCI)
int disable_sensor_type[10] = {7,9,10,24,30,31,32,35,39,40};
#endif
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);
for (z = 0; z < SENSOR_MAX; z++) {
if(z % 10 == 0 && z != 0)
data->sensor_state[len - 1 - cnt++] = ' ';
data->sensor_state[len - 1 - cnt++] = (result & (1ULL << z)) ? '1' : '0';
}
data->sensor_state[cnt - 1] = '\0';
#if defined (CONFIG_SENSORS_SSP_DAVINCI)
if (data->ap_rev == 18 && data->ap_type <= 1) {
int j;
iRet = 0; len = 0;
for (j = 0; j < SENSOR_MAX; j++) {
if (disable_sensor_type[iRet] == j) {
iRet++;
continue;
}
if (result & (1ULL << j))
len |= (1ULL << j);
}
// for(int i = 0; i < ARRAY_SIZE(disable_sensor_type); i++) {
// data->sensor_state[sizeof(data->sensor_state)- (disable_sensor_type[i] + (disable_sensor_type[i] / 10)+1)] = '0'; // divide 10 for blank
// }
result = len;
} // D1 D1x && hw _rev 18 disable prox light sensor type
#endif
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];
}