123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809 |
- /*
- * 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 <linux/init.h>
- #include <linux/module.h>
- #include "adsp.h"
- #ifdef CONFIG_SEC_VIB_NOTIFIER
- #include <linux/vibrator/sec_vibrator_notifier.h>
- #endif
- #define VENDOR "STM"
- #if IS_ENABLED(CONFIG_LSM6DSV_FACTORY)
- #define CHIP_ID "LSM6DSV"
- #else
- #define CHIP_ID "LSM6DSO"
- #endif
- #define ACCEL_ST_TRY_CNT 3
- #define ACCEL_FACTORY_CAL_CNT 20
- #define ACCEL_RAW_DATA_CNT 3
- #define MAX_ACCEL_1G 2048
- #define STM_LSM6DSO_INT_CHECK_RUNNING 4
- #define MAX_MOTOR_STOP_TIMEOUT (8 * NSEC_PER_SEC)
- /* Haptic Pattern A vibrate during 7ms.
- * touch, touchkey, operation feedback use this.
- * Do not call motor_workfunc when duration is 7ms.
- */
- #define DURATION_SKIP 10
- #define MOTOR_OFF 0
- #define MOTOR_ON 1
- #define CALL_VIB_IDX 65534
- #ifdef CONFIG_SEC_VIB_NOTIFIER
- struct accel_motor_data {
- struct notifier_block motor_nb;
- struct hrtimer motor_stop_timer;
- struct workqueue_struct *slpi_motor_wq;
- struct work_struct work_slpi_motor;
- atomic_t motor_state;
- int idx;
- int timeout;
- };
- struct accel_motor_data *pdata_motor;
- #endif
- struct accel_data {
- struct work_struct work_accel;
- struct workqueue_struct *accel_wq;
- struct adsp_data *dev_data;
- bool is_complete_cal;
- bool lpf_onoff;
- bool st_complete;
- int32_t raw_data[ACCEL_RAW_DATA_CNT];
- int32_t avg_data[ACCEL_RAW_DATA_CNT];
- };
- static struct accel_data *pdata;
- static bool is_ignore_crash_factory = false;
- static ssize_t accel_vendor_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- return snprintf(buf, PAGE_SIZE, "%s\n", VENDOR);
- }
- static ssize_t accel_name_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- return snprintf(buf, PAGE_SIZE, "%s\n", CHIP_ID);
- }
- static ssize_t sensor_type_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- return snprintf(buf, PAGE_SIZE, "%s\n", "ADSP");
- }
- int get_accel_cal_data(struct adsp_data *data, int32_t *cal_data)
- {
- uint8_t cnt = 0;
- adsp_unicast(NULL, 0, MSG_ACCEL, 0, MSG_TYPE_GET_CAL_DATA);
- while (!(data->ready_flag[MSG_TYPE_GET_CAL_DATA] & 1 << MSG_ACCEL) &&
- cnt++ < TIMEOUT_CNT)
- usleep_range(500, 550);
- data->ready_flag[MSG_TYPE_GET_CAL_DATA] &= ~(1 << MSG_ACCEL);
- if (cnt >= TIMEOUT_CNT) {
- pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
- return 0;
- }
- if (data->msg_buf[MSG_ACCEL][3] != ACCEL_RAW_DATA_CNT) {
- pr_err("[FACTORY] %s: Reading Bytes Num %d!!!\n",
- __func__, data->msg_buf[MSG_ACCEL][3]);
- return 0;
- }
- cal_data[0] = data->msg_buf[MSG_ACCEL][0];
- cal_data[1] = data->msg_buf[MSG_ACCEL][1];
- cal_data[2] = data->msg_buf[MSG_ACCEL][2];
- pr_info("[FACTORY] %s: %d, %d, %d, %d\n", __func__,
- cal_data[0], cal_data[1], cal_data[2],
- data->msg_buf[MSG_ACCEL][3]);
- return data->msg_buf[MSG_ACCEL][3];
- }
- void set_accel_cal_data(struct adsp_data *data)
- {
- uint8_t cnt = 0;
- pr_info("[FACTORY] %s: %d, %d, %d\n", __func__, pdata->avg_data[0],
- pdata->avg_data[1], pdata->avg_data[2]);
- adsp_unicast(pdata->avg_data, sizeof(pdata->avg_data),
- MSG_ACCEL, 0, MSG_TYPE_SET_CAL_DATA);
- while (!(data->ready_flag[MSG_TYPE_SET_CAL_DATA] & 1 << MSG_ACCEL) &&
- cnt++ < TIMEOUT_CNT)
- usleep_range(500, 550);
- data->ready_flag[MSG_TYPE_SET_CAL_DATA] &= ~(1 << MSG_ACCEL);
- if (cnt >= TIMEOUT_CNT) {
- pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
- } else if (data->msg_buf[MSG_ACCEL][0] != ACCEL_RAW_DATA_CNT) {
- pr_err("[FACTORY] %s: Write Bytes Num %d!!!\n",
- __func__, data->msg_buf[MSG_ACCEL][0]);
- }
- }
- static ssize_t accel_calibration_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct adsp_data *data = dev_get_drvdata(dev);
- int32_t cal_data[ACCEL_RAW_DATA_CNT] = {0, };
- int ret = 0;
- mutex_lock(&data->accel_factory_mutex);
- ret = get_accel_cal_data(data, cal_data);
- mutex_unlock(&data->accel_factory_mutex);
- if (ret > 0) {
- pr_info("[FACTORY] %s: %d, %d, %d\n", __func__,
- cal_data[0], cal_data[1], cal_data[2]);
- if (cal_data[0] == 0 && cal_data[1] == 0 && cal_data[2] == 0)
- return snprintf(buf, PAGE_SIZE, "%d,%d,%d,%d\n",
- 0, 0, 0, 0);
- else
- return snprintf(buf, PAGE_SIZE, "%d,%d,%d,%d\n",
- true, cal_data[0], cal_data[1], cal_data[2]);
- } else {
- pr_err("[FACTORY] %s: get_accel_cal_data fail\n", __func__);
- return snprintf(buf, PAGE_SIZE, "%d,%d,%d,%d\n", 0, 0, 0, 0);
- }
- }
- static ssize_t accel_calibration_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
- {
- struct adsp_data *data = dev_get_drvdata(dev);
- pdata->dev_data = data;
- if (sysfs_streq(buf, "0")) {
- mutex_lock(&data->accel_factory_mutex);
- memset(pdata->avg_data, 0, sizeof(pdata->avg_data));
- set_accel_cal_data(data);
- mutex_unlock(&data->accel_factory_mutex);
- } else {
- pdata->is_complete_cal = false;
- queue_work(pdata->accel_wq, &pdata->work_accel);
- while (pdata->is_complete_cal == false) {
- pr_info("[FACTORY] %s: In factory cal\n", __func__);
- msleep(20);
- }
- mutex_lock(&data->accel_factory_mutex);
- set_accel_cal_data(data);
- mutex_unlock(&data->accel_factory_mutex);
- }
- return size;
- }
- static void accel_work_func(struct work_struct *work)
- {
- struct accel_data *data = container_of((struct work_struct *)work,
- struct accel_data, work_accel);
- int i;
- mutex_lock(&data->dev_data->accel_factory_mutex);
- memset(pdata->avg_data, 0, sizeof(pdata->avg_data));
- adsp_unicast(pdata->avg_data, sizeof(pdata->avg_data),
- MSG_ACCEL, 0, MSG_TYPE_SET_CAL_DATA);
- msleep(30); /* for init of bias */
- for (i = 0; i < ACCEL_FACTORY_CAL_CNT; i++) {
- msleep(20);
- get_accel_raw_data(pdata->raw_data);
- pdata->avg_data[0] += pdata->raw_data[0];
- pdata->avg_data[1] += pdata->raw_data[1];
- pdata->avg_data[2] += pdata->raw_data[2];
- pr_info("[FACTORY] %s: %d, %d, %d\n", __func__,
- pdata->raw_data[0], pdata->raw_data[1],
- pdata->raw_data[2]);
- }
- for (i = 0; i < ACCEL_RAW_DATA_CNT; i++) {
- pdata->avg_data[i] /= ACCEL_FACTORY_CAL_CNT;
- pr_info("[FACTORY] %s: avg : %d\n",
- __func__, pdata->avg_data[i]);
- }
- if (pdata->avg_data[2] > 0)
- pdata->avg_data[2] -= MAX_ACCEL_1G;
- else if (pdata->avg_data[2] < 0)
- pdata->avg_data[2] += MAX_ACCEL_1G;
- mutex_unlock(&data->dev_data->accel_factory_mutex);
- pdata->is_complete_cal = true;
- }
- void accel_cal_work_func(struct work_struct *work)
- {
- struct adsp_data *data = container_of((struct delayed_work *)work,
- struct adsp_data, accel_cal_work);
- int ret = 0;
- mutex_lock(&data->accel_factory_mutex);
- ret = get_accel_cal_data(data, pdata->avg_data);
- mutex_unlock(&data->accel_factory_mutex);
- if (ret > 0) {
- pr_info("[FACTORY] %s: ret(%d) %d, %d, %d\n", __func__, ret,
- pdata->avg_data[0],
- pdata->avg_data[1],
- pdata->avg_data[2]);
- mutex_lock(&data->accel_factory_mutex);
- set_accel_cal_data(data);
- mutex_unlock(&data->accel_factory_mutex);
- } else {
- pr_err("[FACTORY] %s: get_accel_cal_data fail (%d)\n",
- __func__, ret);
- }
- }
- static ssize_t accel_selftest_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct adsp_data *data = dev_get_drvdata(dev);
- uint8_t cnt = 0;
- int retry = 0;
- #if IS_ENABLED(CONFIG_SUPPORT_AK09973) || defined(CONFIG_SUPPORT_AK09973)
- int msg_buf = LSM6DSO_SELFTEST_TRUE;
- adsp_unicast(&msg_buf, sizeof(msg_buf),
- MSG_DIGITAL_HALL_ANGLE, 0, MSG_TYPE_OPTION_DEFINE);
- #elif IS_ENABLED(CONFIG_SUPPORT_REF_ANGLE_WITHOUT_DIGITAL_HALL) || defined(CONFIG_SUPPORT_REF_ANGLE_WITHOUT_DIGITAL_HALL)
- int msg_buf = LSM6DSO_SELFTEST_TRUE;
- adsp_unicast(&msg_buf, sizeof(msg_buf),
- MSG_REF_ANGLE, 0, MSG_TYPE_OPTION_DEFINE);
- #endif
- pdata->st_complete = false;
- RETRY_ACCEL_SELFTEST:
- adsp_unicast(NULL, 0, MSG_ACCEL, 0, MSG_TYPE_ST_SHOW_DATA);
- while (!(data->ready_flag[MSG_TYPE_ST_SHOW_DATA] & 1 << MSG_ACCEL) &&
- cnt++ < TIMEOUT_CNT)
- msleep(26);
- data->ready_flag[MSG_TYPE_ST_SHOW_DATA] &= ~(1 << MSG_ACCEL);
- if (cnt >= TIMEOUT_CNT) {
- pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
- data->msg_buf[MSG_ACCEL][1] = -1;
- #ifdef CONFIG_SEC_FACTORY
- panic("sensor force crash : accel selftest timeout\n");
- #endif
- }
- pr_info("[FACTORY] %s : init = %d, result = %d, XYZ = %d, %d, %d, nXYZ = %d, %d, %d\n",
- __func__, data->msg_buf[MSG_ACCEL][0],
- data->msg_buf[MSG_ACCEL][1], data->msg_buf[MSG_ACCEL][2],
- data->msg_buf[MSG_ACCEL][3], data->msg_buf[MSG_ACCEL][4],
- data->msg_buf[MSG_ACCEL][5], data->msg_buf[MSG_ACCEL][6],
- data->msg_buf[MSG_ACCEL][7]);
- pr_info("[FACTORY] %s : pre/postP/postN [%d, %d, %d/%d, %d, %d/%d, %d, %d], comm_err_cnt %d/%d/%d\n",
- __func__, data->msg_buf[MSG_ACCEL][8],
- data->msg_buf[MSG_ACCEL][9], data->msg_buf[MSG_ACCEL][10],
- data->msg_buf[MSG_ACCEL][11], data->msg_buf[MSG_ACCEL][12],
- data->msg_buf[MSG_ACCEL][13], data->msg_buf[MSG_ACCEL][14],
- data->msg_buf[MSG_ACCEL][15], data->msg_buf[MSG_ACCEL][16],
- data->msg_buf[MSG_ACCEL][17], data->msg_buf[MSG_ACCEL][18],
- data->msg_buf[MSG_ACCEL][19]);
- if (data->msg_buf[MSG_ACCEL][1] == 1) {
- pr_info("[FACTORY] %s : Pass - result = %d, retry = %d\n",
- __func__, data->msg_buf[MSG_ACCEL][1], retry);
- } else {
- data->msg_buf[MSG_ACCEL][1] = -5;
- pr_err("[FACTORY] %s : Fail - result = %d, retry = %d\n",
- __func__, data->msg_buf[MSG_ACCEL][1], retry);
- if (retry < ACCEL_ST_TRY_CNT) {
- retry++;
- msleep(50);
- cnt = 0;
- pr_info("[FACTORY] %s: retry\n", __func__);
- goto RETRY_ACCEL_SELFTEST;
- }
- }
- pdata->st_complete = true;
- #if IS_ENABLED(CONFIG_SUPPORT_AK09973) || defined(CONFIG_SUPPORT_AK09973) ||\
- IS_ENABLED(CONFIG_SUPPORT_REF_ANGLE_WITHOUT_DIGITAL_HALL) || defined(CONFIG_SUPPORT_REF_ANGLE_WITHOUT_DIGITAL_HALL)
- schedule_delayed_work(&data->lsm6dso_selftest_stop_work, msecs_to_jiffies(300));
- #endif
- return snprintf(buf, PAGE_SIZE, "%d,%d,%d,%d,%d,%d,%d\n",
- data->msg_buf[MSG_ACCEL][1],
- (int)abs(data->msg_buf[MSG_ACCEL][2]),
- (int)abs(data->msg_buf[MSG_ACCEL][3]),
- (int)abs(data->msg_buf[MSG_ACCEL][4]),
- (int)abs(data->msg_buf[MSG_ACCEL][5]),
- (int)abs(data->msg_buf[MSG_ACCEL][6]),
- (int)abs(data->msg_buf[MSG_ACCEL][7]));
- }
- static ssize_t accel_raw_data_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct adsp_data *data = dev_get_drvdata(dev);
- int32_t raw_data[ACCEL_RAW_DATA_CNT] = {0, };
- static int32_t prev_raw_data[ACCEL_RAW_DATA_CNT] = {0, };
- int ret = 0;
- #ifdef CONFIG_SEC_FACTORY
- static int same_cnt = 0;
- #endif
- if (pdata->st_complete == false) {
- pr_info("[FACTORY] %s: selftest is running\n", __func__);
- return snprintf(buf, PAGE_SIZE, "%d,%d,%d\n",
- raw_data[0], raw_data[1], raw_data[2]);
- }
- mutex_lock(&data->accel_factory_mutex);
- ret = get_accel_raw_data(raw_data);
- mutex_unlock(&data->accel_factory_mutex);
- #ifdef CONFIG_SEC_FACTORY
- pr_info("[FACTORY] %s: %d, %d, %d\n", __func__,
- raw_data[0], raw_data[1], raw_data[2]);
- if (prev_raw_data[0] == raw_data[0] &&
- prev_raw_data[1] == raw_data[1] &&
- prev_raw_data[2] == raw_data[2]) {
- same_cnt++;
- pr_info("[FACTORY] %s: same_cnt %d\n", __func__, same_cnt);
- if (same_cnt >= 20)
- panic("sensor force crash : accel raw_data stuck\n");
- } else
- same_cnt = 0;
- #endif
- if (!ret) {
- memcpy(prev_raw_data, raw_data, sizeof(int32_t) * 3);
- } else if (!pdata->lpf_onoff) {
- pr_err("[FACTORY] %s: using prev data!!!\n", __func__);
- memcpy(raw_data, prev_raw_data, sizeof(int32_t) * 3);
- } else {
- pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
- }
- return snprintf(buf, PAGE_SIZE, "%d,%d,%d\n",
- raw_data[0], raw_data[1], raw_data[2]);
- }
- static ssize_t accel_reactive_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct adsp_data *data = dev_get_drvdata(dev);
- uint8_t cnt = 0;
- bool success = false;
- int32_t msg_buf = 0;
- mutex_lock(&data->accel_factory_mutex);
- adsp_unicast(&msg_buf, sizeof(int32_t), MSG_ACCEL,
- 0, MSG_TYPE_GET_REGISTER);
- while (!(data->ready_flag[MSG_TYPE_GET_REGISTER] & 1 << MSG_ACCEL) &&
- cnt++ < TIMEOUT_CNT)
- usleep_range(500, 550);
- data->ready_flag[MSG_TYPE_GET_REGISTER] &= ~(1 << MSG_ACCEL);
- mutex_unlock(&data->accel_factory_mutex);
- if (cnt >= TIMEOUT_CNT) {
- pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
- return snprintf(buf, PAGE_SIZE, "%d\n", (int)success);
- }
- pr_info("[FACTORY]: %s - %d\n", __func__,
- data->msg_buf[MSG_ACCEL][0]);
- if (data->msg_buf[MSG_ACCEL][0] == 0)
- success = true;
- else
- panic("sensor accel interrupt check fail!!");
- return snprintf(buf, PAGE_SIZE, "%d\n", (int)success);
- }
- static ssize_t accel_reactive_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
- {
- struct adsp_data *data = dev_get_drvdata(dev);
- int32_t msg_buf;
- uint8_t cnt = 0;
- if (sysfs_streq(buf, "1"))
- pr_info("[FACTORY]: %s - on\n", __func__);
- else if (sysfs_streq(buf, "0"))
- pr_info("[FACTORY]: %s - off\n", __func__);
- else if (sysfs_streq(buf, "2")) {
- pr_info("[FACTORY]: %s - factory\n", __func__);
- msg_buf = 1;
- mutex_lock(&data->accel_factory_mutex);
- adsp_unicast(&msg_buf, sizeof(int32_t), MSG_ACCEL,
- 0, MSG_TYPE_GET_REGISTER);
- while (!(data->ready_flag[MSG_TYPE_GET_REGISTER] & 1 << MSG_ACCEL) &&
- cnt++ < TIMEOUT_CNT)
- usleep_range(500, 550);
- data->ready_flag[MSG_TYPE_GET_REGISTER] &= ~(1 << MSG_ACCEL);
- mutex_unlock(&data->accel_factory_mutex);
- if (cnt >= TIMEOUT_CNT) {
- pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
- return size;
- }
- if (data->msg_buf[MSG_ACCEL][0] == STM_LSM6DSO_INT_CHECK_RUNNING)
- pr_info("[FACTORY]: %s - STM_LSM6DSx_INT_CHECK_RUNNING\n", __func__);
- else
- pr_info("[FACTORY]: %s - Something wrong\n", __func__);
- }
- return size;
- }
- bool sns_check_ignore_crash(void)
- {
- return is_ignore_crash_factory;
- }
- EXPORT_SYMBOL(sns_check_ignore_crash);
- static ssize_t accel_lowpassfilter_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
- {
- struct adsp_data *data = dev_get_drvdata(dev);
- uint8_t cnt = 0;
- int32_t msg_buf;
- if (sysfs_streq(buf, "1")) {
- msg_buf = 1;
- is_ignore_crash_factory = false;
- } else if (sysfs_streq(buf, "0")) {
- msg_buf = 0;
- is_ignore_crash_factory = false;
- #ifdef CONFIG_SEC_FACTORY
- } else if (sysfs_streq(buf, "2")) {
- msg_buf = 2;
- is_ignore_crash_factory = true;
- pr_info("[FACTORY] %s: Pretest\n", __func__);
- } else if (sysfs_streq(buf, "3")) {
- msg_buf = 3;
- is_ignore_crash_factory = true;
- pr_info("[FACTORY] %s: Questt\n", __func__);
- return size;
- #endif
- } else {
- is_ignore_crash_factory = false;
- pr_info("[FACTORY] %s: wrong value\n", __func__);
- return size;
- }
- mutex_lock(&data->accel_factory_mutex);
- adsp_unicast(&msg_buf, sizeof(int32_t), MSG_ACCEL,
- 0, MSG_TYPE_SET_ACCEL_LPF);
- while (!(data->ready_flag[MSG_TYPE_SET_ACCEL_LPF] & 1 << MSG_ACCEL) &&
- cnt++ < TIMEOUT_CNT)
- usleep_range(500, 550);
- data->ready_flag[MSG_TYPE_SET_ACCEL_LPF] &= ~(1 << MSG_ACCEL);
- mutex_unlock(&data->accel_factory_mutex);
- if (cnt >= TIMEOUT_CNT) {
- pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
- return size;
- }
- pdata->lpf_onoff = (bool)data->msg_buf[MSG_ACCEL][0];
- #if IS_ENABLED(CONFIG_LSM6DSV_FACTORY)
- pr_info("[FACTORY] %s: %d, 0x0A:%02x 0x0D:%02x 0x18:%02x\n", __func__,
- data->msg_buf[MSG_ACCEL][0], data->msg_buf[MSG_ACCEL][1],
- data->msg_buf[MSG_ACCEL][2], data->msg_buf[MSG_ACCEL][3]);
- #else
- pr_info("[FACTORY] %s: %d, 0x0A:%02x 0x0D:%02x 0x10:%02x\n", __func__,
- data->msg_buf[MSG_ACCEL][0], data->msg_buf[MSG_ACCEL][1],
- data->msg_buf[MSG_ACCEL][2], data->msg_buf[MSG_ACCEL][3]);
- #endif
- return size;
- }
- #ifdef CONFIG_SEC_VIB_NOTIFIER
- uint64_t motor_stop_timeout(int timeout_ms)
- {
- uint64_t timeout_ns = timeout_ms * NSEC_PER_MSEC;
- if (timeout_ns > MAX_MOTOR_STOP_TIMEOUT)
- return timeout_ns;
- else
- return MAX_MOTOR_STOP_TIMEOUT;
- }
- int ssc_motor_notify(struct notifier_block *nb,
- unsigned long enable, void *v)
- {
- struct vib_notifier_context *vib = (struct vib_notifier_context *)v;
- uint64_t timeout_ns = 0;
- pr_info("[FACTORY] %s: %s, idx: %d timeout: %d\n",
- __func__, enable ? "ON" : "OFF", vib->index, vib->timeout);
- if(enable == 1) {
- pdata_motor->idx = vib->index;
- pdata_motor->timeout = vib->timeout;
- if (pdata_motor->idx == 0)
- timeout_ns = motor_stop_timeout(pdata_motor->timeout);
- else
- timeout_ns = MAX_MOTOR_STOP_TIMEOUT;
- if (atomic_read(&pdata_motor->motor_state) == MOTOR_OFF) {
- atomic_set(&pdata_motor->motor_state, MOTOR_ON);
- queue_work(pdata_motor->slpi_motor_wq,
- &pdata_motor->work_slpi_motor);
- } else {
- hrtimer_cancel(&pdata_motor->motor_stop_timer);
- if (pdata_motor->idx == CALL_VIB_IDX) {
- queue_work(pdata_motor->slpi_motor_wq,
- &pdata_motor->work_slpi_motor);
- return 0;
- }
- hrtimer_start(&pdata_motor->motor_stop_timer,
- ns_to_ktime(timeout_ns),
- HRTIMER_MODE_REL);
- }
- } else {
- if (pdata_motor->idx == CALL_VIB_IDX) {
- atomic_set(&pdata_motor->motor_state, MOTOR_OFF);
- queue_work(pdata_motor->slpi_motor_wq,
- &pdata_motor->work_slpi_motor);
- } else
- pr_info("[FACTORY] %s: Not support OFF\n", __func__);
- }
- return 0;
- }
- static enum hrtimer_restart motor_stop_timer_func(struct hrtimer *timer)
- {
- pr_info("[FACTORY] %s\n", __func__);
- atomic_set(&pdata_motor->motor_state, MOTOR_OFF);
- queue_work(pdata_motor->slpi_motor_wq, &pdata_motor->work_slpi_motor);
- return HRTIMER_NORESTART;
- }
- void slpi_motor_work_func(struct work_struct *work)
- {
- int32_t msg_buf = 0;
- uint64_t timeout_ns = 0;
- if (pdata_motor->idx == 0)
- timeout_ns = motor_stop_timeout(pdata_motor->timeout);
- else
- timeout_ns = MAX_MOTOR_STOP_TIMEOUT;
- if (atomic_read(&pdata_motor->motor_state) == MOTOR_ON) {
- if (pdata_motor->idx != CALL_VIB_IDX)
- hrtimer_start(&pdata_motor->motor_stop_timer,
- ns_to_ktime(timeout_ns),
- HRTIMER_MODE_REL);
- msg_buf = 1;
- } else if (atomic_read(&pdata_motor->motor_state) == MOTOR_OFF) {
- if (pdata_motor->idx != CALL_VIB_IDX)
- hrtimer_cancel(&pdata_motor->motor_stop_timer);
- msg_buf = 0;
- } else {
- pr_info("[FACTORY] %s: invalid state %d\n",
- __func__, (int)atomic_read(&pdata_motor->motor_state));
- }
- pr_info("[FACTORY] %s: msg_buf = %d, idx/timeout = %d/%d\n",
- __func__, msg_buf, pdata_motor->idx,
- (int)(timeout_ns / NSEC_PER_MSEC));
- adsp_unicast(&msg_buf, sizeof(int32_t), MSG_ACCEL,
- 0, MSG_TYPE_SET_ACCEL_MOTOR);
- #ifdef CONFIG_SUPPORT_DUAL_6AXIS
- usleep_range(500, 550);
- adsp_unicast(&msg_buf, sizeof(int32_t), MSG_ACCEL_SUB,
- 0, MSG_TYPE_SET_ACCEL_MOTOR);
- #endif
- }
- #endif
- static ssize_t accel_dhr_sensor_info_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct adsp_data *data = dev_get_drvdata(dev);
- uint8_t cnt = 0;
- char ctrl1_xl = 0;
- uint8_t fullscale = 0;
- adsp_unicast(NULL, 0, MSG_ACCEL, 0, MSG_TYPE_GET_DHR_INFO);
- while (!(data->ready_flag[MSG_TYPE_GET_DHR_INFO] & 1 << MSG_ACCEL) &&
- cnt++ < TIMEOUT_CNT)
- usleep_range(500, 550);
- data->ready_flag[MSG_TYPE_GET_DHR_INFO] &= ~(1 << MSG_ACCEL);
- if (cnt >= TIMEOUT_CNT) {
- pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
- } else {
- ctrl1_xl = data->msg_buf[MSG_ACCEL][16];
- ctrl1_xl &= 0xC;
- switch (ctrl1_xl) {
- case 0xC:
- fullscale = 8;
- break;
- case 0x8:
- fullscale = 4;
- break;
- case 0x4:
- fullscale = 16;
- break;
- case 0:
- fullscale = 2;
- break;
- default:
- break;
- }
- }
- pr_info("[FACTORY] %s: f/s %u\n", __func__, fullscale);
- return snprintf(buf, PAGE_SIZE, "\"FULL_SCALE\":\"%uG\"\n", fullscale);
- }
- static ssize_t accel_turn_over_crash_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct adsp_data *data = dev_get_drvdata(dev);
- pr_info("[FACTORY] %s: %d, \n", __func__, data->turn_over_crash);
- return snprintf(buf, PAGE_SIZE, "%d\n", data->turn_over_crash);
- }
- static ssize_t accel_turn_over_crash_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
- {
- struct adsp_data *data = dev_get_drvdata(dev);
- int32_t msg_buf[2] = {0, };
- if (sysfs_streq(buf, "1")) {
- data->turn_over_crash = 1;
- msg_buf[1] = 1;
- } else if (sysfs_streq(buf, "2")) {
- data->turn_over_crash = 2;
- msg_buf[1] = 2;
- } else {
- data->turn_over_crash = 0;
- msg_buf[1] = 0;
- }
- adsp_unicast(msg_buf, sizeof(msg_buf), MSG_ACCEL,
- 0, MSG_TYPE_OPTION_DEFINE);
- pr_info("[FACTORY] %s: %d, \n", __func__, msg_buf[1]);
- return size;
- }
- static DEVICE_ATTR(name, 0444, accel_name_show, NULL);
- static DEVICE_ATTR(vendor, 0444, accel_vendor_show, NULL);
- static DEVICE_ATTR(type, 0444, sensor_type_show, NULL);
- static DEVICE_ATTR(calibration, 0664,
- accel_calibration_show, accel_calibration_store);
- static DEVICE_ATTR(selftest, 0440,
- accel_selftest_show, NULL);
- static DEVICE_ATTR(raw_data, 0444, accel_raw_data_show, NULL);
- static DEVICE_ATTR(reactive_alert, 0664,
- accel_reactive_show, accel_reactive_store);
- static DEVICE_ATTR(lowpassfilter, 0220,
- NULL, accel_lowpassfilter_store);
- #ifdef CONFIG_SEC_FACTORY
- static DEVICE_ATTR(dhr_sensor_info, 0444,
- accel_dhr_sensor_info_show, NULL);
- #else
- static DEVICE_ATTR(dhr_sensor_info, 0440,
- accel_dhr_sensor_info_show, NULL);
- #endif
- static DEVICE_ATTR(turn_over_crash, 0664,
- accel_turn_over_crash_show, accel_turn_over_crash_store);
- static struct device_attribute *acc_attrs[] = {
- &dev_attr_name,
- &dev_attr_vendor,
- &dev_attr_type,
- &dev_attr_calibration,
- &dev_attr_selftest,
- &dev_attr_raw_data,
- &dev_attr_reactive_alert,
- &dev_attr_lowpassfilter,
- &dev_attr_dhr_sensor_info,
- &dev_attr_turn_over_crash,
- NULL,
- };
- void accel_factory_init_work(struct adsp_data *data)
- {
- schedule_delayed_work(&data->accel_cal_work, msecs_to_jiffies(8000));
- }
- EXPORT_SYMBOL(accel_factory_init_work);
- int __init lsm6dso_accel_factory_init(void)
- {
- adsp_factory_register(MSG_ACCEL, acc_attrs);
- #ifdef CONFIG_SEC_VIB_NOTIFIER
- pdata_motor = kzalloc(sizeof(*pdata_motor), GFP_KERNEL);
- if (pdata_motor == NULL)
- return -ENOMEM;
- pdata_motor->motor_nb.notifier_call = ssc_motor_notify,
- pdata_motor->motor_nb.priority = 1,
- sec_vib_notifier_register(&pdata_motor->motor_nb);
- hrtimer_init(&pdata_motor->motor_stop_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- pdata_motor->motor_stop_timer.function = motor_stop_timer_func;
- pdata_motor->slpi_motor_wq =
- create_singlethread_workqueue("slpi_motor_wq");
- if (pdata_motor->slpi_motor_wq == NULL) {
- pr_err("[FACTORY]: %s - could not create motor wq\n", __func__);
- kfree(pdata_motor);
- return -ENOMEM;
- }
- INIT_WORK(&pdata_motor->work_slpi_motor, slpi_motor_work_func);
- atomic_set(&pdata_motor->motor_state, MOTOR_OFF);
- #endif
- pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
- pdata->accel_wq = create_singlethread_workqueue("accel_wq");
- INIT_WORK(&pdata->work_accel, accel_work_func);
- pdata->lpf_onoff = true;
- pdata->st_complete = true;
- pr_info("[FACTORY] %s\n", __func__);
- return 0;
- }
- void __exit lsm6dso_accel_factory_exit(void)
- {
- adsp_factory_unregister(MSG_ACCEL);
- #ifdef CONFIG_SEC_VIB_NOTIFIER
- if (atomic_read(&pdata_motor->motor_state) == MOTOR_ON)
- hrtimer_cancel(&pdata_motor->motor_stop_timer);
- if (pdata_motor != NULL && pdata_motor->slpi_motor_wq != NULL) {
- cancel_work_sync(&pdata_motor->work_slpi_motor);
- destroy_workqueue(pdata_motor->slpi_motor_wq);
- pdata_motor->slpi_motor_wq = NULL;
- kfree(pdata_motor);
- }
- #endif
- pr_info("[FACTORY] %s\n", __func__);
- }
|