Add samsung specific changes
This commit is contained in:
403
drivers/adsp_factory/Kconfig
Executable file
403
drivers/adsp_factory/Kconfig
Executable file
@@ -0,0 +1,403 @@
|
||||
#
|
||||
# factory sensor drivers configuration
|
||||
#
|
||||
config ADSP_FACTORY
|
||||
tristate "MSM ADSP factory driver"
|
||||
help
|
||||
This driver communicate with SSC DAEMON.
|
||||
register each sensor device.
|
||||
send selftest request using netlink.
|
||||
receive test result using netlink.
|
||||
|
||||
config LSM6DSO_FACTORY
|
||||
bool "factory test for SSC - LSM6DSO"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
lsm6dso factory driver.
|
||||
provide sysfs for factory test.
|
||||
request selftest to adsp_factory.
|
||||
receive test result from adsp_factory.
|
||||
|
||||
config LSM6DSL_FACTORY
|
||||
bool "factory test for SSC - LSM6DSL"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
lsm6dsl factory driver.
|
||||
provide sysfs for factory test.
|
||||
request selftest to adsp_factory.
|
||||
receive test result from adsp_factory.
|
||||
|
||||
config LSM6DSV_FACTORY
|
||||
bool "factory test for SSC - LSM6DSV"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
lsm6dsv factory driver.
|
||||
provide sysfs for factory test.
|
||||
request selftest to adsp_factory.
|
||||
receive test result from adsp_factory.
|
||||
|
||||
config SUPPORT_ACCEL_HIGHG
|
||||
bool "support HIGH G ACCEL"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
highg accel factory driver.
|
||||
provide sysfs for factory test.
|
||||
request selftest to adsp_factory.
|
||||
receive test result from adsp_factory.
|
||||
|
||||
config AK09918_FACTORY
|
||||
bool "factory test for SSC - ak09918"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
ak09918 factory driver.
|
||||
provide sysfs for factory test.
|
||||
request selftest to adsp_factory.
|
||||
receive test result from adsp_factory.
|
||||
|
||||
config SUPPORT_MAG_ABS_SUM
|
||||
tristate "mag abs sum for SSC"
|
||||
depends on AK09918_FACTORY
|
||||
help
|
||||
Support the mag abs sum check
|
||||
check the mag abs sum value.
|
||||
|
||||
config LPS22HH_FACTORY
|
||||
bool "factory test for SSC - lps22hh"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
lps22hh factory driver.
|
||||
provide sysfs for factory test.
|
||||
request selftest to adsp_factory.
|
||||
receive test result from adsp_factory.
|
||||
|
||||
config LPS22DF_FACTORY
|
||||
bool "factory test for SSC - lps22df"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
lps22df factory driver.
|
||||
provide sysfs for factory test.
|
||||
request selftest to adsp_factory.
|
||||
receive test result from adsp_factory.
|
||||
|
||||
config PRESSURE_FACTORY
|
||||
bool "factory test for SSC - pressure"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
pressure factory driver.
|
||||
provide sysfs for factory test.
|
||||
request selftest to adsp_factory.
|
||||
receive test result from adsp_factory.
|
||||
|
||||
config LIGHT_FACTORY
|
||||
bool "factory test for SSC - light"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
light factory driver.
|
||||
provide sysfs for factory test.
|
||||
request selftest to adsp_factory.
|
||||
receive test result from adsp_factory.
|
||||
|
||||
config LIGHT_SUB_FACTORY
|
||||
bool "factory test for SSC - light sub"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
light sub factory driver.
|
||||
provide sysfs for factory test.
|
||||
request selftest to adsp_factory.
|
||||
receive test result from adsp_factory.
|
||||
|
||||
config PROX_FACTORY
|
||||
bool "factory test for SSC - prox"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
prox factory driver.
|
||||
provide sysfs for factory test.
|
||||
request selftest to adsp_factory.
|
||||
receive test result from adsp_factory.
|
||||
|
||||
config STK33610_FACTORY
|
||||
bool "factory test for SSC - STK33610"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
stk33610 factory driver.
|
||||
provide sysfs for factory test.
|
||||
request selftest through factory daemon to slpi.
|
||||
receive test result through factory daemon from slpi.
|
||||
|
||||
config STK33610_SUB_FACTORY
|
||||
bool "factory test for SSC - STK33610"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
stk33610 factory driver.
|
||||
provide sysfs for factory test.
|
||||
request selftest through factory daemon to slpi.
|
||||
receive test result through factory daemon from slpi.
|
||||
|
||||
config SUPPORT_LIGHT_CALIBRATION
|
||||
bool "light cal for SSC"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
light calibration feature.
|
||||
provide sysfs for light calibration.
|
||||
request light cal to adsp_factory.
|
||||
receive cal value from adsp_factory.
|
||||
|
||||
config SUPPORT_PROX_CALIBRATION
|
||||
bool "prox cal for SSC"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
prox calibration feature.
|
||||
provide sysfs for prox calibration.
|
||||
request prox cal to adsp_factory.
|
||||
receive cal value from adsp_factory.
|
||||
|
||||
config SUPPORT_CONTROL_PROX_LED_GPIO
|
||||
bool "control prox led gpio for SSC"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
Support to control prox led gpio.
|
||||
|
||||
config SUPPORT_PROX_POWER_ON_CAL
|
||||
bool "Sensors support proximity sensor power on cal"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
Support power on calibration for proximity sensor
|
||||
make calibration process done as the device power up.
|
||||
|
||||
config SUPPORT_BRIGHTNESS_NOTIFY_FOR_LIGHT_SENSOR
|
||||
bool "Sensors support brightness notify"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
Support brightness notify for light sensor.
|
||||
receive aor and brightness level from lcd driver.
|
||||
|
||||
config SUPPORT_PANEL_STATE_NOTIFY_FOR_LIGHT_SENSOR
|
||||
bool "Sensors support panel state notify"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
Support panel state notify for light sensor.
|
||||
receive panel state from lcd driver.
|
||||
|
||||
config SUPPORT_DDI_COPR_FOR_LIGHT_SENSOR
|
||||
bool "Sensors support ddi copr"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
Support ddi copr for light sensor.
|
||||
provide copr sysfs for factory and afc service.
|
||||
DDI must be connected with sensor core
|
||||
|
||||
config SUPPORT_AP_COPR_FOR_LIGHT_SENSOR
|
||||
bool "Sensors support ap copr"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
Support ap copr for light sensor.
|
||||
provide copr sysfs for factory and afc service.
|
||||
The display driver must provide copr data as notify.
|
||||
|
||||
config SUPPORT_DUAL_DDI_COPR_FOR_LIGHT_SENSOR
|
||||
bool "Sensors support dual ddi copr"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
Support dual ddi copr for light sensor.
|
||||
provide copr sysfs for factory and afc service.
|
||||
DDI must be connected with sensor core
|
||||
|
||||
config SUPPORT_DUAL_6AXIS
|
||||
bool "Sensors support dual 6axis"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
Support the dual accel and gyro function.
|
||||
provide sysfs for factory test.
|
||||
request selftest to adsp_factory.
|
||||
receive test result from adsp_factory.
|
||||
|
||||
config SUPPORT_TRIPLE_6AXIS
|
||||
bool "Sensors support triple 6axis"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
Support the triple accel and gyro function.
|
||||
provide sysfs for factory test.
|
||||
request selftest to adsp_factory.
|
||||
receive test result from adsp_factory.
|
||||
|
||||
config SUPPORT_DUAL_MAG
|
||||
bool "Sensors support dual magnetic sensors"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
Support the dual mag function.
|
||||
provide sysfs for factory test.
|
||||
request selftest to adsp_factory.
|
||||
receive test result from adsp_factory.
|
||||
|
||||
config SUPPORT_DUAL_OPTIC
|
||||
bool "Sensors support dual optic"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
Support the dual prox and light function.
|
||||
provide sysfs for factory test.
|
||||
request selftest to adsp_factory.
|
||||
receive test result from adsp_factory.
|
||||
|
||||
config SUPPORT_VIRTUAL_OPTIC
|
||||
bool "Sensors support virtual optic"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
Support the virtual prox and light function.
|
||||
provide sysfs for factory test.
|
||||
request selftest to adsp_factory.
|
||||
receive test result from adsp_factory.
|
||||
|
||||
config SUPPORT_DUAL_OPTIC_BUT_SUPPORT_SINGLE_PROX
|
||||
bool "Sensors support virtual optic but support single prox"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
Support the virtual prox and light function.
|
||||
provide sysfs for factory test.
|
||||
request selftest to adsp_factory.
|
||||
receive test result from adsp_factory.
|
||||
|
||||
config SUPPORT_SENSOR_FLIP_MODEL
|
||||
bool "Sensors support sensor flip model"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
Support sensor flip model.
|
||||
Separate the flip model from the factory test.
|
||||
|
||||
config SUPPORT_AK09973
|
||||
bool "Support ak09973"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
Support ak09973.
|
||||
|
||||
config SUPPORT_DHALL_SWITCH
|
||||
bool "Support DHALL_SWITCH"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
Support ak09973.
|
||||
|
||||
config SUPPORT_DEVICE_MODE
|
||||
bool "Support device mode"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
Support device mode.
|
||||
|
||||
config SUPPORT_SENSOR_FOLD
|
||||
bool "Support fold state by sensor algorithm"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
Support fold state by sensor algorithm.
|
||||
|
||||
config VEML3235_FACTORY
|
||||
bool "factory test for SSC - veml3235"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
veml3235 factory driver.
|
||||
provide sysfs for factory test.
|
||||
request selftest to adsp_factory.
|
||||
receive test result from adsp_factory.
|
||||
|
||||
config VEML3235_SUB_FACTORY
|
||||
bool "factory test for SSC - veml3235_sub"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
veml3235_sub factory driver.
|
||||
provide sysfs for factory test.
|
||||
request selftest to adsp_factory.
|
||||
receive test result from adsp_factory.
|
||||
|
||||
config VEML3328_FACTORY
|
||||
bool "factory test for SSC - veml3328"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
veml3328 factory driver.
|
||||
provide sysfs for factory test.
|
||||
request selftest to adsp_factory.
|
||||
receive test result from adsp_factory.
|
||||
|
||||
config VEML3328_SUB_FACTORY
|
||||
bool "factory test for SSC - veml3328_sub"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
veml3328_sub factory driver.
|
||||
provide sysfs for factory test.
|
||||
request selftest to adsp_factory.
|
||||
receive test result from adsp_factory.
|
||||
|
||||
config SUPPORT_LIGHT_SEAMLESS
|
||||
bool "Support Light seamless"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
Support Light seamless.
|
||||
|
||||
config BACKTAP_FACTORY
|
||||
bool "factory test for SSC - Back Tap Sensor"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
backtap factory driver.
|
||||
provide sysfs for setting back tap peak threshold
|
||||
|
||||
config FLIP_COVER_DETECTOR_FACTORY
|
||||
bool "factory test for SSC - Flip Cover Detector"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
flip_cover_detector factory driver.
|
||||
provide sysfs for cover status by nfc
|
||||
|
||||
config FLIP_COVER_DETECTOR_NOTIFIER
|
||||
bool "flip cover detector notifier"
|
||||
depends on FLIP_COVER_DETECTOR_FACTORY
|
||||
default y
|
||||
help
|
||||
Support notifier for flip cover attach/detach events
|
||||
|
||||
config SSC_WAKEUP_DEBUG
|
||||
bool "debug to ap wakeup due to SSC"
|
||||
depends on SEC_SENSORS_SSC
|
||||
help
|
||||
debug to ap wakeup due to SSC event frequently
|
||||
|
||||
config SLPI_LOADING_FAILURE_DEBUG
|
||||
bool "debug to slpi loading fail"
|
||||
depends on SEC_SENSORS_SSC
|
||||
help
|
||||
debug to to slpi loading fail
|
||||
|
||||
config SUPPORT_REF_ANGLE_WITHOUT_DIGITAL_HALL
|
||||
bool "support ref angle without digital hall"
|
||||
depends on ADSP_FACTORY
|
||||
help
|
||||
support ref angle without digital hall
|
||||
|
||||
config SENSOR_FACTORY_KUNIT_FOR_ON_DEVICE
|
||||
tristate "KUnit test for sensor factory kunit"
|
||||
depends on SEC_KUNIT
|
||||
depends on ADSP_FACTORY
|
||||
|
||||
config SENSOR_FACTORY_KUNIT_FOR_ONLY_UML
|
||||
tristate "KUnit test for sensor factory kunit"
|
||||
depends on SEC_KUNIT
|
||||
depends on UML
|
||||
depends on ADSP_FACTORY
|
||||
|
||||
config AK09973_DIGITAL_HALL_TEST_FOR_ON_DEVICE
|
||||
tristate "KUnit test for ak09973_digital_hall_test"
|
||||
depends on SEC_KUNIT
|
||||
depends on SUPPORT_AK09973
|
||||
help
|
||||
TODO: Describe config fully.
|
||||
If you run this test driver on device, SHOULD set this config as 'm' to build test driver modulraly.
|
||||
|
||||
config AK09973_DIGITAL_HALL_TEST_FOR_ONLY_UML
|
||||
tristate "KUnit test for ak09973_digital_hall_test"
|
||||
depends on SEC_KUNIT
|
||||
depends on UML
|
||||
depends on SUPPORT_AK09973
|
||||
help
|
||||
TODO: Describe config fully.
|
||||
This CONFIG is recommended to set to y.
|
||||
|
||||
config SEC_SENSORS_RECOVERY
|
||||
bool "recovery slpi or adsp for sensor"
|
||||
depends on SEC_SENSORS_SSC
|
||||
help
|
||||
recovery to slpi or adsp for sensor
|
17
drivers/adsp_factory/Makefile
Executable file
17
drivers/adsp_factory/Makefile
Executable file
@@ -0,0 +1,17 @@
|
||||
obj-$(CONFIG_ADSP_FACTORY) += adsp_factory_module.o
|
||||
adsp_factory_module-$(CONFIG_ADSP_FACTORY) := adsp_factory.o ssc_core.o
|
||||
adsp_factory_module-$(CONFIG_LSM6DSO_FACTORY) += lsm6dso_accel.o lsm6dso_gyro.o
|
||||
adsp_factory_module-$(CONFIG_SUPPORT_ACCEL_HIGHG) += accel_highg_factory.o
|
||||
adsp_factory_module-$(CONFIG_AK09918_FACTORY) += ak09918_mag.o
|
||||
adsp_factory_module-$(CONFIG_LPS22HH_FACTORY) += lps22hh_pressure.o
|
||||
adsp_factory_module-$(CONFIG_PRESSURE_FACTORY) += pressure_factory.o
|
||||
adsp_factory_module-$(CONFIG_LIGHT_FACTORY) += light_factory.o
|
||||
adsp_factory_module-$(CONFIG_PROX_FACTORY) += prox_factory.o
|
||||
adsp_factory_module-$(CONFIG_SUPPORT_DUAL_6AXIS) += lsm6dso_sub_accel.o lsm6dso_sub_gyro.o
|
||||
adsp_factory_module-$(CONFIG_SUPPORT_TRIPLE_6AXIS) += sub2_accel.o sub2_gyro.o
|
||||
adsp_factory_module-$(CONFIG_LSM6DSL_FACTORY) += lsm6dsl_accel.o lsm6dsl_gyro.o
|
||||
adsp_factory_module-$(CONFIG_SUPPORT_AK09973) += ak09973_digital_hall.o
|
||||
adsp_factory_module-$(CONFIG_FLIP_COVER_DETECTOR_FACTORY) += flip_cover_detector.o
|
||||
adsp_factory_module-$(CONFIG_BACKTAP_FACTORY) += back_tap.o
|
||||
adsp_factory_module-$(CONFIG_SUPPORT_DUAL_MAG) += mag_sub_factory.o
|
||||
GCOV_PROFILE_ak09973_digital_hall.o := $(CONFIG_KUNIT)
|
400
drivers/adsp_factory/accel_highg_factory.c
Executable file
400
drivers/adsp_factory/accel_highg_factory.c
Executable file
@@ -0,0 +1,400 @@
|
||||
/*
|
||||
* 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"
|
||||
#if IS_ENABLED(CONFIG_SEC_DEBUG)
|
||||
#include <linux/samsung/debug/sec_debug.h>
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_LSM6DSV_FACTORY)
|
||||
#define VENDOR "STM"
|
||||
#define CHIP_ID "LSM6DSV256X"
|
||||
#else
|
||||
#define VENDOR "UNKNOWN"
|
||||
#define CHIP_ID "UNKNOWN"
|
||||
#endif
|
||||
|
||||
#define ACCEL_ST_TRY_CNT 3
|
||||
#define ACCEL_FACTORY_CAL_CNT 20
|
||||
#define ACCEL_RAW_DATA_CNT 3
|
||||
#define MAX_ACCEL_1G 128 /*256G*/
|
||||
|
||||
struct accel_highg_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_highg_data *pdata;
|
||||
|
||||
static ssize_t accel_highg_vendor_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", VENDOR);
|
||||
}
|
||||
|
||||
static ssize_t accel_highg_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_highg_cal_data(struct adsp_data *data, int32_t *cal_data)
|
||||
{
|
||||
uint8_t cnt = 0;
|
||||
|
||||
adsp_unicast(NULL, 0, MSG_ACCEL_HIGHG, 0, MSG_TYPE_GET_CAL_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_CAL_DATA] & 1 << MSG_ACCEL_HIGHG) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_CAL_DATA] &= ~(1 << MSG_ACCEL_HIGHG);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (data->msg_buf[MSG_ACCEL_HIGHG][3] != ACCEL_RAW_DATA_CNT) {
|
||||
pr_err("[FACTORY] %s: Reading Bytes Num %d!!!\n",
|
||||
__func__, data->msg_buf[MSG_ACCEL_HIGHG][3]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cal_data[0] = data->msg_buf[MSG_ACCEL_HIGHG][0];
|
||||
cal_data[1] = data->msg_buf[MSG_ACCEL_HIGHG][1];
|
||||
cal_data[2] = data->msg_buf[MSG_ACCEL_HIGHG][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_HIGHG][3]);
|
||||
|
||||
return data->msg_buf[MSG_ACCEL_HIGHG][3];
|
||||
}
|
||||
|
||||
void set_accel_highg_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_HIGHG, 0, MSG_TYPE_SET_CAL_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_SET_CAL_DATA] & 1 << MSG_ACCEL_HIGHG) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_SET_CAL_DATA] &= ~(1 << MSG_ACCEL_HIGHG);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
} else if (data->msg_buf[MSG_ACCEL_HIGHG][0] != ACCEL_RAW_DATA_CNT) {
|
||||
pr_err("[FACTORY] %s: Write Bytes Num %d!!!\n",
|
||||
__func__, data->msg_buf[MSG_ACCEL_HIGHG][0]);
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t accel_highg_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_highg_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_highg_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_highg_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_highg_cal_data(data);
|
||||
mutex_unlock(&data->accel_factory_mutex);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static void accel_highg_work_func(struct work_struct *work)
|
||||
{
|
||||
struct accel_highg_data *data = container_of((struct work_struct *)work,
|
||||
struct accel_highg_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_HIGHG, 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_highg_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_highg_cal_work_func(struct work_struct *work)
|
||||
{
|
||||
struct adsp_data *data = container_of((struct delayed_work *)work,
|
||||
struct adsp_data, accel_highg_cal_work);
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&data->accel_factory_mutex);
|
||||
ret = get_accel_highg_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_highg_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_highg_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_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_HIGHG, 0, MSG_TYPE_ST_SHOW_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_ST_SHOW_DATA] & 1 << MSG_ACCEL_HIGHG) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
msleep(26);
|
||||
|
||||
data->ready_flag[MSG_TYPE_ST_SHOW_DATA] &= ~(1 << MSG_ACCEL_HIGHG);
|
||||
|
||||
#if IS_ENABLED(CONFIG_SEC_DEBUG) && defined(CONFIG_SEC_FACTORY)
|
||||
if(sec_debug_is_enabled())
|
||||
BUG_ON(cnt >= TIMEOUT_CNT);
|
||||
#else
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
data->msg_buf[MSG_ACCEL_HIGHG][1] = -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
pr_info("[FACTORY] %s : init = %d, result = %d, XYZ = %d, %d, %d, nXYZ = %d, %d, %d\n",
|
||||
__func__, data->msg_buf[MSG_ACCEL_HIGHG][0],
|
||||
data->msg_buf[MSG_ACCEL_HIGHG][1], data->msg_buf[MSG_ACCEL_HIGHG][2],
|
||||
data->msg_buf[MSG_ACCEL_HIGHG][3], data->msg_buf[MSG_ACCEL_HIGHG][4],
|
||||
data->msg_buf[MSG_ACCEL_HIGHG][5], data->msg_buf[MSG_ACCEL_HIGHG][6],
|
||||
data->msg_buf[MSG_ACCEL_HIGHG][7]);
|
||||
|
||||
if (data->msg_buf[MSG_ACCEL_HIGHG][1] == 1) {
|
||||
pr_info("[FACTORY] %s : Pass - result = %d, retry = %d\n",
|
||||
__func__, data->msg_buf[MSG_ACCEL_HIGHG][1], retry);
|
||||
} else {
|
||||
data->msg_buf[MSG_ACCEL_HIGHG][1] = -5;
|
||||
pr_err("[FACTORY] %s : Fail - result = %d, retry = %d\n",
|
||||
__func__, data->msg_buf[MSG_ACCEL_HIGHG][1], retry);
|
||||
|
||||
if (retry < ACCEL_ST_TRY_CNT &&
|
||||
data->msg_buf[MSG_ACCEL_HIGHG][2] == 0) {
|
||||
retry++;
|
||||
msleep(200);
|
||||
cnt = 0;
|
||||
pr_info("[FACTORY] %s: retry\n", __func__);
|
||||
goto RETRY_ACCEL_SELFTEST;
|
||||
}
|
||||
}
|
||||
|
||||
pdata->st_complete = true;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d,%d,%d,%d,%d,%d,%d\n",
|
||||
data->msg_buf[MSG_ACCEL_HIGHG][1],
|
||||
(int)abs(data->msg_buf[MSG_ACCEL_HIGHG][2]),
|
||||
(int)abs(data->msg_buf[MSG_ACCEL_HIGHG][3]),
|
||||
(int)abs(data->msg_buf[MSG_ACCEL_HIGHG][4]),
|
||||
(int)abs(data->msg_buf[MSG_ACCEL_HIGHG][5]),
|
||||
(int)abs(data->msg_buf[MSG_ACCEL_HIGHG][6]),
|
||||
(int)abs(data->msg_buf[MSG_ACCEL_HIGHG][7]));
|
||||
}
|
||||
|
||||
static ssize_t accel_highg_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_highg_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 IS_ENABLED(CONFIG_SEC_DEBUG)
|
||||
if(sec_debug_is_enabled())
|
||||
BUG_ON(same_cnt >= 20);
|
||||
#endif
|
||||
} 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 DEVICE_ATTR(name, 0444, accel_highg_name_show, NULL);
|
||||
static DEVICE_ATTR(vendor, 0444, accel_highg_vendor_show, NULL);
|
||||
static DEVICE_ATTR(type, 0444, sensor_type_show, NULL);
|
||||
static DEVICE_ATTR(calibration, 0664,
|
||||
accel_highg_calibration_show, accel_highg_calibration_store);
|
||||
static DEVICE_ATTR(selftest, 0440,
|
||||
accel_highg_selftest_show, NULL);
|
||||
static DEVICE_ATTR(raw_data, 0444, accel_highg_raw_data_show, NULL);
|
||||
|
||||
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,
|
||||
NULL,
|
||||
};
|
||||
|
||||
void accel_highg_factory_init_work(struct adsp_data *data)
|
||||
{
|
||||
schedule_delayed_work(&data->accel_highg_cal_work, msecs_to_jiffies(8000));
|
||||
}
|
||||
EXPORT_SYMBOL(accel_highg_factory_init_work);
|
||||
|
||||
int __init accel_highg_factory_init(void)
|
||||
{
|
||||
adsp_factory_register(MSG_ACCEL_HIGHG, acc_attrs);
|
||||
|
||||
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
|
||||
pdata->accel_wq = create_singlethread_workqueue("accel_high_wq");
|
||||
INIT_WORK(&pdata->work_accel, accel_highg_work_func);
|
||||
|
||||
pdata->lpf_onoff = true;
|
||||
pdata->st_complete = true;
|
||||
pr_info("[FACTORY] %s\n", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __exit accel_highg_factory_exit(void)
|
||||
{
|
||||
adsp_factory_unregister(MSG_ACCEL_HIGHG);
|
||||
pr_info("[FACTORY] %s\n", __func__);
|
||||
}
|
381
drivers/adsp_factory/adsp.h
Executable file
381
drivers/adsp_factory/adsp.h
Executable file
@@ -0,0 +1,381 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#ifndef __ADSP_SENSOR_H__
|
||||
#define __ADSP_SENSOR_H__
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/fcntl.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/uaccess.h>
|
||||
//#include <linux/sensors.h>
|
||||
#include <linux/adsp/adsp_ft_common.h>
|
||||
|
||||
#define TIMEOUT_CNT 200
|
||||
#define TIMEOUT_DHR_CNT 50
|
||||
|
||||
#define PATH_LEN 50
|
||||
#define FILE_BUF_LEN 110
|
||||
#define ID_INDEX_NUMS 2
|
||||
#define RETRY_MAX 3
|
||||
#define VERSION_FILE_NAME_LEN 20
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_DUAL_6AXIS)
|
||||
/* To avoid wrong folder close */
|
||||
#define LSM6DSO_SELFTEST_TRUE 3
|
||||
#define LSM6DSO_SELFTEST_FALSE 4
|
||||
#endif
|
||||
#define AUTO_CAL_X_START 1
|
||||
#define AUTO_CAL_Y_START 20
|
||||
#define AUTO_CAL_Z_START 39
|
||||
#define UNKNOWN_INDEX 0
|
||||
#define DEVICE_INFO_LENGTH 10
|
||||
|
||||
#if IS_ENABLED(CONFIG_SEC_KUNIT)
|
||||
#include <kunit/mock.h>
|
||||
#define __mockable __weak
|
||||
#define __visible_for_testing
|
||||
#else
|
||||
#define __mockable
|
||||
#define __visible_for_testing static
|
||||
#endif
|
||||
|
||||
enum {
|
||||
D_FACTOR,
|
||||
R_COEF,
|
||||
G_COEF,
|
||||
B_COEF,
|
||||
C_COEF,
|
||||
CT_COEF,
|
||||
CT_OFFSET,
|
||||
THD_HIGH,
|
||||
THD_LOW,
|
||||
IRIS_PROX_THD,
|
||||
SUM_CRC,
|
||||
EFS_SAVE_NUMS,
|
||||
};
|
||||
|
||||
enum {
|
||||
ID_UTYPE,
|
||||
ID_BLACK,
|
||||
ID_WHITE,
|
||||
ID_GOLD,
|
||||
ID_SILVER,
|
||||
ID_GREEN,
|
||||
ID_BLUE,
|
||||
ID_PINKGOLD,
|
||||
ID_MAX,
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_SENSOR_FOLD)
|
||||
struct sensor_fold_state {
|
||||
int64_t ts;
|
||||
int state; // 0: unfold, 1: close(fold)
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Main struct containing all the data */
|
||||
struct adsp_data {
|
||||
struct device *adsp;
|
||||
struct device *sensor_device[MSG_SENSOR_MAX];
|
||||
struct device_attribute **sensor_attr[MSG_SENSOR_MAX];
|
||||
struct sock *adsp_skt;
|
||||
int32_t *msg_buf[MSG_SENSOR_MAX];
|
||||
unsigned int ready_flag[MSG_TYPE_MAX];
|
||||
bool sysfs_created[MSG_SENSOR_MAX];
|
||||
struct mutex prox_factory_mutex;
|
||||
struct mutex light_factory_mutex;
|
||||
struct mutex accel_factory_mutex;
|
||||
struct mutex remove_sysfs_mutex;
|
||||
struct mutex sensors_dump_mutex;
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_DUAL_OPTIC)
|
||||
struct mutex vir_optic_factory_mutex;
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_FLIP_COVER_DETECTOR_FACTORY)
|
||||
struct mutex flip_cover_factory_mutex;
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_BACKTAP_FACTORY)
|
||||
struct mutex backtap_factory_mutex;
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_AK09973)
|
||||
struct mutex digital_hall_mutex;
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_HALL_NOTIFIER)
|
||||
struct notifier_block adsp_nb;
|
||||
#endif
|
||||
#ifdef CONFIG_VBUS_NOTIFIER
|
||||
struct notifier_block vbus_nb;
|
||||
#endif
|
||||
int32_t fac_fstate;
|
||||
#if IS_ENABLED(CONFIG_LIGHT_FACTORY)
|
||||
struct delayed_work light_init_work;
|
||||
bool light_factory_is_ready;
|
||||
char light_device_vendor[2][10];
|
||||
char light_device_name[2][10];
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_LIGHT_CALIBRATION)
|
||||
struct delayed_work light_cal_work;
|
||||
int32_t light_cal_result;
|
||||
int32_t light_cal1;
|
||||
int32_t light_cal2;
|
||||
int32_t copr_w;
|
||||
int32_t sub_light_cal_result;
|
||||
int32_t sub_light_cal1;
|
||||
int32_t sub_light_cal2;
|
||||
int32_t sub_copr_w;
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_DDI_COPR_FOR_LIGHT_SENSOR)
|
||||
struct delayed_work light_copr_debug_work;
|
||||
int light_copr_debug_count;
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_AP_COPR_FOR_LIGHT_SENSOR)
|
||||
struct delayed_work light_copr_work;
|
||||
int32_t copr_data[15];
|
||||
bool has_pending_copr_data;
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_BRIGHTNESS_NOTIFY_FOR_LIGHT_SENSOR)
|
||||
struct work_struct light_br_work;
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_LIGHT_FACTORY)
|
||||
int32_t light_temp_reg;
|
||||
int32_t brightness_info[6];
|
||||
int32_t pre_bl_level[2];
|
||||
int32_t pre_panel_state[2];
|
||||
int32_t pre_screen_mode[2];
|
||||
int32_t pre_panel_idx;
|
||||
int32_t pre_display_idx;
|
||||
int32_t light_debug_info_cmd;
|
||||
int32_t hyst[4];
|
||||
int32_t brightness_resolution[2];
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_PROX_CALIBRATION)
|
||||
int32_t prox_cal;
|
||||
int32_t prox_sub_cal;
|
||||
#endif
|
||||
struct delayed_work accel_cal_work;
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_DUAL_6AXIS)
|
||||
struct delayed_work sub_accel_cal_work;
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_TRIPLE_6AXIS)
|
||||
struct delayed_work sub2_accel_cal_work;
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_ACCEL_HIGHG) || defined(CONFIG_SUPPORT_ACCEL_HIGHG)
|
||||
struct delayed_work accel_highg_cal_work;
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_LIGHT_SEAMLESS)
|
||||
struct delayed_work light_seamless_work;
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_AK09973) || defined(CONFIG_SUPPORT_AK09973)
|
||||
struct delayed_work lsm6dso_selftest_stop_work;
|
||||
struct delayed_work dhall_cal_work;
|
||||
#elif IS_ENABLED(CONFIG_SUPPORT_REF_ANGLE_WITHOUT_DIGITAL_HALL) || defined(CONFIG_SUPPORT_REF_ANGLE_WITHOUT_DIGITAL_HALL)
|
||||
struct delayed_work lsm6dso_selftest_stop_work;
|
||||
#endif
|
||||
struct delayed_work pressure_cal_work;
|
||||
char press_device_vendor[DEVICE_INFO_LENGTH];
|
||||
char press_device_name[DEVICE_INFO_LENGTH];
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_SENSOR_FOLD)
|
||||
struct sensor_fold_state fold_state;
|
||||
#endif
|
||||
uint32_t support_algo;
|
||||
bool restrict_mode;
|
||||
int turn_over_crash;
|
||||
bool send_probe_fail_msg;
|
||||
bool fssr_ignore;
|
||||
bool fssr_dump;
|
||||
};
|
||||
|
||||
struct device_id_t {
|
||||
uint8_t device_id;
|
||||
char device_vendor[DEVICE_INFO_LENGTH];
|
||||
char device_name[DEVICE_INFO_LENGTH];
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SEC_FACTORY
|
||||
int get_mag_raw_data(int32_t *raw_data);
|
||||
#endif
|
||||
int get_accel_raw_data(int32_t *raw_data);
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_DUAL_6AXIS)
|
||||
int get_sub_accel_raw_data(int32_t *raw_data);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_TRIPLE_6AXIS)
|
||||
int get_sub2_accel_raw_data(int32_t *raw_data);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_ACCEL_HIGHG)
|
||||
int get_accel_highg_raw_data(int32_t *raw_data);
|
||||
#endif
|
||||
int adsp_get_sensor_data(int sensor_type);
|
||||
int adsp_factory_register(unsigned int type,
|
||||
struct device_attribute *attributes[]);
|
||||
int adsp_factory_unregister(unsigned int type);
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_DEVICE_MODE) || defined(CONFIG_VBUS_NOTIFIER) || IS_ENABLED(CONFIG_HALL_NOTIFIER)
|
||||
struct adsp_data* adsp_ssc_core_register(unsigned int type,
|
||||
struct device_attribute *attributes[]);
|
||||
struct adsp_data* adsp_ssc_core_unregister(unsigned int type);
|
||||
#endif
|
||||
int adsp_unicast(void *param, int param_size, u16 sensor_type,
|
||||
u32 portid, u16 msg_type);
|
||||
int sensors_register(struct device **dev, void *drvdata,
|
||||
struct device_attribute *attributes[], char *name);
|
||||
void sensors_unregister(struct device *dev,
|
||||
struct device_attribute *attributes[]);
|
||||
int core_factory_init(void);
|
||||
void core_factory_exit(void);
|
||||
#if IS_ENABLED(CONFIG_LSM6DSO_FACTORY)
|
||||
int lsm6dso_accel_factory_init(void);
|
||||
void lsm6dso_accel_factory_exit(void);
|
||||
int lsm6dso_gyro_factory_init(void);
|
||||
void lsm6dso_gyro_factory_exit(void);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_LSM6DSL_FACTORY)
|
||||
int lsm6dsl_accel_factory_init(void);
|
||||
void lsm6dsl_accel_factory_exit(void);
|
||||
int lsm6dsl_gyro_factory_init(void);
|
||||
void lsm6dsl_gyro_factory_exit(void);
|
||||
#endif
|
||||
void accel_factory_init_work(struct adsp_data *data);
|
||||
void accel_cal_work_func(struct work_struct *work);
|
||||
#if IS_ENABLED(CONFIG_AK09918_FACTORY)
|
||||
int ak09918_factory_init(void);
|
||||
void ak09918_factory_exit(void);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_LPS22HH_FACTORY)
|
||||
int lps22hh_pressure_factory_init(void);
|
||||
void lps22hh_pressure_factory_exit(void);
|
||||
#elif IS_ENABLED(CONFIG_PRESSURE_FACTORY)
|
||||
int pressure_factory_init(void);
|
||||
void pressure_factory_exit(void);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_LIGHT_FACTORY)
|
||||
int light_factory_init(void);
|
||||
void light_factory_exit(void);
|
||||
void light_init_work(struct adsp_data *data);
|
||||
void light_init_work_func(struct work_struct *work);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_PROX_FACTORY)
|
||||
int prox_factory_init(void);
|
||||
void prox_factory_exit(void);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_DUAL_6AXIS)
|
||||
int lsm6dso_sub_accel_factory_init(void);
|
||||
void lsm6dso_sub_accel_factory_exit(void);
|
||||
int lsm6dso_sub_gyro_factory_init(void);
|
||||
void lsm6dso_sub_gyro_factory_exit(void);
|
||||
void sub_accel_factory_init_work(struct adsp_data *data);
|
||||
void sub_accel_cal_work_func(struct work_struct *work);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_TRIPLE_6AXIS)
|
||||
int sub2_accel_factory_init(void);
|
||||
void sub2_accel_factory_exit(void);
|
||||
int sub2_gyro_factory_init(void);
|
||||
void sub2_gyro_factory_exit(void);
|
||||
void sub2_accel_factory_init_work(struct adsp_data *data);
|
||||
void sub2_accel_cal_work_func(struct work_struct *work);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_ACCEL_HIGHG)
|
||||
int accel_highg_factory_init(void);
|
||||
void accel_highg_factory_exit(void);
|
||||
void accel_highg_factory_init_work(struct adsp_data *data);
|
||||
void accel_highg_cal_work_func(struct work_struct *work);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_DUAL_MAG)
|
||||
int mag_sub_factory_init(void);
|
||||
void mag_sub_factory_exit(void);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_AK09973)
|
||||
int ak09970_factory_init(void);
|
||||
void ak09970_factory_exit(void);
|
||||
void lsm6dso_selftest_stop_work_func(struct work_struct *work);
|
||||
bool lf_stream_read_cal_data(int axis, int *cal_data);
|
||||
bool lf_stream_read_auto_cal_x_data(int *cal_data);
|
||||
bool lf_stream_read_auto_cal_y_data(int *cal_data);
|
||||
bool lf_stream_read_auto_cal_z_data(int *cal_data);
|
||||
int lf_stream_write_auto_cal_data(bool first_booting);
|
||||
int lf_stream_write_cal_data(int axis, bool first_booting);
|
||||
void lf_stream_set_mode_flag(bool is_first_boot, int *flag, umode_t *mode);
|
||||
bool lf_stream_get_info_from_axis(int axis, int *index, int *nums);
|
||||
int lf_stream_get_index_cal_data(int axis, int index);
|
||||
bool lf_stream_get_cal_path(int axis, char *path);
|
||||
bool lf_stream_get_data_buf(int axis, int32_t *data_buf);
|
||||
#elif IS_ENABLED(CONFIG_SUPPORT_REF_ANGLE_WITHOUT_DIGITAL_HALL) || defined(CONFIG_SUPPORT_REF_ANGLE_WITHOUT_DIGITAL_HALL)
|
||||
void lsm6dso_selftest_stop_work_func(struct work_struct *work);
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_DEVICE_MODE)
|
||||
void sns_device_mode_init_work(void);
|
||||
void sns_flip_init_work(void);
|
||||
#endif
|
||||
#ifdef CONFIG_VBUS_NOTIFIER
|
||||
void sns_vbus_init_work(void);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_HALL_NOTIFIER)
|
||||
void sns_mpp_cover_init_work(void);
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_BACKTAP_FACTORY)
|
||||
int backtap_factory_init(void);
|
||||
void backtap_factory_exit(void);
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_FLIP_COVER_DETECTOR_FACTORY)
|
||||
int flip_cover_detector_factory_init(void);
|
||||
void flip_cover_detector_factory_exit(void);
|
||||
void flip_cover_detector_cal_init_work(void);
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_LIGHT_CALIBRATION)
|
||||
void light_cal_init_work(struct adsp_data *data);
|
||||
void light_cal_read_work_func(struct work_struct *work);
|
||||
#endif /* CONFIG_SUPPORT_LIGHT_CALIBRATION */
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_DDI_COPR_FOR_LIGHT_SENSOR)
|
||||
void light_copr_debug_work_func(struct work_struct *work);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_AP_COPR_FOR_LIGHT_SENSOR)
|
||||
void light_copr_work_func(struct work_struct *work);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_PROX_CALIBRATION)
|
||||
void prox_cal_init_work(struct adsp_data *data);
|
||||
void prox_send_cal_data(struct adsp_data *data, uint16_t prox_idx, bool fac_cal);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_PROX_POWER_ON_CAL)
|
||||
void prox_factory_init_work(void);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_AK09973)
|
||||
void digital_hall_factory_auto_cal_init_work(struct adsp_data *data);
|
||||
int get_hall_angle_data(int32_t *raw_data);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_LIGHT_SEAMLESS)
|
||||
void light_seamless_work_func(struct work_struct *work);
|
||||
void light_seamless_init_work(struct adsp_data *data);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_DUAL_OPTIC)
|
||||
int get_light_sidx(struct adsp_data *data);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_BRIGHTNESS_NOTIFY_FOR_LIGHT_SENSOR) && \
|
||||
IS_ENABLED(CONFIG_SEC_PANEL_NOTIFIER_V2)
|
||||
void light_brightness_work_func(struct work_struct *work);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_AK09973)
|
||||
void dhall_cal_work_func(struct work_struct *work);
|
||||
#endif
|
||||
void pressure_factory_init_work(struct adsp_data *data);
|
||||
void pressure_cal_work_func(struct work_struct *work);
|
||||
struct adsp_data* adsp_get_struct_data(void);
|
||||
bool sns_check_ignore_crash(void);
|
||||
#endif /* __ADSP_SENSOR_H__ */
|
796
drivers/adsp_factory/adsp_factory.c
Executable file
796
drivers/adsp_factory/adsp_factory.c
Executable file
@@ -0,0 +1,796 @@
|
||||
/*
|
||||
* 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 <linux/platform_device.h>
|
||||
#include <net/sock.h>
|
||||
#include <net/netlink.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/sec_class.h>
|
||||
#include "adsp.h"
|
||||
|
||||
static u8 msg_size[MSG_SENSOR_MAX] = {
|
||||
MSG_ACCEL_MAX,
|
||||
MSG_GYRO_MAX,
|
||||
MSG_MAG_MAX,
|
||||
MSG_PRESSURE_MAX,
|
||||
MSG_LIGHT_MAX,
|
||||
MSG_PROX_MAX, //5
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_DUAL_OPTIC)
|
||||
MSG_LIGHT_MAX,
|
||||
MSG_PROX_MAX,
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_FLICKER)
|
||||
MSG_FLICKER_MAX,
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_DUAL_6AXIS)
|
||||
MSG_ACCEL_MAX,
|
||||
MSG_GYRO_MAX,
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_TRIPLE_6AXIS)
|
||||
MSG_ACCEL_MAX,
|
||||
MSG_GYRO_MAX,
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_ACCEL_HIGHG)
|
||||
MSG_ACCEL_MAX,
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_DUAL_MAG) || defined(CONFIG_SUPPORT_DUAL_MAG)
|
||||
MSG_MAG_MAX,
|
||||
#endif
|
||||
MSG_TYPE_SIZE_ZERO, /* PHYSICAL_SENSOR_SYSFS */
|
||||
MSG_GYRO_TEMP_MAX,
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_DUAL_6AXIS)
|
||||
MSG_GYRO_TEMP_MAX,
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_TRIPLE_6AXIS)
|
||||
MSG_GYRO_TEMP_MAX,
|
||||
#endif
|
||||
MSG_PRESSURE_TEMP_MAX,
|
||||
MSG_TYPE_SIZE_ZERO, /* MSG_MAG_CAL */
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_DUAL_MAG) || defined(CONFIG_SUPPORT_DUAL_MAG)
|
||||
MSG_TYPE_SIZE_ZERO,
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_FLIP_COVER_DETECTOR_FACTORY)
|
||||
MSG_FLIP_COVER_DETECTOR_MAX,
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_VIRTUAL_OPTIC)
|
||||
MSG_VOPTIC_MAX,
|
||||
#endif
|
||||
MSG_REG_SNS_MAX, /* MSG_REG_SNS */
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_AK09973)
|
||||
MSG_DIGITAL_HALL_MAX,
|
||||
MSG_DIGITAL_HALL_ANGLE_MAX,
|
||||
#if ENABLE_LF_STREAM
|
||||
MSG_DIGITAL_HALL_ANGLE_MAX,
|
||||
#endif
|
||||
#elif IS_ENABLED(CONFIG_SUPPORT_REF_ANGLE_WITHOUT_DIGITAL_HALL) || defined(CONFIG_SUPPORT_REF_ANGLE_WITHOUT_DIGITAL_HALL)
|
||||
MSG_REF_ANGLE_MAX,
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_DUAL_DDI_COPR_FOR_LIGHT_SENSOR)
|
||||
MSG_DDI_MAX,
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_LIGHT_MAIN2_SENSOR) || defined(CONFIG_SUPPORT_LIGHT_MAIN2_SENSOR)
|
||||
MSG_TYPE_SIZE_ZERO,
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_BACKTAP_FACTORY) || defined(CONFIG_BACKTAP_FACTORY)
|
||||
MSG_BACKTAP_MAX,
|
||||
#endif
|
||||
MSG_TYPE_SIZE_ZERO,
|
||||
MSG_COMMON_INFO_MAX,
|
||||
};
|
||||
|
||||
/* The netlink socket */
|
||||
struct adsp_data *data;
|
||||
|
||||
DEFINE_MUTEX(factory_mutex);
|
||||
|
||||
struct adsp_data* adsp_get_struct_data(void)
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
/* Function used to send message to the user space */
|
||||
int adsp_unicast(void *param, int param_size, u16 sensor_type,
|
||||
u32 portid, u16 msg_type)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct nlmsghdr *nlh;
|
||||
void *msg;
|
||||
int ret = -1;
|
||||
u16 nlmsg_type = (sensor_type << 8) | msg_type;
|
||||
|
||||
if (data->restrict_mode && msg_type == MSG_TYPE_SET_ACCEL_MOTOR) {
|
||||
pr_err("[FACTORY] %s - restrict_mode\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
data->ready_flag[msg_type] &= ~(1 << sensor_type);
|
||||
skb = nlmsg_new(param_size, GFP_KERNEL);
|
||||
if (!skb) {
|
||||
pr_err("[FACTORY] %s - nlmsg_new fail\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
nlh = nlmsg_put(skb, portid, 0, nlmsg_type, param_size, 0);
|
||||
if (nlh == NULL) {
|
||||
pr_err("[FACTORY] %s - nlmsg_put fail\n", __func__);
|
||||
nlmsg_free(skb);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
msg = nlmsg_data(nlh);
|
||||
memcpy(msg, param, param_size);
|
||||
NETLINK_CB(skb).dst_group = 0;
|
||||
ret = nlmsg_unicast(data->adsp_skt, skb, PID);
|
||||
if (ret != 0)
|
||||
pr_err("[FACTORY] %s - ret = %d\n", __func__, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(adsp_unicast);
|
||||
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_DEVICE_MODE) || defined(CONFIG_VBUS_NOTIFIER) || IS_ENABLED(CONFIG_HALL_NOTIFIER)
|
||||
struct adsp_data* adsp_ssc_core_register(unsigned int type,
|
||||
struct device_attribute *attributes[])
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
data->sensor_attr[type] = attributes;
|
||||
ret = sensors_register(&data->sensor_device[type], data,
|
||||
data->sensor_attr[type], "ssc_core");
|
||||
|
||||
data->sysfs_created[type] = true;
|
||||
pr_info("[FACTORY] %s - type:%u ptr:%pK\n",
|
||||
__func__, type, data->sensor_device[type]);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
struct adsp_data* adsp_ssc_core_unregister(unsigned int type)
|
||||
{
|
||||
pr_info("[FACTORY] %s - type:%u ptr:%pK\n",
|
||||
__func__, type, data->sensor_device[type]);
|
||||
|
||||
if (data->sysfs_created[type]) {
|
||||
sensors_unregister(data->sensor_device[type],
|
||||
data->sensor_attr[type]);
|
||||
data->sysfs_created[type] = false;
|
||||
} else {
|
||||
pr_info("[FACTORY] %s: skip type %u\n", __func__, type);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
#endif
|
||||
|
||||
int adsp_factory_register(unsigned int type,
|
||||
struct device_attribute *attributes[])
|
||||
{
|
||||
int ret = 0;
|
||||
char *dev_name;
|
||||
|
||||
switch (type) {
|
||||
case MSG_ACCEL:
|
||||
dev_name = "accelerometer_sensor";
|
||||
break;
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_ACCEL_HIGHG)
|
||||
case MSG_ACCEL_HIGHG:
|
||||
dev_name = "accelerometer_sensor_high_g";
|
||||
break;
|
||||
#endif
|
||||
case MSG_GYRO:
|
||||
dev_name = "gyro_sensor";
|
||||
break;
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_DUAL_6AXIS)
|
||||
case MSG_ACCEL_SUB:
|
||||
dev_name = "sub_accelerometer_sensor";
|
||||
break;
|
||||
case MSG_GYRO_SUB:
|
||||
dev_name = "sub_gyro_sensor";
|
||||
break;
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_TRIPLE_6AXIS)
|
||||
case MSG_ACCEL_SUB2:
|
||||
dev_name = "sub2_accelerometer_sensor";
|
||||
break;
|
||||
case MSG_GYRO_SUB2:
|
||||
dev_name = "sub2_gyro_sensor";
|
||||
break;
|
||||
#endif
|
||||
case MSG_MAG:
|
||||
dev_name = "magnetic_sensor";
|
||||
break;
|
||||
case MSG_PRESSURE:
|
||||
dev_name = "barometer_sensor";
|
||||
break;
|
||||
case MSG_LIGHT:
|
||||
dev_name = "light_sensor";
|
||||
break;
|
||||
case MSG_PROX:
|
||||
dev_name = "proximity_sensor";
|
||||
break;
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_DUAL_OPTIC)
|
||||
case MSG_LIGHT_SUB:
|
||||
dev_name = "sub_light_sensor";
|
||||
break;
|
||||
case MSG_PROX_SUB:
|
||||
dev_name = "sub_proximity_sensor";
|
||||
break;
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_FLIP_COVER_DETECTOR_FACTORY)
|
||||
case MSG_FLIP_COVER_DETECTOR:
|
||||
dev_name = "flip_cover_detector_sensor";
|
||||
break;
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_BACKTAP_FACTORY)
|
||||
case MSG_BACKTAP:
|
||||
dev_name = "backtap_sensor";
|
||||
break;
|
||||
#endif
|
||||
case MSG_SSC_CORE:
|
||||
dev_name = "ssc_core";
|
||||
break;
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_AK09973)
|
||||
case MSG_DIGITAL_HALL:
|
||||
dev_name = "digital_hall";
|
||||
break;
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_DUAL_MAG) || defined(CONFIG_SUPPORT_DUAL_MAG)
|
||||
case MSG_MAG_SUB:
|
||||
dev_name = "sub_magnetic_sensor";
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
dev_name = "unknown_sensor";
|
||||
break;
|
||||
}
|
||||
|
||||
data->sensor_attr[type] = attributes;
|
||||
ret = sensors_register(&data->sensor_device[type], data,
|
||||
data->sensor_attr[type], dev_name);
|
||||
|
||||
data->sysfs_created[type] = true;
|
||||
pr_info("[FACTORY] %s - type:%u ptr:%pK\n",
|
||||
__func__, type, data->sensor_device[type]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(adsp_factory_register);
|
||||
|
||||
int adsp_factory_unregister(unsigned int type)
|
||||
{
|
||||
pr_info("[FACTORY] %s - type:%u ptr:%pK\n",
|
||||
__func__, type, data->sensor_device[type]);
|
||||
|
||||
if (data->sysfs_created[type]) {
|
||||
sensors_unregister(data->sensor_device[type],
|
||||
data->sensor_attr[type]);
|
||||
data->sysfs_created[type] = false;
|
||||
} else {
|
||||
pr_info("[FACTORY] %s: skip type %u\n", __func__, type);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(adsp_factory_unregister);
|
||||
|
||||
int get_accel_raw_data(int32_t *raw_data)
|
||||
{
|
||||
uint8_t cnt = 0;
|
||||
|
||||
adsp_unicast(NULL, 0, MSG_ACCEL, 0, MSG_TYPE_GET_RAW_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_RAW_DATA] & 1 << MSG_ACCEL) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_RAW_DATA] &= ~(1 << MSG_ACCEL);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(raw_data, &data->msg_buf[MSG_ACCEL][0], sizeof(int32_t) * 3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(get_accel_raw_data);
|
||||
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_DUAL_6AXIS)
|
||||
int get_sub_accel_raw_data(int32_t *raw_data)
|
||||
{
|
||||
uint8_t cnt = 0;
|
||||
|
||||
adsp_unicast(NULL, 0, MSG_ACCEL_SUB, 0, MSG_TYPE_GET_RAW_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_RAW_DATA] & 1 << MSG_ACCEL_SUB) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_RAW_DATA] &= ~(1 << MSG_ACCEL_SUB);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(raw_data, &data->msg_buf[MSG_ACCEL_SUB][0], sizeof(int32_t) * 3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_ACCEL_HIGHG)
|
||||
int get_accel_highg_raw_data(int32_t *raw_data)
|
||||
{
|
||||
uint8_t cnt = 0;
|
||||
|
||||
adsp_unicast(NULL, 0, MSG_ACCEL_HIGHG, 0, MSG_TYPE_GET_RAW_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_RAW_DATA] & 1 << MSG_ACCEL_HIGHG) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_RAW_DATA] &= ~(1 << MSG_ACCEL_HIGHG);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(raw_data, &data->msg_buf[MSG_ACCEL_HIGHG][0], sizeof(int32_t) * 3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_TRIPLE_6AXIS)
|
||||
int get_sub2_accel_raw_data(int32_t *raw_data)
|
||||
{
|
||||
uint8_t cnt = 0;
|
||||
|
||||
adsp_unicast(NULL, 0, MSG_ACCEL_SUB2, 0, MSG_TYPE_GET_RAW_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_RAW_DATA] & 1 << MSG_ACCEL_SUB2) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_RAW_DATA] &= ~(1 << MSG_ACCEL_SUB2);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(raw_data, &data->msg_buf[MSG_ACCEL_SUB2][0], sizeof(int32_t) * 3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_AK09973)
|
||||
void lsm6dso_selftest_stop_work_func(struct work_struct *work)
|
||||
{
|
||||
int msg_buf = LSM6DSO_SELFTEST_FALSE;
|
||||
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)
|
||||
void lsm6dso_selftest_stop_work_func(struct work_struct *work)
|
||||
{
|
||||
int msg_buf = LSM6DSO_SELFTEST_FALSE;
|
||||
adsp_unicast(&msg_buf, sizeof(msg_buf),
|
||||
MSG_REF_ANGLE, 0, MSG_TYPE_OPTION_DEFINE);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CONFIG_SEC_FACTORY
|
||||
int get_mag_raw_data(int32_t *raw_data)
|
||||
{
|
||||
uint8_t cnt = 0;
|
||||
|
||||
adsp_unicast(NULL, 0, MSG_MAG, 0, MSG_TYPE_GET_RAW_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_RAW_DATA] & 1 << MSG_MAG) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_RAW_DATA] &= ~(1 << MSG_MAG);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(raw_data, &data->msg_buf[MSG_MAG][0], sizeof(int32_t) * 3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_AK09973)
|
||||
int get_hall_angle_data(int32_t *raw_data)
|
||||
{
|
||||
uint8_t cnt = 0;
|
||||
|
||||
mutex_lock(&data->digital_hall_mutex);
|
||||
adsp_unicast(NULL, 0, MSG_DIGITAL_HALL_ANGLE, 0, MSG_TYPE_GET_RAW_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_RAW_DATA] & 1 << MSG_DIGITAL_HALL_ANGLE) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_RAW_DATA] &= ~(1 << MSG_DIGITAL_HALL_ANGLE);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pr_info("[FACTORY] %s - st %d/%d, akm %d/%d, lf %d/%d, hall %d/%d/%d(uT)\n",
|
||||
__func__, data->msg_buf[MSG_DIGITAL_HALL_ANGLE][0],
|
||||
data->msg_buf[MSG_DIGITAL_HALL_ANGLE][1],
|
||||
data->msg_buf[MSG_DIGITAL_HALL_ANGLE][2],
|
||||
data->msg_buf[MSG_DIGITAL_HALL_ANGLE][3],
|
||||
data->msg_buf[MSG_DIGITAL_HALL_ANGLE][4],
|
||||
data->msg_buf[MSG_DIGITAL_HALL_ANGLE][5],
|
||||
data->msg_buf[MSG_DIGITAL_HALL_ANGLE][6],
|
||||
data->msg_buf[MSG_DIGITAL_HALL_ANGLE][7],
|
||||
data->msg_buf[MSG_DIGITAL_HALL_ANGLE][8]);
|
||||
|
||||
*raw_data = data->msg_buf[MSG_DIGITAL_HALL_ANGLE][2];
|
||||
mutex_unlock(&data->digital_hall_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int process_received_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
|
||||
{
|
||||
u16 sensor_type = nlh->nlmsg_type >> 8;
|
||||
u16 msg_type = nlh->nlmsg_type & 0xff;
|
||||
|
||||
/* check the boundary to prevent memory attack */
|
||||
if (msg_type >= MSG_TYPE_MAX || sensor_type >= MSG_SENSOR_MAX ||
|
||||
nlh->nlmsg_len - (int32_t)sizeof(struct nlmsghdr) >
|
||||
sizeof(int32_t) * msg_size[sensor_type]) {
|
||||
pr_err("[FACTORY] %s %d, %d, %d\n", __func__, msg_type, sensor_type, nlh->nlmsg_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sensor_type == MSG_FACTORY_INIT_CMD) {
|
||||
pr_info("[FACTORY] %s - MSG_FACTORY_INIT_CMD\n", __func__);
|
||||
accel_factory_init_work(data);
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_DUAL_6AXIS)
|
||||
sub_accel_factory_init_work(data);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_ACCEL_HIGHG)
|
||||
accel_highg_factory_init_work(data);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_DEVICE_MODE)
|
||||
sns_device_mode_init_work();
|
||||
sns_flip_init_work();
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_LIGHT_FACTORY)
|
||||
light_init_work(data);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_LIGHT_CALIBRATION)
|
||||
light_cal_init_work(data);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_PROX_CALIBRATION)
|
||||
prox_cal_init_work(data);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_PROX_POWER_ON_CAL)
|
||||
prox_factory_init_work();
|
||||
#endif
|
||||
#ifdef CONFIG_VBUS_NOTIFIER
|
||||
sns_vbus_init_work();
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_AK09973)
|
||||
digital_hall_factory_auto_cal_init_work(data);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_FLIP_COVER_DETECTOR_FACTORY)
|
||||
flip_cover_detector_cal_init_work();
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_LIGHT_SEAMLESS)
|
||||
light_seamless_init_work(data);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_LPS22HH_FACTORY) || IS_ENABLED(CONFIG_PRESSURE_FACTORY)
|
||||
pressure_factory_init_work(data);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_HALL_NOTIFIER)
|
||||
sns_mpp_cover_init_work();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(data->msg_buf[sensor_type],
|
||||
(int32_t *)NLMSG_DATA(nlh),
|
||||
nlh->nlmsg_len - (int32_t)sizeof(struct nlmsghdr));
|
||||
data->ready_flag[msg_type] |= 1 << sensor_type;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void factory_receive_skb(struct sk_buff *skb)
|
||||
{
|
||||
struct netlink_ext_ack extack = {};
|
||||
struct nlmsghdr *nlh;
|
||||
int len;
|
||||
int err;
|
||||
|
||||
nlh = (struct nlmsghdr *)skb->data;
|
||||
len = skb->len;
|
||||
while (NLMSG_OK(nlh, len)) {
|
||||
err = process_received_msg(skb, nlh);
|
||||
/* if err or if this message says it wants a response */
|
||||
if (err || (nlh->nlmsg_flags & NLM_F_ACK))
|
||||
netlink_ack(skb, nlh, err, &extack);
|
||||
nlh = NLMSG_NEXT(nlh, len);
|
||||
}
|
||||
}
|
||||
|
||||
/* Receive messages from netlink socket. */
|
||||
static void factory_test_result_receive(struct sk_buff *skb)
|
||||
{
|
||||
mutex_lock(&factory_mutex);
|
||||
factory_receive_skb(skb);
|
||||
mutex_unlock(&factory_mutex);
|
||||
}
|
||||
|
||||
struct netlink_kernel_cfg netlink_cfg = {
|
||||
.input = factory_test_result_receive,
|
||||
};
|
||||
|
||||
static int __init factory_adsp_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
pr_info("[FACTORY] %s\n", __func__);
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
|
||||
for (i = 0; i < MSG_SENSOR_MAX; i++) {
|
||||
if (msg_size[i] > 0)
|
||||
data->msg_buf[i] = kzalloc(sizeof(int32_t) * msg_size[i],
|
||||
GFP_KERNEL);
|
||||
}
|
||||
|
||||
data->adsp_skt = netlink_kernel_create(&init_net,
|
||||
NETLINK_ADSP_FAC, &netlink_cfg);
|
||||
|
||||
for (i = 0; i < MSG_SENSOR_MAX; i++)
|
||||
data->sysfs_created[i] = false;
|
||||
for (i = 0; i < MSG_TYPE_MAX; i++)
|
||||
data->ready_flag[i] = 0;
|
||||
|
||||
data->restrict_mode = false;
|
||||
data->turn_over_crash = 0;
|
||||
data->fssr_ignore = false;
|
||||
data->fssr_dump = false;
|
||||
mutex_init(&data->accel_factory_mutex);
|
||||
mutex_init(&data->prox_factory_mutex);
|
||||
mutex_init(&data->light_factory_mutex);
|
||||
mutex_init(&data->remove_sysfs_mutex);
|
||||
mutex_init(&data->sensors_dump_mutex);
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_DUAL_OPTIC)
|
||||
mutex_init(&data->vir_optic_factory_mutex);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_FLIP_COVER_DETECTOR_FACTORY)
|
||||
mutex_init(&data->flip_cover_factory_mutex);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_BACKTAP_FACTORY)
|
||||
mutex_init(&data->backtap_factory_mutex);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_AK09973)
|
||||
mutex_init(&data->digital_hall_mutex);
|
||||
INIT_DELAYED_WORK(&data->dhall_cal_work, dhall_cal_work_func);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_LIGHT_FACTORY)
|
||||
INIT_DELAYED_WORK(&data->light_init_work, light_init_work_func);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_LIGHT_CALIBRATION)
|
||||
INIT_DELAYED_WORK(&data->light_cal_work, light_cal_read_work_func);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_DDI_COPR_FOR_LIGHT_SENSOR)
|
||||
INIT_DELAYED_WORK(&data->light_copr_debug_work,
|
||||
light_copr_debug_work_func);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_AP_COPR_FOR_LIGHT_SENSOR)
|
||||
INIT_DELAYED_WORK(&data->light_copr_work, light_copr_work_func);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_BRIGHTNESS_NOTIFY_FOR_LIGHT_SENSOR) && \
|
||||
IS_ENABLED(CONFIG_SEC_PANEL_NOTIFIER_V2)
|
||||
INIT_WORK(&data->light_br_work, light_brightness_work_func);
|
||||
#endif
|
||||
INIT_DELAYED_WORK(&data->accel_cal_work, accel_cal_work_func);
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_DUAL_6AXIS)
|
||||
INIT_DELAYED_WORK(&data->sub_accel_cal_work, sub_accel_cal_work_func);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_TRIPLE_6AXIS)
|
||||
INIT_DELAYED_WORK(&data->sub2_accel_cal_work, sub2_accel_cal_work_func);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_ACCEL_HIGHG)
|
||||
INIT_DELAYED_WORK(&data->accel_highg_cal_work, accel_highg_cal_work_func);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_AK09973) || IS_ENABLED(CONFIG_SUPPORT_REF_ANGLE_WITHOUT_DIGITAL_HALL) || defined(CONFIG_SUPPORT_REF_ANGLE_WITHOUT_DIGITAL_HALL)
|
||||
INIT_DELAYED_WORK(&data->lsm6dso_selftest_stop_work, lsm6dso_selftest_stop_work_func);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_LIGHT_SEAMLESS)
|
||||
INIT_DELAYED_WORK(&data->light_seamless_work, light_seamless_work_func);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_LPS22HH_FACTORY) || IS_ENABLED(CONFIG_PRESSURE_FACTORY)
|
||||
INIT_DELAYED_WORK(&data->pressure_cal_work, pressure_cal_work_func);
|
||||
#endif
|
||||
core_factory_init();
|
||||
#if IS_ENABLED(CONFIG_LSM6DSO_FACTORY)
|
||||
lsm6dso_accel_factory_init();
|
||||
lsm6dso_gyro_factory_init();
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_LSM6DSL_FACTORY)
|
||||
lsm6dsl_accel_factory_init();
|
||||
lsm6dsl_gyro_factory_init();
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_AK09918_FACTORY)
|
||||
ak09918_factory_init();
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_LPS22HH_FACTORY)
|
||||
lps22hh_pressure_factory_init();
|
||||
#elif IS_ENABLED(CONFIG_PRESSURE_FACTORY)
|
||||
pressure_factory_init();
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_BACKTAP_FACTORY)
|
||||
backtap_factory_init();
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_LIGHT_FACTORY)
|
||||
light_factory_init();
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_PROX_FACTORY)
|
||||
prox_factory_init();
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_DUAL_6AXIS)
|
||||
lsm6dso_sub_accel_factory_init();
|
||||
lsm6dso_sub_gyro_factory_init();
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_TRIPLE_6AXIS)
|
||||
sub2_accel_factory_init();
|
||||
sub2_gyro_factory_init();
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_ACCEL_HIGHG)
|
||||
accel_highg_factory_init();
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_AK09973)
|
||||
ak09970_factory_init();
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_FLIP_COVER_DETECTOR_FACTORY)
|
||||
flip_cover_detector_factory_init();
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_DUAL_MAG)
|
||||
mag_sub_factory_init();
|
||||
#endif
|
||||
|
||||
pr_info("[FACTORY] %s: Timer Init\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit factory_adsp_exit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
core_factory_exit();
|
||||
#if IS_ENABLED(CONFIG_LSM6DSO_FACTORY)
|
||||
lsm6dso_accel_factory_exit();
|
||||
lsm6dso_gyro_factory_exit();
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_LSM6DSL_FACTORY)
|
||||
lsm6dsl_accel_factory_exit();
|
||||
lsm6dsl_gyro_factory_exit();
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_AK09918_FACTORY)
|
||||
ak09918_factory_exit();
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_LPS22HH_FACTORY)
|
||||
lps22hh_pressure_factory_exit();
|
||||
#elif IS_ENABLED(CONFIG_PRESSURE_FACTORY)
|
||||
pressure_factory_exit();
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_BACKTAP_FACTORY)
|
||||
backtap_factory_exit();
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_LIGHT_FACTORY)
|
||||
cancel_delayed_work_sync(&data->light_init_work);
|
||||
light_factory_exit();
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_PROX_FACTORY)
|
||||
prox_factory_exit();
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_DUAL_6AXIS)
|
||||
lsm6dso_sub_accel_factory_exit();
|
||||
lsm6dso_sub_gyro_factory_exit();
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_TRIPLE_6AXIS)
|
||||
sub2_accel_factory_exit();
|
||||
sub2_gyro_factory_exit();
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_ACCEL_HIGHG) || defined(CONFIG_SUPPORT_ACCEL_HIGHG)
|
||||
accel_highg_factory_exit();
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_AK09973)
|
||||
ak09970_factory_exit();
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_FLIP_COVER_DETECTOR_FACTORY)
|
||||
flip_cover_detector_factory_exit();
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_DUAL_MAG)
|
||||
mag_sub_factory_exit();
|
||||
#endif
|
||||
mutex_destroy(&data->accel_factory_mutex);
|
||||
mutex_destroy(&data->prox_factory_mutex);
|
||||
mutex_destroy(&data->light_factory_mutex);
|
||||
mutex_destroy(&data->remove_sysfs_mutex);
|
||||
mutex_destroy(&data->sensors_dump_mutex);
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_DUAL_OPTIC)
|
||||
mutex_destroy(&data->vir_optic_factory_mutex);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_FLIP_COVER_DETECTOR_FACTORY)
|
||||
mutex_destroy(&data->flip_cover_factory_mutex);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_BACKTAP_FACTORY)
|
||||
mutex_destroy(&data->backtap_factory_mutex);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_AK09973)
|
||||
mutex_destroy(&data->digital_hall_mutex);
|
||||
cancel_delayed_work_sync(&data->dhall_cal_work);
|
||||
cancel_delayed_work_sync(&data->lsm6dso_selftest_stop_work);
|
||||
#elif IS_ENABLED(CONFIG_SUPPORT_REF_ANGLE_WITHOUT_DIGITAL_HALL) || defined(CONFIG_SUPPORT_REF_ANGLE_WITHOUT_DIGITAL_HALL)
|
||||
cancel_delayed_work_sync(&data->lsm6dso_selftest_stop_work);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_LIGHT_CALIBRATION)
|
||||
cancel_delayed_work_sync(&data->light_cal_work);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_DDI_COPR_FOR_LIGHT_SENSOR)
|
||||
cancel_delayed_work_sync(&data->light_copr_debug_work);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_AP_COPR_FOR_LIGHT_SENSOR)
|
||||
cancel_delayed_work_sync(&data->light_copr_work);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_BRIGHTNESS_NOTIFY_FOR_LIGHT_SENSOR)
|
||||
cancel_work_sync(&data->light_br_work);
|
||||
#endif
|
||||
cancel_delayed_work_sync(&data->accel_cal_work);
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_DUAL_6AXIS)
|
||||
cancel_delayed_work_sync(&data->sub_accel_cal_work);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_TRIPLE_6AXIS)
|
||||
cancel_delayed_work_sync(&data->sub2_accel_cal_work);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_ACCEL_HIGHG) || defined(CONFIG_SUPPORT_ACCEL_HIGHG)
|
||||
cancel_delayed_work_sync(&data->accel_highg_cal_work);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_LIGHT_SEAMLESS)
|
||||
cancel_delayed_work_sync(&data->light_seamless_work);
|
||||
#endif
|
||||
cancel_delayed_work_sync(&data->pressure_cal_work);
|
||||
|
||||
for (i = 0; i < MSG_SENSOR_MAX; i++)
|
||||
kfree(data->msg_buf[i]);
|
||||
pr_info("[FACTORY] %s\n", __func__);
|
||||
}
|
||||
|
||||
module_init(factory_adsp_init);
|
||||
module_exit(factory_adsp_exit);
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("Support for factory test sensors (adsp)");
|
256
drivers/adsp_factory/ak09918_mag.c
Executable file
256
drivers/adsp_factory/ak09918_mag.c
Executable file
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
* 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"
|
||||
#define VENDOR "AKM"
|
||||
#define CHIP_ID "AK09918"
|
||||
|
||||
#define MAG_ST_TRY_CNT 3
|
||||
#define ABS(x) (((x)>0)?(x):-(x))
|
||||
#define AKM_ST_FAIL (-1)
|
||||
|
||||
static ssize_t mag_vendor_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", VENDOR);
|
||||
}
|
||||
|
||||
static ssize_t mag_name_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", CHIP_ID);
|
||||
}
|
||||
|
||||
static ssize_t mag_check_cntl(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "OK\n");
|
||||
}
|
||||
|
||||
static ssize_t mag_check_registers(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE,
|
||||
"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
static ssize_t mag_get_asa(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
/* Do not have Fuserom */
|
||||
return snprintf(buf, PAGE_SIZE, "%u,%u,%u\n", 128, 128, 128);
|
||||
}
|
||||
|
||||
static ssize_t mag_get_status(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
/* Do not have Fuserom */
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", "OK");
|
||||
}
|
||||
|
||||
static ssize_t mag_raw_data_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
uint8_t cnt = 0;
|
||||
|
||||
adsp_unicast(NULL, 0, MSG_MAG, 0, MSG_TYPE_GET_RAW_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_RAW_DATA] & 1 << MSG_MAG) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_RAW_DATA] &= ~(1 << MSG_MAG);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
return snprintf(buf, PAGE_SIZE, "0,0,0\n");
|
||||
}
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d,%d,%d\n",
|
||||
data->msg_buf[MSG_MAG][0],
|
||||
data->msg_buf[MSG_MAG][1],
|
||||
data->msg_buf[MSG_MAG][2]);
|
||||
}
|
||||
|
||||
static ssize_t mag_raw_data_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
adsp_unicast(NULL, 0, MSG_MAG_CAL, 0, MSG_TYPE_FACTORY_ENABLE);
|
||||
msleep(20);
|
||||
adsp_unicast(NULL, 0, MSG_MAG_CAL, 0, MSG_TYPE_SET_CAL_DATA);
|
||||
msleep(20);
|
||||
adsp_unicast(NULL, 0, MSG_MAG_CAL, 0, MSG_TYPE_FACTORY_DISABLE);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t mag_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, i;
|
||||
int abs_adc_sum = 0, abs_adc_x = 0, abs_adc_y = 0, abs_adc_z = 0;
|
||||
int st_status = 0;
|
||||
|
||||
RETRY_MAG_SELFTEST:
|
||||
pr_info("[FACTORY] %s - start\n", __func__);
|
||||
adsp_unicast(NULL, 0, MSG_MAG, 0, MSG_TYPE_ST_SHOW_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_ST_SHOW_DATA] & 1 << MSG_MAG) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
msleep(26);
|
||||
|
||||
data->ready_flag[MSG_TYPE_ST_SHOW_DATA] &= ~(1 << MSG_MAG);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
data->msg_buf[MSG_MAG][0] = -1;
|
||||
#ifdef CONFIG_SEC_FACTORY
|
||||
panic("force crash : sensor selftest timeout\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!(data->msg_buf[MSG_MAG][0] == 0)) {
|
||||
if (retry < MAG_ST_TRY_CNT) {
|
||||
retry++;
|
||||
for (i = 0; i < 10; i++)
|
||||
data->msg_buf[MSG_MAG][i] = 0;
|
||||
|
||||
msleep(100);
|
||||
cnt = 0;
|
||||
pr_info("[FACTORY] %s - retry %d\n", __func__, retry);
|
||||
goto RETRY_MAG_SELFTEST;
|
||||
}
|
||||
|
||||
adsp_unicast(NULL, 0, MSG_MAG_CAL, 0, MSG_TYPE_FACTORY_ENABLE);
|
||||
msleep(20);
|
||||
adsp_unicast(NULL, 0, MSG_MAG_CAL, 0, MSG_TYPE_SET_CAL_DATA);
|
||||
msleep(20);
|
||||
adsp_unicast(NULL, 0, MSG_MAG_CAL, 0, MSG_TYPE_FACTORY_DISABLE);
|
||||
return snprintf(buf, PAGE_SIZE, "-1,0,0,0,0,0,0,0,0,0\n");
|
||||
}
|
||||
|
||||
if (data->msg_buf[MSG_MAG][1] != 0) {
|
||||
pr_info("[FACTORY] %s - msg_buf[1] 0x%x\n", __func__, data->msg_buf[MSG_MAG][1]);
|
||||
st_status = AKM_ST_FAIL;
|
||||
}
|
||||
pr_info("[FACTORY] status=%d, st_status=%d, st_xyz=%d,%d,%d, dac=%d, adc=%d, adc_xyz=%d,%d,%d\n",
|
||||
data->msg_buf[MSG_MAG][0], st_status,
|
||||
data->msg_buf[MSG_MAG][2], data->msg_buf[MSG_MAG][3],
|
||||
data->msg_buf[MSG_MAG][4], data->msg_buf[MSG_MAG][5],
|
||||
data->msg_buf[MSG_MAG][6], data->msg_buf[MSG_MAG][7],
|
||||
data->msg_buf[MSG_MAG][8], data->msg_buf[MSG_MAG][9]);
|
||||
|
||||
abs_adc_x = ABS(data->msg_buf[MSG_MAG][7]);
|
||||
abs_adc_y = ABS(data->msg_buf[MSG_MAG][8]);
|
||||
abs_adc_z = ABS(data->msg_buf[MSG_MAG][9]);
|
||||
abs_adc_sum = abs_adc_x + abs_adc_y + abs_adc_z;
|
||||
|
||||
if (abs_adc_sum >= 26666) {
|
||||
pr_info("[FACTORY] abs_adc_sum is higher then 40Gauss\n");
|
||||
st_status = AKM_ST_FAIL;
|
||||
}
|
||||
|
||||
adsp_unicast(NULL, 0, MSG_MAG_CAL, 0, MSG_TYPE_FACTORY_ENABLE);
|
||||
msleep(20);
|
||||
adsp_unicast(NULL, 0, MSG_MAG_CAL, 0, MSG_TYPE_SET_CAL_DATA);
|
||||
msleep(20);
|
||||
adsp_unicast(NULL, 0, MSG_MAG_CAL, 0, MSG_TYPE_FACTORY_DISABLE);
|
||||
return snprintf(buf, PAGE_SIZE, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
|
||||
data->msg_buf[MSG_MAG][0], st_status,
|
||||
data->msg_buf[MSG_MAG][2], data->msg_buf[MSG_MAG][3],
|
||||
data->msg_buf[MSG_MAG][4], data->msg_buf[MSG_MAG][5],
|
||||
data->msg_buf[MSG_MAG][6], data->msg_buf[MSG_MAG][7],
|
||||
data->msg_buf[MSG_MAG][8], data->msg_buf[MSG_MAG][9]);
|
||||
}
|
||||
|
||||
static ssize_t mag_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;
|
||||
|
||||
adsp_unicast(NULL, 0, MSG_MAG, 0, MSG_TYPE_GET_DHR_INFO);
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_DHR_INFO] & 1 << MSG_MAG) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_DHR_INFO] &= ~(1 << MSG_MAG);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
} else {
|
||||
pr_info("[FACTORY] %s - [00h-03h] %02x,%02x,%02x,%02x [10h-16h,18h] %02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x [30h-32h] %02x,%02x,%02x\n",
|
||||
__func__,
|
||||
data->msg_buf[MSG_MAG][0], data->msg_buf[MSG_MAG][1],
|
||||
data->msg_buf[MSG_MAG][2], data->msg_buf[MSG_MAG][3],
|
||||
data->msg_buf[MSG_MAG][4], data->msg_buf[MSG_MAG][5],
|
||||
data->msg_buf[MSG_MAG][6], data->msg_buf[MSG_MAG][7],
|
||||
data->msg_buf[MSG_MAG][8], data->msg_buf[MSG_MAG][9],
|
||||
data->msg_buf[MSG_MAG][10], data->msg_buf[MSG_MAG][11],
|
||||
data->msg_buf[MSG_MAG][12], data->msg_buf[MSG_MAG][13],
|
||||
data->msg_buf[MSG_MAG][14]);
|
||||
}
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", "Done");
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(name, 0444, mag_name_show, NULL);
|
||||
static DEVICE_ATTR(vendor, 0444, mag_vendor_show, NULL);
|
||||
static DEVICE_ATTR(raw_data, 0664, mag_raw_data_show, mag_raw_data_store);
|
||||
static DEVICE_ATTR(dac, 0444, mag_check_cntl, NULL);
|
||||
static DEVICE_ATTR(chk_registers, 0444, mag_check_registers, NULL);
|
||||
static DEVICE_ATTR(selftest, 0440, mag_selftest_show, NULL);
|
||||
static DEVICE_ATTR(asa, 0444, mag_get_asa, NULL);
|
||||
static DEVICE_ATTR(status, 0444, mag_get_status, NULL);
|
||||
#ifdef CONFIG_SEC_FACTORY
|
||||
static DEVICE_ATTR(dhr_sensor_info, 0444, mag_dhr_sensor_info_show, NULL);
|
||||
#else
|
||||
static DEVICE_ATTR(dhr_sensor_info, 0440, mag_dhr_sensor_info_show, NULL);
|
||||
#endif
|
||||
|
||||
static struct device_attribute *mag_attrs[] = {
|
||||
&dev_attr_name,
|
||||
&dev_attr_vendor,
|
||||
&dev_attr_raw_data,
|
||||
&dev_attr_dac,
|
||||
&dev_attr_chk_registers,
|
||||
&dev_attr_selftest,
|
||||
&dev_attr_asa,
|
||||
&dev_attr_status,
|
||||
&dev_attr_dhr_sensor_info,
|
||||
NULL,
|
||||
};
|
||||
|
||||
int ak09918_factory_init(void)
|
||||
{
|
||||
adsp_factory_register(MSG_MAG, mag_attrs);
|
||||
|
||||
pr_info("[FACTORY] %s\n", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ak09918_factory_exit(void)
|
||||
{
|
||||
adsp_factory_unregister(MSG_MAG);
|
||||
|
||||
pr_info("[FACTORY] %s\n", __func__);
|
||||
}
|
1242
drivers/adsp_factory/ak09973_digital_hall.c
Executable file
1242
drivers/adsp_factory/ak09973_digital_hall.c
Executable file
File diff suppressed because it is too large
Load Diff
163
drivers/adsp_factory/back_tap.c
Normal file
163
drivers/adsp_factory/back_tap.c
Normal file
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright (C) 2024, 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"
|
||||
#define NAME "Back Tap"
|
||||
#define VENDOR "Samsung"
|
||||
|
||||
/* 1: Double Tap
|
||||
* 2: Triple Tap
|
||||
* 3: Double and Triple Tap
|
||||
*/
|
||||
static int backtap_type = 3;
|
||||
static int backtap_thd;
|
||||
|
||||
static ssize_t backtap_name_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", NAME);
|
||||
}
|
||||
|
||||
static ssize_t backtap_vendor_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", VENDOR);
|
||||
}
|
||||
|
||||
static ssize_t backtap_peak_thd_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
pr_info("[FACTORY] %s: Curr THD %d\n", __func__, backtap_thd);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", backtap_thd);
|
||||
}
|
||||
|
||||
static ssize_t backtap_peak_thd_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
int cnt = 0;
|
||||
int msg_buf;
|
||||
int ret = 0;
|
||||
|
||||
ret = kstrtoint(buf, 10, &msg_buf);
|
||||
if (ret < 0) {
|
||||
pr_err("[FACTORY] %s: kstrtoint fail\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (msg_buf < 0 || msg_buf > 2) {
|
||||
pr_err("[FACTORY] %s: Invalid value\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pr_info("[FACTORY] %s: msg_buf = %d\n", __func__, msg_buf);
|
||||
|
||||
mutex_lock(&data->backtap_factory_mutex);
|
||||
adsp_unicast(&msg_buf, sizeof(int),
|
||||
MSG_BACKTAP, 0, MSG_TYPE_SET_THRESHOLD);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_SET_THRESHOLD] & 1 << MSG_BACKTAP) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_SET_THRESHOLD] &= ~(1 << MSG_BACKTAP);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT)
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
else
|
||||
backtap_thd = data->msg_buf[MSG_BACKTAP][0];
|
||||
|
||||
pr_info("[FACTORY] %s: New THD %d\n", __func__, backtap_thd);
|
||||
mutex_unlock(&data->backtap_factory_mutex);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t backtap_type_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
pr_info("[FACTORY] %s: Curr Type %d\n", __func__, backtap_type);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", backtap_type);
|
||||
}
|
||||
|
||||
static ssize_t backtap_type_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
int cnt = 0;
|
||||
int msg_buf;
|
||||
int ret = 0;
|
||||
|
||||
ret = kstrtoint(buf, 10, &msg_buf);
|
||||
if (ret < 0) {
|
||||
pr_err("[FACTORY] %s: kstrtoint fail\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (msg_buf <= 0 || msg_buf >= 4) {
|
||||
pr_err("[FACTORY] %s: Invalid value\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pr_info("[FACTORY] %s: msg_buf = %d\n", __func__, msg_buf);
|
||||
|
||||
mutex_lock(&data->backtap_factory_mutex);
|
||||
adsp_unicast(&msg_buf, sizeof(int),
|
||||
MSG_BACKTAP, 0, MSG_TYPE_OPTION_DEFINE);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_OPTION_DEFINE] & 1 << MSG_BACKTAP) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_OPTION_DEFINE] &= ~(1 << MSG_BACKTAP);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT)
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
else
|
||||
backtap_type = data->msg_buf[MSG_BACKTAP][0];
|
||||
|
||||
pr_info("[FACTORY] %s: New Type %d\n", __func__, backtap_type);
|
||||
mutex_unlock(&data->backtap_factory_mutex);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(name, 0444, backtap_name_show, NULL);
|
||||
static DEVICE_ATTR(vendor, 0444, backtap_vendor_show, NULL);
|
||||
static DEVICE_ATTR(backtap_peak_thd, 0660, backtap_peak_thd_show, backtap_peak_thd_store);
|
||||
static DEVICE_ATTR(backtap_type, 0660, backtap_type_show, backtap_type_store);
|
||||
|
||||
static struct device_attribute *backtap_attrs[] = {
|
||||
&dev_attr_name,
|
||||
&dev_attr_vendor,
|
||||
&dev_attr_backtap_peak_thd,
|
||||
&dev_attr_backtap_type,
|
||||
NULL,
|
||||
};
|
||||
|
||||
int __init backtap_factory_init(void)
|
||||
{
|
||||
adsp_factory_register(MSG_BACKTAP, backtap_attrs);
|
||||
pr_info("[FACTORY] %s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __exit backtap_factory_exit(void)
|
||||
{
|
||||
adsp_factory_unregister(MSG_BACKTAP);
|
||||
pr_info("[FACTORY] %s\n", __func__);
|
||||
}
|
707
drivers/adsp_factory/flip_cover_detector.c
Executable file
707
drivers/adsp_factory/flip_cover_detector.c
Executable file
@@ -0,0 +1,707 @@
|
||||
/*
|
||||
* Copyright (C) 2020, 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 <linux/of.h>
|
||||
#include <linux/notifier.h>
|
||||
#include "adsp.h"
|
||||
|
||||
enum {
|
||||
OFF = 0,
|
||||
ON = 1
|
||||
};
|
||||
|
||||
enum {
|
||||
X = 0,
|
||||
Y = 1,
|
||||
Z = 2,
|
||||
AXIS_MAX
|
||||
};
|
||||
|
||||
#define ATTACH "ATTACH"
|
||||
#define DETACH "DETACH"
|
||||
#define PASS "PASS"
|
||||
#define FAIL "FAIL"
|
||||
|
||||
#define AXIS_SELECT X
|
||||
#define THRESHOLD -500
|
||||
#define DETACH_MARGIN 100
|
||||
#define SATURATION_VALUE 4900
|
||||
#define MAG_DELAY_MS 10
|
||||
|
||||
#define COVER_DETACH 0 // OPEN
|
||||
#define COVER_ATTACH 1 // CLOSE
|
||||
#define COVER_ATTACH_NFC_ACTIVE 2 // CLOSE
|
||||
#define COVER_ATTACH_NFC_TAG_PRESENT 7 // CLOSE
|
||||
|
||||
static bool fcd_available;
|
||||
static int fcd_dual_cal_matrix;
|
||||
|
||||
struct factory_cover_status_data {
|
||||
char cover_status[10];
|
||||
uint32_t axis_select;
|
||||
int32_t threshold;
|
||||
int32_t init[AXIS_MAX];
|
||||
int32_t attach[AXIS_MAX];
|
||||
int32_t attach_extremum[AXIS_MAX];
|
||||
int32_t detach[AXIS_MAX];
|
||||
char attach_result[10];
|
||||
char detach_result[10];
|
||||
char final_result[10];
|
||||
|
||||
uint8_t factory_test_status;
|
||||
int32_t attach_diff;
|
||||
int32_t detach_diff;
|
||||
int32_t failed_attach_max;
|
||||
int32_t failed_attach_min;
|
||||
uint8_t saturation;
|
||||
};
|
||||
|
||||
struct flip_cover_detector_data {
|
||||
struct hrtimer fcd_timer;
|
||||
struct workqueue_struct *fcd_wq;
|
||||
struct work_struct work_fcd;
|
||||
ktime_t poll_delay;
|
||||
struct delayed_work notifier_work;
|
||||
struct adsp_data *data;
|
||||
};
|
||||
|
||||
struct factory_cover_status_data *factory_data;
|
||||
struct flip_cover_detector_data *fcd_data;
|
||||
|
||||
static int nfc_cover_status = -1;
|
||||
static uint32_t axis_update = AXIS_SELECT;
|
||||
static int32_t threshold_update = THRESHOLD;
|
||||
|
||||
char sysfs_cover_status[10];
|
||||
|
||||
#if IS_ENABLED(CONFIG_FLIP_COVER_DETECTOR_NOTIFIER)
|
||||
static BLOCKING_NOTIFIER_HEAD(fcd_nb_head);
|
||||
|
||||
int fcd_notifier_register(struct notifier_block *nb)
|
||||
{
|
||||
if (!fcd_available) {
|
||||
pr_info("%s: fcd not available\n", __func__);
|
||||
return -1;
|
||||
} else {
|
||||
pr_info("%s\n", __func__);
|
||||
return blocking_notifier_chain_register(&fcd_nb_head, nb);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fcd_notifier_register);
|
||||
|
||||
int fcd_notifier_unregister(struct notifier_block *nb)
|
||||
{
|
||||
if (!fcd_available) {
|
||||
pr_info("%s: fcd not available\n", __func__);
|
||||
return -1;
|
||||
} else {
|
||||
pr_info("%s\n", __func__);
|
||||
return blocking_notifier_chain_unregister(&fcd_nb_head, nb);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(fcd_notifier_unregister);
|
||||
|
||||
int fcd_notifier_call_chain(unsigned long val, void *v)
|
||||
{
|
||||
if (!fcd_available) {
|
||||
pr_info("%s: fcd not available\n", __func__);
|
||||
return -1;
|
||||
} else {
|
||||
pr_info("%s - %lu\n", __func__, val);
|
||||
return blocking_notifier_call_chain(&fcd_nb_head, val, v);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void send_axis_threshold_settings(struct adsp_data *data, int axis, int threshold)
|
||||
{
|
||||
uint8_t cnt = 0;
|
||||
uint16_t flip_cover_detector_idx = MSG_FLIP_COVER_DETECTOR;
|
||||
int32_t msg_buf[2];
|
||||
|
||||
msg_buf[0] = axis;
|
||||
msg_buf[1] = threshold;
|
||||
|
||||
mutex_lock(&data->flip_cover_factory_mutex);
|
||||
|
||||
adsp_unicast(msg_buf, sizeof(msg_buf),
|
||||
flip_cover_detector_idx, 0, MSG_TYPE_SET_THRESHOLD);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_SET_THRESHOLD] & 1 << flip_cover_detector_idx) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(20000, 20000);
|
||||
|
||||
data->ready_flag[MSG_TYPE_SET_THRESHOLD] &= ~(1 << flip_cover_detector_idx);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
} else {
|
||||
axis_update = axis;
|
||||
threshold_update = threshold;
|
||||
}
|
||||
|
||||
pr_info("[FACTORY] %s: axis=%d, threshold=%d\n", __func__, axis_update, threshold_update);
|
||||
|
||||
mutex_unlock(&data->flip_cover_factory_mutex);
|
||||
}
|
||||
|
||||
static void send_flip_cover_status_to_mag_sensor(struct adsp_data *data, int val)
|
||||
{
|
||||
uint8_t cnt = 0;
|
||||
int32_t msg_buf[1];
|
||||
|
||||
msg_buf[0] = val;
|
||||
|
||||
mutex_lock(&data->flip_cover_factory_mutex);
|
||||
|
||||
adsp_unicast(msg_buf, sizeof(msg_buf),
|
||||
MSG_MAG, 0, MSG_TYPE_SET_TEMPORARY_MSG);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_SET_TEMPORARY_MSG] & 1 << MSG_MAG) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(20000, 20000);
|
||||
|
||||
data->ready_flag[MSG_TYPE_SET_TEMPORARY_MSG] &= ~(1 << MSG_MAG);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT)
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
|
||||
pr_info("[FACTORY] %s: nfc_cover_status=%d set in mag sensor\n", __func__, nfc_cover_status);
|
||||
|
||||
mutex_unlock(&data->flip_cover_factory_mutex);
|
||||
}
|
||||
|
||||
static void notify_fcd_status(struct work_struct *work)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_FLIP_COVER_DETECTOR_NOTIFIER)
|
||||
fcd_notifier_call_chain(nfc_cover_status, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void send_nfc_cover_status(struct adsp_data *data, int val)
|
||||
{
|
||||
uint8_t cnt = 0;
|
||||
uint16_t flip_cover_detector_idx = MSG_FLIP_COVER_DETECTOR;
|
||||
int32_t msg_buf[1];
|
||||
|
||||
msg_buf[0] = val;
|
||||
|
||||
mutex_lock(&data->flip_cover_factory_mutex);
|
||||
|
||||
adsp_unicast(msg_buf, sizeof(msg_buf),
|
||||
flip_cover_detector_idx, 0, MSG_TYPE_OPTION_DEFINE);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_OPTION_DEFINE] & 1 << flip_cover_detector_idx) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(20000, 20000);
|
||||
|
||||
data->ready_flag[MSG_TYPE_OPTION_DEFINE] &= ~(1 << flip_cover_detector_idx);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT)
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
else
|
||||
nfc_cover_status = data->msg_buf[flip_cover_detector_idx][0];
|
||||
|
||||
pr_info("[FACTORY] %s: nfc_cover_status=%d\n", __func__, nfc_cover_status);
|
||||
|
||||
mutex_unlock(&data->flip_cover_factory_mutex);
|
||||
|
||||
if (fcd_dual_cal_matrix)
|
||||
send_flip_cover_status_to_mag_sensor(data, val);
|
||||
|
||||
schedule_delayed_work(&fcd_data->notifier_work, msecs_to_jiffies(0));
|
||||
}
|
||||
|
||||
static void get_mag_cal_data_with_saturation(struct adsp_data *data, int *mag_data)
|
||||
{
|
||||
uint8_t cnt = 0;
|
||||
|
||||
adsp_unicast(NULL, 0, MSG_MAG, 0, MSG_TYPE_GET_CAL_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_CAL_DATA] & 1 << MSG_MAG) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 500);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_CAL_DATA] &= ~(1 << MSG_MAG);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
} else {
|
||||
mag_data[X] = data->msg_buf[MSG_MAG][0];
|
||||
mag_data[Y] = data->msg_buf[MSG_MAG][1];
|
||||
mag_data[Z] = data->msg_buf[MSG_MAG][2];
|
||||
factory_data->saturation = data->msg_buf[MSG_MAG][3];
|
||||
}
|
||||
|
||||
pr_info("[FACTORY] %s: %d, %d, %d, %d\n", __func__,
|
||||
mag_data[0], mag_data[1], mag_data[2], factory_data->saturation);
|
||||
}
|
||||
|
||||
void check_cover_detection_factory(int *mag_data, int axis_select)
|
||||
{
|
||||
int axis = 0;
|
||||
|
||||
if (!strcmp(factory_data->cover_status, DETACH)) {
|
||||
if (mag_data[axis_select] > factory_data->failed_attach_max) {
|
||||
factory_data->failed_attach_max = mag_data[axis_select];
|
||||
|
||||
if (abs(factory_data->failed_attach_max - factory_data->init[axis_select])
|
||||
> abs(factory_data->failed_attach_min - factory_data->init[axis_select])) {
|
||||
for (axis = X; axis < AXIS_MAX; axis++) {
|
||||
factory_data->attach[axis] = mag_data[axis];
|
||||
}
|
||||
}
|
||||
} else if (mag_data[axis_select] < factory_data->failed_attach_min) {
|
||||
factory_data->failed_attach_min = mag_data[axis_select];
|
||||
|
||||
if (abs(factory_data->failed_attach_max - factory_data->init[axis_select])
|
||||
< abs(factory_data->failed_attach_min - factory_data->init[axis_select])) {
|
||||
for (axis = X; axis < AXIS_MAX; axis++) {
|
||||
factory_data->attach[axis] = mag_data[axis];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pr_info("[FACTORY] %s: failed_attach_max=%d, failed_attach_min=%d\n", __func__,
|
||||
factory_data->failed_attach_max, factory_data->failed_attach_min);
|
||||
|
||||
factory_data->attach_diff = mag_data[axis_select] - factory_data->init[axis_select];
|
||||
|
||||
if (abs(factory_data->attach_diff) > factory_data->threshold) {
|
||||
snprintf(factory_data->cover_status, 10, ATTACH);
|
||||
snprintf(factory_data->attach_result, 10, PASS);
|
||||
for (axis = X; axis < AXIS_MAX; axis++) {
|
||||
factory_data->attach[axis] = mag_data[axis];
|
||||
factory_data->attach_extremum[axis] = mag_data[axis];
|
||||
}
|
||||
pr_info("[FACTORY] %s: COVER ATTACHED\n", __func__);
|
||||
}
|
||||
} else {
|
||||
if (factory_data->attach_diff > 0) {
|
||||
if (factory_data->saturation) {
|
||||
for (axis = X; axis < AXIS_MAX; axis++) {
|
||||
mag_data[axis] = SATURATION_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (mag_data[axis_select] > factory_data->attach_extremum[axis_select]) {
|
||||
for (axis = X; axis < AXIS_MAX; axis++) {
|
||||
factory_data->attach_extremum[axis] = mag_data[axis];
|
||||
factory_data->detach[axis] = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (factory_data->saturation) {
|
||||
for (axis = X; axis < AXIS_MAX; axis++) {
|
||||
mag_data[axis] = -SATURATION_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (mag_data[axis_select] < factory_data->attach_extremum[axis_select]) {
|
||||
for (axis = X; axis < AXIS_MAX; axis++) {
|
||||
factory_data->attach_extremum[axis] = mag_data[axis];
|
||||
factory_data->detach[axis] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
factory_data->detach_diff = mag_data[axis_select] - factory_data->attach_extremum[axis_select];
|
||||
|
||||
if (factory_data->attach_diff > 0) {
|
||||
if (mag_data[axis_select] < (factory_data->attach_extremum[axis_select] - DETACH_MARGIN)) {
|
||||
for (axis = X; axis < AXIS_MAX; axis++) {
|
||||
factory_data->detach[axis] = mag_data[axis];
|
||||
}
|
||||
}
|
||||
|
||||
if (factory_data->detach_diff < -factory_data->threshold) {
|
||||
snprintf(factory_data->cover_status, 10, DETACH);
|
||||
snprintf(factory_data->detach_result, 10, PASS);
|
||||
snprintf(factory_data->final_result, 10, PASS);
|
||||
factory_data->factory_test_status = OFF;
|
||||
pr_info("[FACTORY] %s: COVER_DETACHED\n", __func__);
|
||||
}
|
||||
} else {
|
||||
if (mag_data[axis_select] > (factory_data->attach_extremum[axis_select] + DETACH_MARGIN)) {
|
||||
for (axis = X; axis < AXIS_MAX; axis++) {
|
||||
factory_data->detach[axis] = mag_data[axis];
|
||||
}
|
||||
}
|
||||
|
||||
if (factory_data->detach_diff > factory_data->threshold) {
|
||||
snprintf(factory_data->cover_status, 10, DETACH);
|
||||
snprintf(factory_data->detach_result, 10, PASS);
|
||||
snprintf(factory_data->final_result, 10, PASS);
|
||||
factory_data->factory_test_status = OFF;
|
||||
pr_info("[FACTORY] %s: COVER_DETACHED\n", __func__);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pr_info("[FACTORY1] %s: cover_status=%s, axis_select=%d, thd=%d, \
|
||||
x_init=%d, x_attach=%d, x_min_max=%d, x_detach=%d, \
|
||||
y_init=%d, y_attach=%d, y_min_max=%d, y_detach=%d, \
|
||||
z_init=%d, z_attach=%d, z_min_max=%d, z_detach=%d, \
|
||||
attach_result=%s, detach_result=%s, final_result=%s\n",
|
||||
__func__, factory_data->cover_status, factory_data->axis_select, factory_data->threshold,
|
||||
factory_data->init[X], factory_data->attach[X], factory_data->attach_extremum[X], factory_data->detach[X],
|
||||
factory_data->init[Y], factory_data->attach[Y], factory_data->attach_extremum[Y], factory_data->detach[Y],
|
||||
factory_data->init[Z], factory_data->attach[Z], factory_data->attach_extremum[Z], factory_data->detach[Z],
|
||||
factory_data->attach_result, factory_data->detach_result, factory_data->final_result);
|
||||
}
|
||||
|
||||
static void fcd_work_func(struct work_struct *work)
|
||||
{
|
||||
int mag_data[AXIS_MAX];
|
||||
|
||||
if (factory_data->factory_test_status == ON) {
|
||||
get_mag_cal_data_with_saturation(fcd_data->data, mag_data);
|
||||
check_cover_detection_factory(mag_data, factory_data->axis_select);
|
||||
}
|
||||
}
|
||||
|
||||
static enum hrtimer_restart fcd_timer_func(struct hrtimer *timer)
|
||||
{
|
||||
queue_work(fcd_data->fcd_wq, &fcd_data->work_fcd);
|
||||
hrtimer_forward_now(&fcd_data->fcd_timer, fcd_data->poll_delay);
|
||||
|
||||
if (factory_data->factory_test_status == ON)
|
||||
return HRTIMER_RESTART;
|
||||
else
|
||||
return HRTIMER_NORESTART;
|
||||
}
|
||||
|
||||
static void factory_data_init(void)
|
||||
{
|
||||
int mag_data[AXIS_MAX];
|
||||
int axis = 0;
|
||||
|
||||
memset(factory_data, 0, sizeof(struct factory_cover_status_data));
|
||||
|
||||
get_mag_cal_data_with_saturation(fcd_data->data, mag_data);
|
||||
|
||||
factory_data->axis_select = axis_update;
|
||||
factory_data->threshold = (threshold_update > 0) ? threshold_update : threshold_update * (-1);
|
||||
|
||||
for (axis = X; axis < AXIS_MAX; axis++) {
|
||||
factory_data->init[axis] = mag_data[axis];
|
||||
factory_data->attach[axis] = mag_data[axis];
|
||||
}
|
||||
|
||||
factory_data->failed_attach_max = mag_data[factory_data->axis_select];
|
||||
factory_data->failed_attach_min = mag_data[factory_data->axis_select];
|
||||
|
||||
snprintf(factory_data->cover_status, 10, DETACH);
|
||||
snprintf(factory_data->attach_result, 10, FAIL);
|
||||
snprintf(factory_data->detach_result, 10, FAIL);
|
||||
snprintf(factory_data->final_result, 10, FAIL);
|
||||
}
|
||||
|
||||
static void enable_factory_test(int request)
|
||||
{
|
||||
if (request == ON) {
|
||||
factory_data_init();
|
||||
factory_data->factory_test_status = ON;
|
||||
hrtimer_start(&fcd_data->fcd_timer, fcd_data->poll_delay, HRTIMER_MODE_REL);
|
||||
} else {
|
||||
hrtimer_cancel(&fcd_data->fcd_timer);
|
||||
cancel_work_sync(&fcd_data->work_fcd);
|
||||
factory_data->factory_test_status = OFF;
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t nfc_cover_status_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
if (nfc_cover_status == COVER_ATTACH || nfc_cover_status == COVER_ATTACH_NFC_ACTIVE || nfc_cover_status == COVER_ATTACH_NFC_TAG_PRESENT) {
|
||||
snprintf(sysfs_cover_status, 10, "CLOSE");
|
||||
} else if (nfc_cover_status == COVER_DETACH) {
|
||||
snprintf(sysfs_cover_status, 10, "OPEN");
|
||||
}
|
||||
|
||||
pr_info("[FACTORY] %s: sysfs_cover_status=%s\n", __func__, sysfs_cover_status);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", sysfs_cover_status);
|
||||
}
|
||||
|
||||
static ssize_t nfc_cover_status_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
int status = 0;
|
||||
|
||||
if (kstrtoint(buf, 10, &status)) {
|
||||
pr_err("[FACTORY] %s: kstrtoint fail\n", __func__);
|
||||
return size;
|
||||
}
|
||||
|
||||
send_nfc_cover_status(data, status);
|
||||
|
||||
pr_info("[FACTORY] %s: status=%d\n", __func__, status);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t factory_cover_status_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
pr_info("[FACTORY] %s: status=%s, axis=%d, thd=%d, \
|
||||
x_init=%d, x_attach=%d, x_min_max=%d, x_detach=%d, \
|
||||
y_init=%d, y_attach=%d, y_min_max=%d, y_detach=%d, \
|
||||
z_init=%d, z_attach=%d, z_min_max=%d, z_detach=%d, \
|
||||
attach_result=%s, detach_result=%s, final_result=%s\n",
|
||||
__func__, factory_data->cover_status, factory_data->axis_select, factory_data->threshold,
|
||||
factory_data->init[X], factory_data->attach[X], factory_data->attach_extremum[X], factory_data->detach[X],
|
||||
factory_data->init[Y], factory_data->attach[Y], factory_data->attach_extremum[Y], factory_data->detach[Y],
|
||||
factory_data->init[Z], factory_data->attach[Z], factory_data->attach_extremum[Z], factory_data->detach[Z],
|
||||
factory_data->attach_result, factory_data->detach_result, factory_data->final_result);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%s,%s,%s\n",
|
||||
factory_data->cover_status, factory_data->axis_select, factory_data->threshold,
|
||||
factory_data->init[X], factory_data->attach[X], factory_data->attach_extremum[X], factory_data->detach[X],
|
||||
factory_data->init[Y], factory_data->attach[Y], factory_data->attach_extremum[Y], factory_data->detach[Y],
|
||||
factory_data->init[Z], factory_data->attach[Z], factory_data->attach_extremum[Z], factory_data->detach[Z],
|
||||
factory_data->attach_result, factory_data->detach_result, factory_data->final_result);
|
||||
}
|
||||
|
||||
static ssize_t factory_cover_status_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
int factory_test_request = -1;
|
||||
|
||||
fcd_data->data = data;
|
||||
|
||||
if (kstrtoint(buf, 10, &factory_test_request)) {
|
||||
pr_err("[FACTORY] %s: kstrtoint fail\n", __func__);
|
||||
return size;
|
||||
}
|
||||
|
||||
pr_info("[FACTORY] %s: factory_test_request=%d\n", __func__, factory_test_request);
|
||||
|
||||
if (factory_test_request == ON && factory_data->factory_test_status == OFF)
|
||||
enable_factory_test(ON);
|
||||
else if (factory_test_request == OFF && factory_data->factory_test_status == ON)
|
||||
enable_factory_test(OFF);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t axis_threshold_setting_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
pr_info("[FACTORY] %s: axis=%d, threshold=%d\n", __func__, axis_update, threshold_update);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d,%d\n", axis_update, threshold_update);
|
||||
}
|
||||
|
||||
static ssize_t axis_threshold_setting_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
int axis, threshold;
|
||||
|
||||
ret = sscanf(buf, "%d,%d", &axis, &threshold);
|
||||
|
||||
if (ret != 2) {
|
||||
pr_err("[FACTORY] %s: Invalid values received, ret=%d\n", __func__, ret);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (axis < 0 || axis >= AXIS_MAX) {
|
||||
pr_err("[FACTORY] %s: Invalid axis value received\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pr_info("[FACTORY] %s: axis=%d, threshold=%d\n", __func__, axis, threshold);
|
||||
|
||||
send_axis_threshold_settings(data, axis, threshold);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t mag_cal_matrix_num_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
uint8_t cnt = 0;
|
||||
int cal_matrix_num;
|
||||
|
||||
adsp_unicast(NULL, 0, MSG_MAG, 0, MSG_TYPE_GET_THRESHOLD);
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_THRESHOLD] & 1 << MSG_MAG) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_THRESHOLD] &= ~(1 << MSG_MAG);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
cal_matrix_num = -1;
|
||||
} else {
|
||||
pr_info("[FACTORY] %s cal_matix_num = %d\n", __func__, data->msg_buf[MSG_MAG][0]);
|
||||
cal_matrix_num = data->msg_buf[MSG_MAG][0];
|
||||
}
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", cal_matrix_num);
|
||||
}
|
||||
|
||||
void flip_cover_detector_cal_init_work(void)
|
||||
{
|
||||
if (fcd_dual_cal_matrix && nfc_cover_status > 0) {
|
||||
int32_t msg_buf[1];
|
||||
|
||||
msg_buf[0] = nfc_cover_status;
|
||||
adsp_unicast(msg_buf, sizeof(msg_buf), MSG_MAG, 0, MSG_TYPE_SET_TEMPORARY_MSG);
|
||||
pr_info("[FACTORY] %s: nfc_cover_status=%d set in mag sensor after factory init\n",
|
||||
__func__, msg_buf[0]);
|
||||
}
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(nfc_cover_status, 0664, nfc_cover_status_show, nfc_cover_status_store);
|
||||
static DEVICE_ATTR(factory_cover_status, 0664, factory_cover_status_show, factory_cover_status_store);
|
||||
static DEVICE_ATTR(axis_threshold_setting, 0664, axis_threshold_setting_show, axis_threshold_setting_store);
|
||||
static DEVICE_ATTR(cal_matrix_num, 0444, mag_cal_matrix_num_show, NULL);
|
||||
|
||||
static struct device_attribute *flip_cover_detector_attrs[] = {
|
||||
&dev_attr_nfc_cover_status,
|
||||
&dev_attr_factory_cover_status,
|
||||
&dev_attr_axis_threshold_setting,
|
||||
&dev_attr_cal_matrix_num,
|
||||
NULL,
|
||||
};
|
||||
|
||||
void check_device_default_thd(struct device_node *np)
|
||||
{
|
||||
int ret = of_property_read_u32(np, "fcd,attach_thd", &threshold_update);
|
||||
if (ret < 0) {
|
||||
pr_info("[FACTORY] %s: attach_thd not found, ret=%d\n", __func__, ret);
|
||||
threshold_update = THRESHOLD;
|
||||
}
|
||||
pr_info("[FACTORY] %s: %d\n", __func__, threshold_update);
|
||||
}
|
||||
|
||||
void check_device_axis_update(struct device_node *np)
|
||||
{
|
||||
int ret = of_property_read_u32(np, "fcd,axis", &axis_update);
|
||||
if (ret < 0) {
|
||||
pr_info("[FACTORY] %s: fcd,axis not found, ret=%d\n", __func__, ret);
|
||||
axis_update = AXIS_SELECT;
|
||||
}
|
||||
|
||||
pr_info("[FACTORY] %s: %d\n", __func__, axis_update);
|
||||
}
|
||||
|
||||
void check_fcd_dual_cal_matrix_support(struct device_node *np)
|
||||
{
|
||||
int ret = of_property_read_u32(np, "fcd,dual_cal_matrix", &fcd_dual_cal_matrix);
|
||||
if (ret < 0) {
|
||||
pr_info("[FACTORY] %s: fcd,dual_cal_matrix not found, ret=%d\n", __func__, ret);
|
||||
fcd_dual_cal_matrix = 0;
|
||||
}
|
||||
|
||||
pr_info("[FACTORY] %s: %d\n", __func__, fcd_dual_cal_matrix);
|
||||
}
|
||||
|
||||
static bool check_flip_cover_detector_availability(void)
|
||||
{
|
||||
struct device_node *np = of_find_node_by_name(NULL, "flip_cover_detector_sensor");
|
||||
|
||||
if (np == NULL) {
|
||||
pr_info("[FACTORY] %s: false\n", __func__);
|
||||
fcd_available = false;
|
||||
} else {
|
||||
pr_info("[FACTORY] %s: true\n", __func__);
|
||||
fcd_available = true;
|
||||
|
||||
check_fcd_dual_cal_matrix_support(np);
|
||||
check_device_default_thd(np);
|
||||
check_device_axis_update(np);
|
||||
}
|
||||
|
||||
return fcd_available;
|
||||
}
|
||||
|
||||
int flip_cover_detector_factory_init(void)
|
||||
{
|
||||
fcd_available = check_flip_cover_detector_availability();
|
||||
|
||||
if (!fcd_available)
|
||||
return 0;
|
||||
|
||||
adsp_factory_register(MSG_FLIP_COVER_DETECTOR, flip_cover_detector_attrs);
|
||||
|
||||
fcd_data = kzalloc(sizeof(*fcd_data), GFP_KERNEL);
|
||||
if (fcd_data == NULL) {
|
||||
pr_err("[FACTORY] %s: Memory allocation failed for fcd_data\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
factory_data = kzalloc(sizeof(*factory_data), GFP_KERNEL);
|
||||
if (factory_data == NULL) {
|
||||
pr_err("[FACTORY] %s: Memory allocation failed for factory_data\n", __func__);
|
||||
kfree(fcd_data);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
hrtimer_init(&fcd_data->fcd_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||
fcd_data->fcd_timer.function = fcd_timer_func;
|
||||
|
||||
fcd_data->fcd_wq = create_singlethread_workqueue("flip_cover_detector_wq");
|
||||
if (fcd_data->fcd_wq == NULL) {
|
||||
pr_err("[FACTORY] %s: could not create flip cover detector wq\n", __func__);
|
||||
kfree(fcd_data);
|
||||
kfree(factory_data);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
INIT_WORK(&fcd_data->work_fcd, fcd_work_func);
|
||||
fcd_data->poll_delay = ns_to_ktime(MAG_DELAY_MS * NSEC_PER_MSEC);
|
||||
|
||||
INIT_DELAYED_WORK(&fcd_data->notifier_work, notify_fcd_status);
|
||||
|
||||
snprintf(sysfs_cover_status, 10, "OPEN");
|
||||
|
||||
pr_info("[FACTORY] %s\n", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void flip_cover_detector_factory_exit(void)
|
||||
{
|
||||
if (!fcd_available)
|
||||
return;
|
||||
|
||||
cancel_delayed_work(&fcd_data->notifier_work);
|
||||
|
||||
adsp_factory_unregister(MSG_FLIP_COVER_DETECTOR);
|
||||
|
||||
if (fcd_data != NULL) {
|
||||
if (factory_data->factory_test_status == ON)
|
||||
enable_factory_test(OFF);
|
||||
|
||||
if (fcd_data->fcd_wq != NULL) {
|
||||
destroy_workqueue(fcd_data->fcd_wq);
|
||||
fcd_data->fcd_wq = NULL;
|
||||
}
|
||||
|
||||
kfree(fcd_data);
|
||||
kfree(factory_data);
|
||||
}
|
||||
|
||||
pr_info("[FACTORY] %s\n", __func__);
|
||||
}
|
1809
drivers/adsp_factory/light_factory.c
Executable file
1809
drivers/adsp_factory/light_factory.c
Executable file
File diff suppressed because it is too large
Load Diff
326
drivers/adsp_factory/lps22hh_pressure.c
Executable file
326
drivers/adsp_factory/lps22hh_pressure.c
Executable file
@@ -0,0 +1,326 @@
|
||||
/*
|
||||
* 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"
|
||||
#define VENDOR "STM"
|
||||
#if IS_ENABLED(CONFIG_LPS22DF_FACTORY)
|
||||
#define CHIP_ID "LPS22DF"
|
||||
#else
|
||||
#define CHIP_ID "LPS22HH"
|
||||
#endif
|
||||
|
||||
#define CALIBRATION_FILE_PATH "/efs/FactoryApp/baro_delta"
|
||||
|
||||
#define PR_MAX 8388607 /* 24 bit 2'compl */
|
||||
#define PR_MIN -8388608
|
||||
#define SNS_SUCCESS 0
|
||||
#define ST_PASS 1
|
||||
#define ST_FAIL 0
|
||||
|
||||
static int sea_level_pressure;
|
||||
static int pressure_cal;
|
||||
|
||||
static ssize_t pressure_vendor_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", VENDOR);
|
||||
}
|
||||
|
||||
static ssize_t pressure_name_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", CHIP_ID);
|
||||
}
|
||||
|
||||
static ssize_t sea_level_pressure_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", sea_level_pressure);
|
||||
}
|
||||
|
||||
static ssize_t sea_level_pressure_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
if (sscanf(buf, "%10d", &sea_level_pressure) != 1) {
|
||||
pr_err("[FACTORY] %s: sscanf error\n", __func__);
|
||||
return size;
|
||||
}
|
||||
|
||||
sea_level_pressure = sea_level_pressure / 100;
|
||||
|
||||
pr_info("[FACTORY] %s: sea_level_pressure = %d\n", __func__,
|
||||
sea_level_pressure);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/*
|
||||
int pressure_open_calibration(struct adsp_data *data)
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
return error;
|
||||
}
|
||||
*/
|
||||
|
||||
static ssize_t pressure_cabratioin_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
|
||||
schedule_delayed_work(&data->pressure_cal_work, 0);
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t pressure_cabratioin_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
//struct adsp_data *data = dev_get_drvdata(dev);
|
||||
|
||||
//pressure_open_calibration(data);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", pressure_cal);
|
||||
}
|
||||
|
||||
static ssize_t temperature_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
uint8_t cnt = 0;
|
||||
|
||||
adsp_unicast(NULL, 0, MSG_PRESSURE_TEMP, 0, MSG_TYPE_GET_RAW_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_RAW_DATA] &
|
||||
1 << MSG_PRESSURE_TEMP) && cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_RAW_DATA] &= ~(1 << MSG_PRESSURE_TEMP);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
return snprintf(buf, PAGE_SIZE, "-99\n");
|
||||
}
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||
data->msg_buf[MSG_PRESSURE_TEMP][0]);
|
||||
}
|
||||
|
||||
static ssize_t selftest_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
uint8_t cnt = 0;
|
||||
|
||||
adsp_unicast(NULL, 0, MSG_PRESSURE, 0, MSG_TYPE_ST_SHOW_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_ST_SHOW_DATA] &
|
||||
1 << MSG_PRESSURE) && cnt++ < TIMEOUT_CNT)
|
||||
msleep(26);
|
||||
|
||||
data->ready_flag[MSG_TYPE_ST_SHOW_DATA] &= ~(1 << MSG_PRESSURE);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
return snprintf(buf, PAGE_SIZE, "0\n");
|
||||
}
|
||||
|
||||
pr_info("[FACTORY] %s : P:%d, T:%d, RES:%d\n",
|
||||
__func__, data->msg_buf[MSG_PRESSURE][0],
|
||||
data->msg_buf[MSG_PRESSURE][1], data->msg_buf[MSG_PRESSURE][2]);
|
||||
|
||||
if (SNS_SUCCESS == data->msg_buf[MSG_PRESSURE][2])
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", ST_PASS);
|
||||
else
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", ST_FAIL);
|
||||
}
|
||||
|
||||
static ssize_t pressure_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;
|
||||
int i = 0;
|
||||
|
||||
adsp_unicast(NULL, 0, MSG_PRESSURE, 0, MSG_TYPE_GET_DHR_INFO);
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_DHR_INFO] & 1 << MSG_PRESSURE) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_DHR_INFO] &= ~(1 << MSG_PRESSURE);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
} else {
|
||||
for (i = 0; i < 8; i++) {
|
||||
pr_info("[FACTORY] %s - %02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x\n",
|
||||
__func__,
|
||||
data->msg_buf[MSG_PRESSURE][i * 16 + 0],
|
||||
data->msg_buf[MSG_PRESSURE][i * 16 + 1],
|
||||
data->msg_buf[MSG_PRESSURE][i * 16 + 2],
|
||||
data->msg_buf[MSG_PRESSURE][i * 16 + 3],
|
||||
data->msg_buf[MSG_PRESSURE][i * 16 + 4],
|
||||
data->msg_buf[MSG_PRESSURE][i * 16 + 5],
|
||||
data->msg_buf[MSG_PRESSURE][i * 16 + 6],
|
||||
data->msg_buf[MSG_PRESSURE][i * 16 + 7],
|
||||
data->msg_buf[MSG_PRESSURE][i * 16 + 8],
|
||||
data->msg_buf[MSG_PRESSURE][i * 16 + 9],
|
||||
data->msg_buf[MSG_PRESSURE][i * 16 + 10],
|
||||
data->msg_buf[MSG_PRESSURE][i * 16 + 11],
|
||||
data->msg_buf[MSG_PRESSURE][i * 16 + 12],
|
||||
data->msg_buf[MSG_PRESSURE][i * 16 + 13],
|
||||
data->msg_buf[MSG_PRESSURE][i * 16 + 14],
|
||||
data->msg_buf[MSG_PRESSURE][i * 16 + 15]);
|
||||
}
|
||||
}
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", "Done");
|
||||
}
|
||||
|
||||
static ssize_t pressure_sw_offset_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;
|
||||
int input = 0;
|
||||
int sw_offset = 0;
|
||||
int ret;
|
||||
|
||||
ret = kstrtoint(buf, 10, &input);
|
||||
if (ret < 0) {
|
||||
pr_err("[FACTORY] %s: kstrtoint fail\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pr_info("[FACTORY] %s: write value = %d\n", __func__, input);
|
||||
|
||||
adsp_unicast(&input, sizeof(int),
|
||||
MSG_PRESSURE, 0, MSG_TYPE_SET_THRESHOLD);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_SET_THRESHOLD] & 1 << MSG_PRESSURE) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_SET_THRESHOLD] &= ~(1 << MSG_PRESSURE);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
} else {
|
||||
sw_offset = data->msg_buf[MSG_PRESSURE][0];
|
||||
}
|
||||
|
||||
pr_info("[FACTORY] %s: sw_offset %d\n", __func__, sw_offset);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t pressure_sw_offset_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
uint8_t cnt = 0;
|
||||
|
||||
adsp_unicast(NULL, 0, MSG_PRESSURE, 0, MSG_TYPE_GET_THRESHOLD);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_THRESHOLD] &
|
||||
1 << MSG_PRESSURE) && cnt++ < TIMEOUT_CNT)
|
||||
msleep(20);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_THRESHOLD] &= ~(1 << MSG_PRESSURE);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
return snprintf(buf, PAGE_SIZE, "0\n");
|
||||
}
|
||||
|
||||
pr_info("[FACTORY] %s : sw_offset %d\n",
|
||||
__func__, data->msg_buf[MSG_PRESSURE][0]);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", data->msg_buf[MSG_PRESSURE][0]);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(vendor, 0444, pressure_vendor_show, NULL);
|
||||
static DEVICE_ATTR(name, 0444, pressure_name_show, NULL);
|
||||
static DEVICE_ATTR(calibration, 0664,
|
||||
pressure_cabratioin_show, pressure_cabratioin_store);
|
||||
static DEVICE_ATTR(sea_level_pressure, 0664,
|
||||
sea_level_pressure_show, sea_level_pressure_store);
|
||||
static DEVICE_ATTR(temperature, 0444, temperature_show, NULL);
|
||||
static DEVICE_ATTR(selftest, 0444, selftest_show, NULL);
|
||||
#ifdef CONFIG_SEC_FACTORY
|
||||
static DEVICE_ATTR(dhr_sensor_info, 0444,
|
||||
pressure_dhr_sensor_info_show, NULL);
|
||||
#else
|
||||
static DEVICE_ATTR(dhr_sensor_info, 0440,
|
||||
pressure_dhr_sensor_info_show, NULL);
|
||||
#endif
|
||||
static DEVICE_ATTR(sw_offset, 0664,
|
||||
pressure_sw_offset_show, pressure_sw_offset_store);
|
||||
|
||||
static struct device_attribute *pressure_attrs[] = {
|
||||
&dev_attr_vendor,
|
||||
&dev_attr_name,
|
||||
&dev_attr_calibration,
|
||||
&dev_attr_sea_level_pressure,
|
||||
&dev_attr_temperature,
|
||||
&dev_attr_selftest,
|
||||
&dev_attr_dhr_sensor_info,
|
||||
&dev_attr_sw_offset,
|
||||
NULL,
|
||||
};
|
||||
|
||||
void pressure_cal_work_func(struct work_struct *work)
|
||||
{
|
||||
struct adsp_data *data = container_of((struct delayed_work *)work,
|
||||
struct adsp_data, pressure_cal_work);
|
||||
int cnt = 0;
|
||||
int temp = 0;
|
||||
|
||||
adsp_unicast(&temp, sizeof(temp), MSG_PRESSURE, 0, MSG_TYPE_SET_CAL_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_SET_CAL_DATA] & 1 << MSG_PRESSURE) &&
|
||||
cnt++ < 3)
|
||||
msleep(30);
|
||||
|
||||
data->ready_flag[MSG_TYPE_SET_CAL_DATA] &= ~(1 << MSG_PRESSURE);
|
||||
|
||||
if (cnt >= 3) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
pressure_cal = data->msg_buf[MSG_PRESSURE][0];
|
||||
pr_info("[FACTORY] %s: pressure_cal = %d (lsb)\n", __func__, data->msg_buf[MSG_PRESSURE][0]);
|
||||
}
|
||||
EXPORT_SYMBOL(pressure_cal_work_func);
|
||||
void pressure_factory_init_work(struct adsp_data *data)
|
||||
{
|
||||
schedule_delayed_work(&data->pressure_cal_work, msecs_to_jiffies(8000));
|
||||
}
|
||||
EXPORT_SYMBOL(pressure_factory_init_work);
|
||||
|
||||
int __init lps22hh_pressure_factory_init(void)
|
||||
{
|
||||
adsp_factory_register(MSG_PRESSURE, pressure_attrs);
|
||||
|
||||
pr_info("[FACTORY] %s\n", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
void __exit lps22hh_pressure_factory_exit(void)
|
||||
{
|
||||
adsp_factory_unregister(MSG_PRESSURE);
|
||||
|
||||
pr_info("[FACTORY] %s\n", __func__);
|
||||
}
|
191
drivers/adsp_factory/lsm6dsl_gyro.c
Executable file
191
drivers/adsp_factory/lsm6dsl_gyro.c
Executable file
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* 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"
|
||||
#define VENDOR "STM"
|
||||
#define CHIP_ID "LSM6DSL"
|
||||
#define ST_PASS 1
|
||||
#define ST_FAIL 0
|
||||
#define ST_ZRO_MIN (-40)
|
||||
#define ST_ZRO_MAX 40
|
||||
#define SELFTEST_REVISED 1
|
||||
|
||||
static ssize_t gyro_vendor_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", VENDOR);
|
||||
}
|
||||
|
||||
static ssize_t gyro_name_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", CHIP_ID);
|
||||
}
|
||||
|
||||
static ssize_t selftest_revised_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", SELFTEST_REVISED);
|
||||
}
|
||||
|
||||
static ssize_t gyro_power_off(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
pr_info("[FACTORY]: %s\n", __func__);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", 1);
|
||||
}
|
||||
|
||||
static ssize_t gyro_power_on(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
pr_info("[FACTORY]: %s\n", __func__);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", 1);
|
||||
}
|
||||
|
||||
static ssize_t gyro_temp_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
uint8_t cnt = 0;
|
||||
|
||||
adsp_unicast(NULL, 0, MSG_GYRO_TEMP, 0, MSG_TYPE_GET_RAW_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_RAW_DATA] & 1 << MSG_GYRO_TEMP)
|
||||
&& cnt++ < TIMEOUT_CNT)
|
||||
msleep(20);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_RAW_DATA] &= ~(1 << MSG_GYRO_TEMP);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
return snprintf(buf, PAGE_SIZE, "-99\n");
|
||||
}
|
||||
|
||||
pr_info("[FACTORY] %s: gyro_temp = %d\n", __func__,
|
||||
data->msg_buf[MSG_GYRO_TEMP][0]);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||
data->msg_buf[MSG_GYRO_TEMP][0]);
|
||||
}
|
||||
|
||||
static ssize_t gyro_selftest_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
uint8_t cnt = 0;
|
||||
int st_diff_res = ST_FAIL;
|
||||
int st_zro_res = ST_FAIL;
|
||||
|
||||
pr_info("[FACTORY] %s - start", __func__);
|
||||
adsp_unicast(NULL, 0, MSG_GYRO, 0, MSG_TYPE_ST_SHOW_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_ST_SHOW_DATA] & 1 << MSG_GYRO) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
msleep(25);
|
||||
|
||||
data->ready_flag[MSG_TYPE_ST_SHOW_DATA] &= ~(1 << MSG_GYRO);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
return snprintf(buf, PAGE_SIZE,
|
||||
"0,0,0,0,0,0,0,0,0,0,0,0,%d,%d\n",
|
||||
ST_FAIL, ST_FAIL);
|
||||
}
|
||||
|
||||
if (data->msg_buf[MSG_GYRO][1] != 0) {
|
||||
pr_info("[FACTORY] %s - failed(%d, %d)\n", __func__,
|
||||
data->msg_buf[MSG_GYRO][1],
|
||||
data->msg_buf[MSG_GYRO][5]);
|
||||
|
||||
pr_info("[FACTORY]: %s - %d,%d,%d\n", __func__,
|
||||
data->msg_buf[MSG_GYRO][2],
|
||||
data->msg_buf[MSG_GYRO][3],
|
||||
data->msg_buf[MSG_GYRO][4]);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d,%d,%d\n",
|
||||
data->msg_buf[MSG_GYRO][2],
|
||||
data->msg_buf[MSG_GYRO][3],
|
||||
data->msg_buf[MSG_GYRO][4]);
|
||||
}
|
||||
|
||||
if (!data->msg_buf[MSG_GYRO][5])
|
||||
st_diff_res = ST_PASS;
|
||||
|
||||
if((ST_ZRO_MIN <= data->msg_buf[MSG_GYRO][6])
|
||||
&& (data->msg_buf[MSG_GYRO][6] <= ST_ZRO_MAX)
|
||||
&& (ST_ZRO_MIN <= data->msg_buf[MSG_GYRO][7])
|
||||
&& (data->msg_buf[MSG_GYRO][7] <= ST_ZRO_MAX)
|
||||
&& (ST_ZRO_MIN <= data->msg_buf[MSG_GYRO][8])
|
||||
&& (data->msg_buf[MSG_GYRO][8]<= ST_ZRO_MAX))
|
||||
st_zro_res = ST_PASS;
|
||||
|
||||
pr_info("[FACTORY]: %s - %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
|
||||
__func__,
|
||||
data->msg_buf[MSG_GYRO][2], data->msg_buf[MSG_GYRO][3],
|
||||
data->msg_buf[MSG_GYRO][4], data->msg_buf[MSG_GYRO][6],
|
||||
data->msg_buf[MSG_GYRO][7], data->msg_buf[MSG_GYRO][8],
|
||||
data->msg_buf[MSG_GYRO][9], data->msg_buf[MSG_GYRO][10],
|
||||
data->msg_buf[MSG_GYRO][11], data->msg_buf[MSG_GYRO][12],
|
||||
data->msg_buf[MSG_GYRO][13], data->msg_buf[MSG_GYRO][14],
|
||||
st_diff_res, st_zro_res);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE,
|
||||
"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
|
||||
data->msg_buf[MSG_GYRO][2], data->msg_buf[MSG_GYRO][3],
|
||||
data->msg_buf[MSG_GYRO][4], data->msg_buf[MSG_GYRO][6],
|
||||
data->msg_buf[MSG_GYRO][7], data->msg_buf[MSG_GYRO][8],
|
||||
data->msg_buf[MSG_GYRO][9], data->msg_buf[MSG_GYRO][10],
|
||||
data->msg_buf[MSG_GYRO][11], data->msg_buf[MSG_GYRO][12],
|
||||
data->msg_buf[MSG_GYRO][13], data->msg_buf[MSG_GYRO][14],
|
||||
st_diff_res, st_zro_res);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(name, 0444, gyro_name_show, NULL);
|
||||
static DEVICE_ATTR(vendor, 0444, gyro_vendor_show, NULL);
|
||||
static DEVICE_ATTR(selftest, 0440, gyro_selftest_show, NULL);
|
||||
static DEVICE_ATTR(power_on, 0444, gyro_power_on, NULL);
|
||||
static DEVICE_ATTR(power_off, 0444, gyro_power_off, NULL);
|
||||
static DEVICE_ATTR(temperature, 0440, gyro_temp_show, NULL);
|
||||
static DEVICE_ATTR(selftest_revised, 0440, selftest_revised_show, NULL);
|
||||
|
||||
static struct device_attribute *gyro_attrs[] = {
|
||||
&dev_attr_name,
|
||||
&dev_attr_vendor,
|
||||
&dev_attr_selftest,
|
||||
&dev_attr_power_on,
|
||||
&dev_attr_power_off,
|
||||
&dev_attr_temperature,
|
||||
&dev_attr_selftest_revised,
|
||||
NULL,
|
||||
};
|
||||
|
||||
int __init lsm6dsl_gyro_factory_init(void)
|
||||
{
|
||||
adsp_factory_register(MSG_GYRO, gyro_attrs);
|
||||
|
||||
pr_info("[FACTORY] %s\n", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __exit lsm6dsl_gyro_factory_exit(void)
|
||||
{
|
||||
adsp_factory_unregister(MSG_GYRO);
|
||||
|
||||
pr_info("[FACTORY] %s\n", __func__);
|
||||
}
|
868
drivers/adsp_factory/lsm6dso_accel.c
Executable file
868
drivers/adsp_factory/lsm6dso_accel.c
Executable file
@@ -0,0 +1,868 @@
|
||||
/*
|
||||
* 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 STM_LSM6DSV_INT_CHECK_SKIP_IBI 5
|
||||
|
||||
#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;
|
||||
atomic_t vib_state;
|
||||
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;
|
||||
|
||||
if (data->msg_buf[MSG_ACCEL][0] == STM_LSM6DSV_INT_CHECK_SKIP_IBI) {
|
||||
pr_info("[FACTORY]: %s - IBI mode. Ignore Interrupt Check Test\n", __func__);
|
||||
success = true;
|
||||
}
|
||||
|
||||
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 if (data->msg_buf[MSG_ACCEL][0] == STM_LSM6DSV_INT_CHECK_SKIP_IBI)
|
||||
pr_info("[FACTORY]: %s - IBI mode. Ignore Interrupt Check Test\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;
|
||||
}
|
||||
|
||||
void vib_onoff(int onoff)
|
||||
{
|
||||
int32_t msg_buf = MOTOR_OFF;
|
||||
if (atomic_read(&pdata->vib_state) == MOTOR_ON)
|
||||
msg_buf = MOTOR_ON;
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
static ssize_t vib_onoff_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int vib_onoff = (int)atomic_read(&pdata->vib_state);
|
||||
pr_info("[FACTORY] %s: %d\n", __func__, vib_onoff);
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", vib_onoff);
|
||||
}
|
||||
|
||||
static ssize_t vib_onoff_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
int32_t enable = -1;
|
||||
|
||||
if (sysfs_streq(buf, "1"))
|
||||
enable = 1;
|
||||
else
|
||||
enable = 0;
|
||||
|
||||
if (enable == 1) {
|
||||
if (atomic_read(&pdata->vib_state) == MOTOR_OFF) {
|
||||
atomic_set(&pdata->vib_state, MOTOR_ON);
|
||||
vib_onoff(MOTOR_ON);
|
||||
} else {
|
||||
pr_info("[FACTORY] %s: Current vib_state is MOTOR_ON\n", __func__);
|
||||
}
|
||||
} else {
|
||||
atomic_set(&pdata->vib_state, MOTOR_OFF);
|
||||
vib_onoff(MOTOR_OFF);
|
||||
}
|
||||
pr_info("[FACTORY] %s: %d\n", __func__, enable);
|
||||
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 DEVICE_ATTR(vib_onoff, 0664,
|
||||
vib_onoff_show, vib_onoff_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,
|
||||
&dev_attr_vib_onoff,
|
||||
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;
|
||||
atomic_set(&pdata->vib_state, MOTOR_OFF);
|
||||
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__);
|
||||
}
|
263
drivers/adsp_factory/lsm6dso_gyro.c
Executable file
263
drivers/adsp_factory/lsm6dso_gyro.c
Executable file
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
* 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"
|
||||
#define VENDOR "STM"
|
||||
#if IS_ENABLED(CONFIG_LSM6DSV_FACTORY)
|
||||
#define CHIP_ID "LSM6DSV"
|
||||
#else
|
||||
#define CHIP_ID "LSM6DSO"
|
||||
#endif
|
||||
#define ST_PASS 1
|
||||
#define ST_FAIL 0
|
||||
#define STARTUP_BIT_FAIL 2
|
||||
#define OIS_ST_BIT_SET 3
|
||||
#define G_ZRL_DELTA_FAIL 4
|
||||
#define OIS_RW_FAIL 5
|
||||
#define SFLP_FAIL 6
|
||||
#define SELFTEST_REVISED 1
|
||||
|
||||
static ssize_t gyro_vendor_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", VENDOR);
|
||||
}
|
||||
|
||||
static ssize_t gyro_name_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", CHIP_ID);
|
||||
}
|
||||
|
||||
static ssize_t selftest_revised_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", SELFTEST_REVISED);
|
||||
}
|
||||
|
||||
static ssize_t gyro_power_off(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
pr_info("[FACTORY]: %s\n", __func__);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", 1);
|
||||
}
|
||||
|
||||
static ssize_t gyro_power_on(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
pr_info("[FACTORY]: %s\n", __func__);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", 1);
|
||||
}
|
||||
|
||||
static ssize_t gyro_temp_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
uint8_t cnt = 0;
|
||||
|
||||
adsp_unicast(NULL, 0, MSG_GYRO_TEMP, 0, MSG_TYPE_GET_RAW_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_RAW_DATA] & 1 << MSG_GYRO_TEMP)
|
||||
&& cnt++ < TIMEOUT_CNT)
|
||||
msleep(20);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_RAW_DATA] &= ~(1 << MSG_GYRO_TEMP);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
return snprintf(buf, PAGE_SIZE, "-99\n");
|
||||
}
|
||||
|
||||
pr_info("[FACTORY] %s: gyro_temp = %d\n", __func__,
|
||||
data->msg_buf[MSG_GYRO_TEMP][0]);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||
data->msg_buf[MSG_GYRO_TEMP][0]);
|
||||
}
|
||||
|
||||
static ssize_t gyro_selftest_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
uint8_t cnt = 0;
|
||||
int st_diff_res = ST_FAIL;
|
||||
int st_zro_res = ST_FAIL;
|
||||
#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
|
||||
|
||||
pr_info("[FACTORY] %s - start\n", __func__);
|
||||
adsp_unicast(NULL, 0, MSG_GYRO, 0, MSG_TYPE_ST_SHOW_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_ST_SHOW_DATA] & 1 << MSG_GYRO) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(30000, 30100); /* 30 * 200 = 6 sec */
|
||||
|
||||
data->ready_flag[MSG_TYPE_ST_SHOW_DATA] &= ~(1 << MSG_GYRO);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
#ifdef CONFIG_SEC_FACTORY
|
||||
panic("sensor force crash : gyro selftest timeout\n");
|
||||
#endif
|
||||
#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,
|
||||
"0,0,0,0,0,0,0,0,0,0,0,0,%d,%d\n",
|
||||
ST_FAIL, ST_FAIL);
|
||||
}
|
||||
|
||||
if (data->msg_buf[MSG_GYRO][1] != 0) {
|
||||
pr_info("[FACTORY] %s - failed(%d, %d)\n", __func__,
|
||||
data->msg_buf[MSG_GYRO][1],
|
||||
data->msg_buf[MSG_GYRO][5]);
|
||||
|
||||
pr_info("[FACTORY]: %s - %d,%d,%d\n", __func__,
|
||||
data->msg_buf[MSG_GYRO][2],
|
||||
data->msg_buf[MSG_GYRO][3],
|
||||
data->msg_buf[MSG_GYRO][4]);
|
||||
|
||||
if (data->msg_buf[MSG_GYRO][5] == OIS_ST_BIT_SET)
|
||||
pr_info("[FACTORY] %s - OIS_ST_BIT fail\n", __func__);
|
||||
else if (data->msg_buf[MSG_GYRO][5] == G_ZRL_DELTA_FAIL)
|
||||
pr_info("[FACTORY] %s - ZRL Delta fail\n", __func__);
|
||||
else if (data->msg_buf[MSG_GYRO][5] == OIS_RW_FAIL)
|
||||
pr_info("[FACTORY] %s - Gyro OIS read write fail\n", __func__);
|
||||
|
||||
#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\n",
|
||||
data->msg_buf[MSG_GYRO][2],
|
||||
data->msg_buf[MSG_GYRO][3],
|
||||
data->msg_buf[MSG_GYRO][4]);
|
||||
} else {
|
||||
st_zro_res = ST_PASS;
|
||||
}
|
||||
|
||||
if (!data->msg_buf[MSG_GYRO][5])
|
||||
st_diff_res = ST_PASS;
|
||||
else if (data->msg_buf[MSG_GYRO][5] == STARTUP_BIT_FAIL)
|
||||
pr_info("[FACTORY] %s - Gyro Start Up Bit fail\n", __func__);
|
||||
else if (data->msg_buf[MSG_GYRO][5] == OIS_RW_FAIL) {
|
||||
pr_info("[FACTORY] %s - Gyro OIS read write fail\n", __func__);
|
||||
st_diff_res = OIS_RW_FAIL;
|
||||
}
|
||||
else if (data->msg_buf[MSG_GYRO][5] == SFLP_FAIL) {
|
||||
pr_info("[FACTORY] %s - SFLP sanity test fail\n", __func__);
|
||||
st_diff_res = SFLP_FAIL;
|
||||
}
|
||||
|
||||
pr_info("[FACTORY] %s - %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
|
||||
__func__,
|
||||
data->msg_buf[MSG_GYRO][2], data->msg_buf[MSG_GYRO][3],
|
||||
data->msg_buf[MSG_GYRO][4], data->msg_buf[MSG_GYRO][6],
|
||||
data->msg_buf[MSG_GYRO][7], data->msg_buf[MSG_GYRO][8],
|
||||
data->msg_buf[MSG_GYRO][9], data->msg_buf[MSG_GYRO][10],
|
||||
data->msg_buf[MSG_GYRO][11], data->msg_buf[MSG_GYRO][12],
|
||||
data->msg_buf[MSG_GYRO][13], data->msg_buf[MSG_GYRO][14],
|
||||
st_diff_res, st_zro_res);
|
||||
|
||||
#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,%d,%d,%d,%d,%d,%d,%d\n",
|
||||
data->msg_buf[MSG_GYRO][2], data->msg_buf[MSG_GYRO][3],
|
||||
data->msg_buf[MSG_GYRO][4], data->msg_buf[MSG_GYRO][6],
|
||||
data->msg_buf[MSG_GYRO][7], data->msg_buf[MSG_GYRO][8],
|
||||
data->msg_buf[MSG_GYRO][9], data->msg_buf[MSG_GYRO][10],
|
||||
data->msg_buf[MSG_GYRO][11], data->msg_buf[MSG_GYRO][12],
|
||||
data->msg_buf[MSG_GYRO][13], data->msg_buf[MSG_GYRO][14],
|
||||
st_diff_res, st_zro_res);
|
||||
}
|
||||
|
||||
static ssize_t trimmed_odr_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
uint8_t cnt = 0;
|
||||
|
||||
adsp_unicast(NULL, 0, MSG_GYRO, 0, MSG_TYPE_GET_REGISTER);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_REGISTER] & 1 << MSG_GYRO)
|
||||
&& cnt++ < TIMEOUT_CNT)
|
||||
msleep(20);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_REGISTER] &= ~(1 << MSG_GYRO);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
return snprintf(buf, PAGE_SIZE, "0\n");
|
||||
}
|
||||
|
||||
pr_info("[FACTORY] %s: 0x63h = 0x%02x, trimmed_odr = %d Hz\n", __func__,
|
||||
data->msg_buf[MSG_GYRO][0], data->msg_buf[MSG_GYRO][1]);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||
data->msg_buf[MSG_GYRO][1]);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(name, 0444, gyro_name_show, NULL);
|
||||
static DEVICE_ATTR(vendor, 0444, gyro_vendor_show, NULL);
|
||||
static DEVICE_ATTR(selftest, 0440, gyro_selftest_show, NULL);
|
||||
static DEVICE_ATTR(power_on, 0444, gyro_power_on, NULL);
|
||||
static DEVICE_ATTR(power_off, 0444, gyro_power_off, NULL);
|
||||
static DEVICE_ATTR(temperature, 0440, gyro_temp_show, NULL);
|
||||
static DEVICE_ATTR(selftest_revised, 0440, selftest_revised_show, NULL);
|
||||
static DEVICE_ATTR(trimmed_odr, 0440, trimmed_odr_show, NULL);
|
||||
|
||||
static struct device_attribute *gyro_attrs[] = {
|
||||
&dev_attr_name,
|
||||
&dev_attr_vendor,
|
||||
&dev_attr_selftest,
|
||||
&dev_attr_power_on,
|
||||
&dev_attr_power_off,
|
||||
&dev_attr_temperature,
|
||||
&dev_attr_selftest_revised,
|
||||
&dev_attr_trimmed_odr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
int __init lsm6dso_gyro_factory_init(void)
|
||||
{
|
||||
adsp_factory_register(MSG_GYRO, gyro_attrs);
|
||||
|
||||
pr_info("[FACTORY] %s\n", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __exit lsm6dso_gyro_factory_exit(void)
|
||||
{
|
||||
adsp_factory_unregister(MSG_GYRO);
|
||||
|
||||
pr_info("[FACTORY] %s\n", __func__);
|
||||
}
|
694
drivers/adsp_factory/lsm6dso_sub_accel.c
Executable file
694
drivers/adsp_factory/lsm6dso_sub_accel.c
Executable file
@@ -0,0 +1,694 @@
|
||||
/*
|
||||
* 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"
|
||||
#define VENDOR "STM"
|
||||
#if IS_ENABLED(CONFIG_LSM6DSV_FACTORY)
|
||||
#define CHIP_ID "LSM6DSVW"
|
||||
#else
|
||||
#define CHIP_ID "LSM6DSOW"
|
||||
#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 PASS 0
|
||||
|
||||
#define STM_LSM6DSO_INT_CHECK_RUNNING 4
|
||||
#define STM_LSM6DSV_INT_CHECK_SKIP_IBI 5
|
||||
|
||||
struct sub_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 sub_accel_data *pdata;
|
||||
|
||||
static ssize_t sub_accel_vendor_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", VENDOR);
|
||||
}
|
||||
|
||||
static ssize_t sub_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_sub_accel_cal_data(struct adsp_data *data, int32_t *cal_data)
|
||||
{
|
||||
uint8_t cnt = 0;
|
||||
|
||||
adsp_unicast(NULL, 0, MSG_ACCEL_SUB, 0, MSG_TYPE_GET_CAL_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_CAL_DATA] & 1 << MSG_ACCEL_SUB) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_CAL_DATA] &= ~(1 << MSG_ACCEL_SUB);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (data->msg_buf[MSG_ACCEL_SUB][3] != ACCEL_RAW_DATA_CNT) {
|
||||
pr_err("[FACTORY] %s: Reading Bytes Num %d!!!\n",
|
||||
__func__, data->msg_buf[MSG_ACCEL_SUB][3]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cal_data[0] = data->msg_buf[MSG_ACCEL_SUB][0];
|
||||
cal_data[1] = data->msg_buf[MSG_ACCEL_SUB][1];
|
||||
cal_data[2] = data->msg_buf[MSG_ACCEL_SUB][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_SUB][3]);
|
||||
|
||||
return data->msg_buf[MSG_ACCEL_SUB][3];
|
||||
}
|
||||
|
||||
void set_sub_accel_cal_data(struct adsp_data *data)
|
||||
{
|
||||
uint8_t cnt = 0;
|
||||
|
||||
pr_info("[FACTORY] %s(1): %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_SUB, 0, MSG_TYPE_SET_CAL_DATA);
|
||||
pr_info("[FACTORY] %s(2): %d, %d, %d\n", __func__, pdata->avg_data[0],
|
||||
pdata->avg_data[1], pdata->avg_data[2]);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_SET_CAL_DATA] & 1 << MSG_ACCEL_SUB) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_SET_CAL_DATA] &= ~(1 << MSG_ACCEL_SUB);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
} else if (data->msg_buf[MSG_ACCEL_SUB][0] != ACCEL_RAW_DATA_CNT) {
|
||||
pr_err("[FACTORY] %s: Write Bytes Num %d!!!\n",
|
||||
__func__, data->msg_buf[MSG_ACCEL_SUB][0]);
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t sub_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_sub_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_sub_accel_cal_data fail\n", __func__);
|
||||
return snprintf(buf, PAGE_SIZE, "%d,%d,%d,%d\n", 0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t sub_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_sub_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_sub_accel_cal_data(data);
|
||||
mutex_unlock(&data->accel_factory_mutex);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static void sub_accel_work_func(struct work_struct *work)
|
||||
{
|
||||
struct sub_accel_data *data = container_of((struct work_struct *)work,
|
||||
struct sub_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_SUB, 0, MSG_TYPE_SET_CAL_DATA);
|
||||
msleep(30); /* for init of bias */
|
||||
for (i = 0; i < ACCEL_FACTORY_CAL_CNT; i++) {
|
||||
msleep(20);
|
||||
get_sub_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 sub_accel_cal_work_func(struct work_struct *work)
|
||||
{
|
||||
struct adsp_data *data = container_of((struct delayed_work *)work,
|
||||
struct adsp_data, sub_accel_cal_work);
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&data->accel_factory_mutex);
|
||||
ret = get_sub_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_sub_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 sub_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_SUB, 0, MSG_TYPE_ST_SHOW_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_ST_SHOW_DATA] & 1 << MSG_ACCEL_SUB) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
msleep(26);
|
||||
|
||||
data->ready_flag[MSG_TYPE_ST_SHOW_DATA] &= ~(1 << MSG_ACCEL_SUB);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
data->msg_buf[MSG_ACCEL_SUB][1] = -1;
|
||||
#ifdef CONFIG_SEC_FACTORY
|
||||
panic("sensor force crash : sub 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_SUB][0],
|
||||
data->msg_buf[MSG_ACCEL_SUB][1], data->msg_buf[MSG_ACCEL_SUB][2],
|
||||
data->msg_buf[MSG_ACCEL_SUB][3], data->msg_buf[MSG_ACCEL_SUB][4],
|
||||
data->msg_buf[MSG_ACCEL_SUB][5], data->msg_buf[MSG_ACCEL_SUB][6],
|
||||
data->msg_buf[MSG_ACCEL_SUB][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_SUB][8],
|
||||
data->msg_buf[MSG_ACCEL_SUB][9], data->msg_buf[MSG_ACCEL_SUB][10],
|
||||
data->msg_buf[MSG_ACCEL_SUB][11], data->msg_buf[MSG_ACCEL_SUB][12],
|
||||
data->msg_buf[MSG_ACCEL_SUB][13], data->msg_buf[MSG_ACCEL_SUB][14],
|
||||
data->msg_buf[MSG_ACCEL_SUB][15], data->msg_buf[MSG_ACCEL_SUB][16],
|
||||
data->msg_buf[MSG_ACCEL_SUB][17], data->msg_buf[MSG_ACCEL_SUB][18],
|
||||
data->msg_buf[MSG_ACCEL_SUB][19]);
|
||||
|
||||
if (data->msg_buf[MSG_ACCEL_SUB][1] == 1) {
|
||||
pr_info("[FACTORY] %s : Pass - result = %d, retry = %d\n",
|
||||
__func__, data->msg_buf[MSG_ACCEL_SUB][1], retry);
|
||||
} else {
|
||||
data->msg_buf[MSG_ACCEL_SUB][1] = -5;
|
||||
pr_err("[FACTORY] %s : Fail - result = %d, retry = %d\n",
|
||||
__func__, data->msg_buf[MSG_ACCEL_SUB][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_SUB][1],
|
||||
(int)abs(data->msg_buf[MSG_ACCEL_SUB][2]),
|
||||
(int)abs(data->msg_buf[MSG_ACCEL_SUB][3]),
|
||||
(int)abs(data->msg_buf[MSG_ACCEL_SUB][4]),
|
||||
(int)abs(data->msg_buf[MSG_ACCEL_SUB][5]),
|
||||
(int)abs(data->msg_buf[MSG_ACCEL_SUB][6]),
|
||||
(int)abs(data->msg_buf[MSG_ACCEL_SUB][7]));
|
||||
}
|
||||
|
||||
static ssize_t sub_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;
|
||||
#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_sub_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 : sub 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 sub_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_SUB,
|
||||
0, MSG_TYPE_GET_REGISTER);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_REGISTER] & 1 << MSG_ACCEL_SUB) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_REGISTER] &= ~(1 << MSG_ACCEL_SUB);
|
||||
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_SUB][0]);
|
||||
|
||||
if (data->msg_buf[MSG_ACCEL_SUB][0] == 0)
|
||||
success = true;
|
||||
|
||||
if (data->msg_buf[MSG_ACCEL_SUB][0] == STM_LSM6DSV_INT_CHECK_SKIP_IBI) {
|
||||
pr_info("[FACTORY]: %s - IBI mode. Ignore Interrupt Check Test\n", __func__);
|
||||
success = true;
|
||||
}
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", (int)success);
|
||||
}
|
||||
|
||||
static ssize_t sub_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_SUB,
|
||||
0, MSG_TYPE_GET_REGISTER);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_REGISTER] & 1 << MSG_ACCEL_SUB) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_REGISTER] &= ~(1 << MSG_ACCEL_SUB);
|
||||
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_SUB][0] == STM_LSM6DSO_INT_CHECK_RUNNING)
|
||||
pr_info("[FACTORY]: %s - STM_LSM6DSO_INT_CHECK_RUNNING\n", __func__);
|
||||
else if (data->msg_buf[MSG_ACCEL_SUB][0] == STM_LSM6DSV_INT_CHECK_SKIP_IBI)
|
||||
pr_info("[FACTORY]: %s - IBI mode. Ignore Interrupt Check Test\n", __func__);
|
||||
else
|
||||
pr_info("[FACTORY]: %s - Something wrong\n", __func__);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t sub_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;
|
||||
} else if (sysfs_streq(buf, "0")) {
|
||||
msg_buf = 0;
|
||||
#ifdef CONFIG_SEC_FACTORY
|
||||
} else if (sysfs_streq(buf, "2")) {
|
||||
msg_buf = 2;
|
||||
pr_info("[FACTORY] %s: Pretest\n", __func__);
|
||||
#endif
|
||||
} else {
|
||||
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_SUB,
|
||||
0, MSG_TYPE_SET_ACCEL_LPF);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_SET_ACCEL_LPF] & 1 << MSG_ACCEL_SUB) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_SET_ACCEL_LPF] &= ~(1 << MSG_ACCEL_SUB);
|
||||
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_SUB][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_SUB][0], data->msg_buf[MSG_ACCEL_SUB][1],
|
||||
data->msg_buf[MSG_ACCEL_SUB][2], data->msg_buf[MSG_ACCEL_SUB][3]);
|
||||
#else
|
||||
pr_info("[FACTORY] %s: %d, 0x0A:%02x 0x0D:%02x 0x10:%02x\n", __func__,
|
||||
data->msg_buf[MSG_ACCEL_SUB][0], data->msg_buf[MSG_ACCEL_SUB][1],
|
||||
data->msg_buf[MSG_ACCEL_SUB][2], data->msg_buf[MSG_ACCEL_SUB][3]);
|
||||
#endif
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t sub_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_SUB, 0, MSG_TYPE_GET_DHR_INFO);
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_DHR_INFO] & 1 << MSG_ACCEL_SUB) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_DHR_INFO] &= ~(1 << MSG_ACCEL_SUB);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT)
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
|
||||
ctrl1_xl = data->msg_buf[MSG_ACCEL_SUB][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);
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_REF_ANGLE_WITHOUT_DIGITAL_HALL) || defined(CONFIG_SUPPORT_REF_ANGLE_WITHOUT_DIGITAL_HALL)
|
||||
static ssize_t ref_angle_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
uint8_t cnt = 0;
|
||||
int32_t result = PASS;
|
||||
|
||||
mutex_lock(&data->accel_factory_mutex);
|
||||
adsp_unicast(NULL, 0, MSG_REF_ANGLE, 0, MSG_TYPE_GET_RAW_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_RAW_DATA] & 1 << MSG_REF_ANGLE) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
msleep(20);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_RAW_DATA] &= ~(1 << MSG_REF_ANGLE);
|
||||
mutex_unlock(&data->accel_factory_mutex);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
return snprintf(buf, PAGE_SIZE, "-1\n");
|
||||
}
|
||||
|
||||
pr_info("[FACTORY] %s - st %d/%d, akm %d/%d, lf %d/%d, hall %d/%d/%d(uT)\n",
|
||||
__func__, data->msg_buf[MSG_REF_ANGLE][0],
|
||||
data->msg_buf[MSG_REF_ANGLE][1],
|
||||
data->msg_buf[MSG_REF_ANGLE][2],
|
||||
data->msg_buf[MSG_REF_ANGLE][3],
|
||||
data->msg_buf[MSG_REF_ANGLE][4],
|
||||
data->msg_buf[MSG_REF_ANGLE][5],
|
||||
data->msg_buf[MSG_REF_ANGLE][6],
|
||||
data->msg_buf[MSG_REF_ANGLE][7],
|
||||
data->msg_buf[MSG_REF_ANGLE][8]);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d,%d\n",
|
||||
data->msg_buf[MSG_REF_ANGLE][0], result);
|
||||
}
|
||||
|
||||
static ssize_t angle_read_data_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
uint8_t cnt = 0;
|
||||
|
||||
mutex_lock(&data->accel_factory_mutex);
|
||||
adsp_unicast(NULL, 0, MSG_REF_ANGLE, 0, MSG_TYPE_GET_RAW_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_RAW_DATA] & 1 << MSG_REF_ANGLE) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
msleep(20);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_RAW_DATA] &= ~(1 << MSG_REF_ANGLE);
|
||||
mutex_unlock(&data->accel_factory_mutex);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
return snprintf(buf, PAGE_SIZE, "-1\n");
|
||||
}
|
||||
|
||||
pr_info("[FACTORY] %s - st %d/%d, akm %d/%d, lf %d/%d, hall %d/%d/%d(uT)\n",
|
||||
__func__, data->msg_buf[MSG_REF_ANGLE][0],
|
||||
data->msg_buf[MSG_REF_ANGLE][1],
|
||||
data->msg_buf[MSG_REF_ANGLE][2],
|
||||
data->msg_buf[MSG_REF_ANGLE][3],
|
||||
data->msg_buf[MSG_REF_ANGLE][4],
|
||||
data->msg_buf[MSG_REF_ANGLE][5],
|
||||
data->msg_buf[MSG_REF_ANGLE][6],
|
||||
data->msg_buf[MSG_REF_ANGLE][7],
|
||||
data->msg_buf[MSG_REF_ANGLE][8]);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
|
||||
data->msg_buf[MSG_REF_ANGLE][0],
|
||||
data->msg_buf[MSG_REF_ANGLE][1],
|
||||
data->msg_buf[MSG_REF_ANGLE][2],
|
||||
data->msg_buf[MSG_REF_ANGLE][3],
|
||||
data->msg_buf[MSG_REF_ANGLE][4],
|
||||
data->msg_buf[MSG_REF_ANGLE][5],
|
||||
data->msg_buf[MSG_REF_ANGLE][6],
|
||||
data->msg_buf[MSG_REF_ANGLE][7],
|
||||
data->msg_buf[MSG_REF_ANGLE][8]);
|
||||
}
|
||||
#endif
|
||||
|
||||
static DEVICE_ATTR(name, 0444, sub_accel_name_show, NULL);
|
||||
static DEVICE_ATTR(vendor, 0444, sub_accel_vendor_show, NULL);
|
||||
static DEVICE_ATTR(type, 0444, sensor_type_show, NULL);
|
||||
static DEVICE_ATTR(calibration, 0664,
|
||||
sub_accel_calibration_show, sub_accel_calibration_store);
|
||||
static DEVICE_ATTR(selftest, 0440,
|
||||
sub_accel_selftest_show, NULL);
|
||||
static DEVICE_ATTR(raw_data, 0444, sub_accel_raw_data_show, NULL);
|
||||
static DEVICE_ATTR(reactive_alert, 0664,
|
||||
sub_accel_reactive_show, sub_accel_reactive_store);
|
||||
static DEVICE_ATTR(lowpassfilter, 0220,
|
||||
NULL, sub_accel_lowpassfilter_store);
|
||||
#ifdef CONFIG_SEC_FACTORY
|
||||
static DEVICE_ATTR(dhr_sensor_info, 0444,
|
||||
sub_accel_dhr_sensor_info_show, NULL);
|
||||
#else
|
||||
static DEVICE_ATTR(dhr_sensor_info, 0440,
|
||||
sub_accel_dhr_sensor_info_show, NULL);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_REF_ANGLE_WITHOUT_DIGITAL_HALL) || defined(CONFIG_SUPPORT_REF_ANGLE_WITHOUT_DIGITAL_HALL)
|
||||
static DEVICE_ATTR(ref_angle, 0444, ref_angle_show, NULL);
|
||||
static DEVICE_ATTR(read_angle_data, 0444, angle_read_data_show, NULL);
|
||||
#endif
|
||||
|
||||
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,
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_REF_ANGLE_WITHOUT_DIGITAL_HALL) || defined(CONFIG_SUPPORT_REF_ANGLE_WITHOUT_DIGITAL_HALL)
|
||||
&dev_attr_ref_angle,
|
||||
&dev_attr_read_angle_data,
|
||||
#endif
|
||||
NULL,
|
||||
};
|
||||
|
||||
void sub_accel_factory_init_work(struct adsp_data *data)
|
||||
{
|
||||
schedule_delayed_work(&data->sub_accel_cal_work, msecs_to_jiffies(8000));
|
||||
}
|
||||
|
||||
int __init lsm6dso_sub_accel_factory_init(void)
|
||||
{
|
||||
adsp_factory_register(MSG_ACCEL_SUB, acc_attrs);
|
||||
|
||||
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
|
||||
pdata->accel_wq = create_singlethread_workqueue("sub_accel_wq");
|
||||
INIT_WORK(&pdata->work_accel, sub_accel_work_func);
|
||||
|
||||
pdata->lpf_onoff = true;
|
||||
pdata->st_complete = true;
|
||||
pr_info("[FACTORY] %s\n", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __exit lsm6dso_sub_accel_factory_exit(void)
|
||||
{
|
||||
adsp_factory_unregister(MSG_ACCEL_SUB);
|
||||
pr_info("[FACTORY] %s\n", __func__);
|
||||
}
|
226
drivers/adsp_factory/lsm6dso_sub_gyro.c
Executable file
226
drivers/adsp_factory/lsm6dso_sub_gyro.c
Executable file
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
* 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"
|
||||
#define VENDOR "STM"
|
||||
#if IS_ENABLED(CONFIG_LSM6DSV_FACTORY)
|
||||
#define CHIP_ID "LSM6DSVW"
|
||||
#else
|
||||
#define CHIP_ID "LSM6DSOW"
|
||||
#endif
|
||||
#define ST_PASS 1
|
||||
#define ST_FAIL 0
|
||||
#define STARTUP_BIT_FAIL 2
|
||||
#define G_ZRL_DELTA_FAIL 4
|
||||
#define SFLP_FAIL 6
|
||||
#define SELFTEST_REVISED 1
|
||||
|
||||
static ssize_t sub_gyro_vendor_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", VENDOR);
|
||||
}
|
||||
|
||||
static ssize_t sub_gyro_name_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", CHIP_ID);
|
||||
}
|
||||
|
||||
static ssize_t selftest_revised_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", SELFTEST_REVISED);
|
||||
}
|
||||
|
||||
static ssize_t gyro_power_off(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
pr_info("[FACTORY]: %s\n", __func__);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", 1);
|
||||
}
|
||||
|
||||
static ssize_t gyro_power_on(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
pr_info("[FACTORY]: %s\n", __func__);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", 1);
|
||||
}
|
||||
|
||||
static ssize_t sub_gyro_temp_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
uint8_t cnt = 0;
|
||||
|
||||
adsp_unicast(NULL, 0, MSG_GYRO_SUB_TEMP, 0, MSG_TYPE_GET_RAW_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_RAW_DATA] & 1 << MSG_GYRO_SUB_TEMP)
|
||||
&& cnt++ < TIMEOUT_CNT)
|
||||
msleep(20);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_RAW_DATA] &= ~(1 << MSG_GYRO_SUB_TEMP);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
return snprintf(buf, PAGE_SIZE, "-99\n");
|
||||
}
|
||||
|
||||
pr_info("[FACTORY] %s: sub_gyro_temp = %d\n", __func__,
|
||||
data->msg_buf[MSG_GYRO_SUB_TEMP][0]);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||
data->msg_buf[MSG_GYRO_SUB_TEMP][0]);
|
||||
}
|
||||
|
||||
static ssize_t sub_gyro_selftest_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
uint8_t cnt = 0;
|
||||
int st_diff_res = ST_FAIL;
|
||||
int st_zro_res = ST_FAIL;
|
||||
#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
|
||||
|
||||
pr_info("[FACTORY] %s - start", __func__);
|
||||
adsp_unicast(NULL, 0, MSG_GYRO_SUB, 0, MSG_TYPE_ST_SHOW_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_ST_SHOW_DATA] & 1 << MSG_GYRO_SUB) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(30000, 30100); /* 30 * 200 = 6 sec */
|
||||
|
||||
data->ready_flag[MSG_TYPE_ST_SHOW_DATA] &= ~(1 << MSG_GYRO_SUB);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
#ifdef CONFIG_SEC_FACTORY
|
||||
panic("sensor force crash : sub gyro selftest timeout\n");
|
||||
#endif
|
||||
#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,
|
||||
"0,0,0,0,0,0,0,0,0,0,0,0,%d,%d\n",
|
||||
ST_FAIL, ST_FAIL);
|
||||
}
|
||||
|
||||
if (data->msg_buf[MSG_GYRO_SUB][1] != 0) {
|
||||
pr_info("[FACTORY] %s - failed(%d, %d)\n", __func__,
|
||||
data->msg_buf[MSG_GYRO_SUB][1],
|
||||
data->msg_buf[MSG_GYRO_SUB][5]);
|
||||
|
||||
pr_info("[FACTORY]: %s - %d,%d,%d\n", __func__,
|
||||
data->msg_buf[MSG_GYRO_SUB][2],
|
||||
data->msg_buf[MSG_GYRO_SUB][3],
|
||||
data->msg_buf[MSG_GYRO_SUB][4]);
|
||||
|
||||
#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
|
||||
|
||||
if (data->msg_buf[MSG_GYRO_SUB][5] == G_ZRL_DELTA_FAIL)
|
||||
pr_info("[FACTORY] %s - ZRL Delta fail\n", __func__);
|
||||
return snprintf(buf, PAGE_SIZE, "%d,%d,%d\n",
|
||||
data->msg_buf[MSG_GYRO_SUB][2],
|
||||
data->msg_buf[MSG_GYRO_SUB][3],
|
||||
data->msg_buf[MSG_GYRO_SUB][4]);
|
||||
} else {
|
||||
st_zro_res = ST_PASS;
|
||||
}
|
||||
|
||||
if (!data->msg_buf[MSG_GYRO_SUB][5])
|
||||
st_diff_res = ST_PASS;
|
||||
else if (data->msg_buf[MSG_GYRO_SUB][5] == STARTUP_BIT_FAIL)
|
||||
pr_info("[FACTORY] %s - Gyro Start Up Bit fail\n", __func__);
|
||||
else if (data->msg_buf[MSG_GYRO_SUB][5] == SFLP_FAIL) {
|
||||
pr_info("[FACTORY] %s - SFLP sanity test fail\n", __func__);
|
||||
st_diff_res = SFLP_FAIL;
|
||||
}
|
||||
|
||||
pr_info("[FACTORY]: %s - %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
|
||||
__func__,
|
||||
data->msg_buf[MSG_GYRO_SUB][2], data->msg_buf[MSG_GYRO_SUB][3],
|
||||
data->msg_buf[MSG_GYRO_SUB][4], data->msg_buf[MSG_GYRO_SUB][6],
|
||||
data->msg_buf[MSG_GYRO_SUB][7], data->msg_buf[MSG_GYRO_SUB][8],
|
||||
data->msg_buf[MSG_GYRO_SUB][9], data->msg_buf[MSG_GYRO_SUB][10],
|
||||
data->msg_buf[MSG_GYRO_SUB][11], data->msg_buf[MSG_GYRO_SUB][12],
|
||||
data->msg_buf[MSG_GYRO_SUB][13], data->msg_buf[MSG_GYRO_SUB][14],
|
||||
st_diff_res, st_zro_res);
|
||||
|
||||
#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,%d,%d,%d,%d,%d,%d,%d\n",
|
||||
data->msg_buf[MSG_GYRO_SUB][2], data->msg_buf[MSG_GYRO_SUB][3],
|
||||
data->msg_buf[MSG_GYRO_SUB][4], data->msg_buf[MSG_GYRO_SUB][6],
|
||||
data->msg_buf[MSG_GYRO_SUB][7], data->msg_buf[MSG_GYRO_SUB][8],
|
||||
data->msg_buf[MSG_GYRO_SUB][9], data->msg_buf[MSG_GYRO_SUB][10],
|
||||
data->msg_buf[MSG_GYRO_SUB][11], data->msg_buf[MSG_GYRO_SUB][12],
|
||||
data->msg_buf[MSG_GYRO_SUB][13], data->msg_buf[MSG_GYRO_SUB][14],
|
||||
st_diff_res, st_zro_res);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(name, 0444, sub_gyro_name_show, NULL);
|
||||
static DEVICE_ATTR(vendor, 0444, sub_gyro_vendor_show, NULL);
|
||||
static DEVICE_ATTR(selftest, 0440, sub_gyro_selftest_show, NULL);
|
||||
static DEVICE_ATTR(power_on, 0444, gyro_power_on, NULL);
|
||||
static DEVICE_ATTR(power_off, 0444, gyro_power_off, NULL);
|
||||
static DEVICE_ATTR(temperature, 0440, sub_gyro_temp_show, NULL);
|
||||
static DEVICE_ATTR(selftest_revised, 0440, selftest_revised_show, NULL);
|
||||
|
||||
static struct device_attribute *gyro_attrs[] = {
|
||||
&dev_attr_name,
|
||||
&dev_attr_vendor,
|
||||
&dev_attr_selftest,
|
||||
&dev_attr_power_on,
|
||||
&dev_attr_power_off,
|
||||
&dev_attr_temperature,
|
||||
&dev_attr_selftest_revised,
|
||||
NULL,
|
||||
};
|
||||
|
||||
int __init lsm6dso_sub_gyro_factory_init(void)
|
||||
{
|
||||
adsp_factory_register(MSG_GYRO_SUB, gyro_attrs);
|
||||
|
||||
pr_info("[FACTORY] %s\n", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __exit lsm6dso_sub_gyro_factory_exit(void)
|
||||
{
|
||||
adsp_factory_unregister(MSG_GYRO_SUB);
|
||||
|
||||
pr_info("[FACTORY] %s\n", __func__);
|
||||
}
|
256
drivers/adsp_factory/mag_sub_factory.c
Executable file
256
drivers/adsp_factory/mag_sub_factory.c
Executable file
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
* 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"
|
||||
#define VENDOR "AKM"
|
||||
#define CHIP_ID "AK09918"
|
||||
|
||||
#define MAG_ST_TRY_CNT 3
|
||||
#define ABS(x) (((x)>0)?(x):-(x))
|
||||
#define AKM_ST_FAIL (-1)
|
||||
|
||||
static ssize_t sub_mag_vendor_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", VENDOR);
|
||||
}
|
||||
|
||||
static ssize_t sub_mag_name_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", CHIP_ID);
|
||||
}
|
||||
|
||||
static ssize_t sub_mag_check_cntl(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "OK\n");
|
||||
}
|
||||
|
||||
static ssize_t sub_mag_check_registers(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE,
|
||||
"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
static ssize_t sub_mag_get_asa(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
/* Do not have Fuserom */
|
||||
return snprintf(buf, PAGE_SIZE, "%u,%u,%u\n", 128, 128, 128);
|
||||
}
|
||||
|
||||
static ssize_t sub_mag_get_status(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
/* Do not have Fuserom */
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", "OK");
|
||||
}
|
||||
|
||||
static ssize_t sub_mag_raw_data_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
uint8_t cnt = 0;
|
||||
|
||||
adsp_unicast(NULL, 0, MSG_MAG_SUB, 0, MSG_TYPE_GET_RAW_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_RAW_DATA] & 1 << MSG_MAG_SUB) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_RAW_DATA] &= ~(1 << MSG_MAG_SUB);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
return snprintf(buf, PAGE_SIZE, "0,0,0\n");
|
||||
}
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d,%d,%d\n",
|
||||
data->msg_buf[MSG_MAG_SUB][0],
|
||||
data->msg_buf[MSG_MAG_SUB][1],
|
||||
data->msg_buf[MSG_MAG_SUB][2]);
|
||||
}
|
||||
|
||||
static ssize_t sub_mag_raw_data_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
adsp_unicast(NULL, 0, MSG_MAG_CAL_SUB, 0, MSG_TYPE_FACTORY_ENABLE);
|
||||
msleep(20);
|
||||
adsp_unicast(NULL, 0, MSG_MAG_CAL_SUB, 0, MSG_TYPE_SET_CAL_DATA);
|
||||
msleep(20);
|
||||
adsp_unicast(NULL, 0, MSG_MAG_CAL_SUB, 0, MSG_TYPE_FACTORY_DISABLE);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t sub_mag_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, i;
|
||||
int abs_adc_sum = 0, abs_adc_x = 0, abs_adc_y = 0, abs_adc_z = 0;
|
||||
int st_status = 0;
|
||||
|
||||
RETRY_MAG_SELFTEST:
|
||||
pr_info("[FACTORY] %s - start\n", __func__);
|
||||
adsp_unicast(NULL, 0, MSG_MAG_SUB, 0, MSG_TYPE_ST_SHOW_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_ST_SHOW_DATA] & 1 << MSG_MAG_SUB) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
msleep(26);
|
||||
|
||||
data->ready_flag[MSG_TYPE_ST_SHOW_DATA] &= ~(1 << MSG_MAG_SUB);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
data->msg_buf[MSG_MAG_SUB][0] = -1;
|
||||
#ifdef CONFIG_SEC_FACTORY
|
||||
panic("force crash : sensor selftest timeout\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!(data->msg_buf[MSG_MAG_SUB][0] == 0)) {
|
||||
if (retry < MAG_ST_TRY_CNT) {
|
||||
retry++;
|
||||
for (i = 0; i < 10; i++)
|
||||
data->msg_buf[MSG_MAG_SUB][i] = 0;
|
||||
|
||||
msleep(100);
|
||||
cnt = 0;
|
||||
pr_info("[FACTORY] %s - retry %d\n", __func__, retry);
|
||||
goto RETRY_MAG_SELFTEST;
|
||||
}
|
||||
|
||||
adsp_unicast(NULL, 0, MSG_MAG_CAL_SUB, 0, MSG_TYPE_FACTORY_ENABLE);
|
||||
msleep(20);
|
||||
adsp_unicast(NULL, 0, MSG_MAG_CAL_SUB, 0, MSG_TYPE_SET_CAL_DATA);
|
||||
msleep(20);
|
||||
adsp_unicast(NULL, 0, MSG_MAG_CAL_SUB, 0, MSG_TYPE_FACTORY_DISABLE);
|
||||
return snprintf(buf, PAGE_SIZE, "-1,0,0,0,0,0,0,0,0,0\n");
|
||||
}
|
||||
|
||||
if (data->msg_buf[MSG_MAG_SUB][1] != 0) {
|
||||
pr_info("[FACTORY] %s - msg_buf[1] 0x%x\n", __func__, data->msg_buf[MSG_MAG_SUB][1]);
|
||||
st_status = AKM_ST_FAIL;
|
||||
}
|
||||
pr_info("[FACTORY] status=%d, st_status=%d, st_xyz=%d,%d,%d, dac=%d, adc=%d, adc_xyz=%d,%d,%d\n",
|
||||
data->msg_buf[MSG_MAG_SUB][0], st_status,
|
||||
data->msg_buf[MSG_MAG_SUB][2], data->msg_buf[MSG_MAG_SUB][3],
|
||||
data->msg_buf[MSG_MAG_SUB][4], data->msg_buf[MSG_MAG_SUB][5],
|
||||
data->msg_buf[MSG_MAG_SUB][6], data->msg_buf[MSG_MAG_SUB][7],
|
||||
data->msg_buf[MSG_MAG_SUB][8], data->msg_buf[MSG_MAG_SUB][9]);
|
||||
|
||||
abs_adc_x = ABS(data->msg_buf[MSG_MAG_SUB][7]);
|
||||
abs_adc_y = ABS(data->msg_buf[MSG_MAG_SUB][8]);
|
||||
abs_adc_z = ABS(data->msg_buf[MSG_MAG_SUB][9]);
|
||||
abs_adc_sum = abs_adc_x + abs_adc_y + abs_adc_z;
|
||||
|
||||
if (abs_adc_sum >= 26666) {
|
||||
pr_info("[FACTORY] abs_adc_sum is higher then 40Gauss\n");
|
||||
st_status = AKM_ST_FAIL;
|
||||
}
|
||||
|
||||
adsp_unicast(NULL, 0, MSG_MAG_CAL_SUB, 0, MSG_TYPE_FACTORY_ENABLE);
|
||||
msleep(20);
|
||||
adsp_unicast(NULL, 0, MSG_MAG_CAL_SUB, 0, MSG_TYPE_SET_CAL_DATA);
|
||||
msleep(20);
|
||||
adsp_unicast(NULL, 0, MSG_MAG_CAL_SUB, 0, MSG_TYPE_FACTORY_DISABLE);
|
||||
return snprintf(buf, PAGE_SIZE, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
|
||||
data->msg_buf[MSG_MAG_SUB][0], st_status,
|
||||
data->msg_buf[MSG_MAG_SUB][2], data->msg_buf[MSG_MAG_SUB][3],
|
||||
data->msg_buf[MSG_MAG_SUB][4], data->msg_buf[MSG_MAG_SUB][5],
|
||||
data->msg_buf[MSG_MAG_SUB][6], data->msg_buf[MSG_MAG_SUB][7],
|
||||
data->msg_buf[MSG_MAG_SUB][8], data->msg_buf[MSG_MAG_SUB][9]);
|
||||
}
|
||||
|
||||
static ssize_t sub_mag_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;
|
||||
|
||||
adsp_unicast(NULL, 0, MSG_MAG_SUB, 0, MSG_TYPE_GET_DHR_INFO);
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_DHR_INFO] & 1 << MSG_MAG_SUB) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_DHR_INFO] &= ~(1 << MSG_MAG_SUB);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
} else {
|
||||
pr_info("[FACTORY] %s - [00h-03h] %02x,%02x,%02x,%02x [10h-16h,18h] %02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x [30h-32h] %02x,%02x,%02x\n",
|
||||
__func__,
|
||||
data->msg_buf[MSG_MAG_SUB][0], data->msg_buf[MSG_MAG_SUB][1],
|
||||
data->msg_buf[MSG_MAG_SUB][2], data->msg_buf[MSG_MAG_SUB][3],
|
||||
data->msg_buf[MSG_MAG_SUB][4], data->msg_buf[MSG_MAG_SUB][5],
|
||||
data->msg_buf[MSG_MAG_SUB][6], data->msg_buf[MSG_MAG_SUB][7],
|
||||
data->msg_buf[MSG_MAG_SUB][8], data->msg_buf[MSG_MAG_SUB][9],
|
||||
data->msg_buf[MSG_MAG_SUB][10], data->msg_buf[MSG_MAG_SUB][11],
|
||||
data->msg_buf[MSG_MAG_SUB][12], data->msg_buf[MSG_MAG_SUB][13],
|
||||
data->msg_buf[MSG_MAG_SUB][14]);
|
||||
}
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", "Done");
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(name, 0444, sub_mag_name_show, NULL);
|
||||
static DEVICE_ATTR(vendor, 0444, sub_mag_vendor_show, NULL);
|
||||
static DEVICE_ATTR(raw_data, 0664, sub_mag_raw_data_show, sub_mag_raw_data_store);
|
||||
static DEVICE_ATTR(dac, 0444, sub_mag_check_cntl, NULL);
|
||||
static DEVICE_ATTR(chk_registers, 0444, sub_mag_check_registers, NULL);
|
||||
static DEVICE_ATTR(selftest, 0440, sub_mag_selftest_show, NULL);
|
||||
static DEVICE_ATTR(asa, 0444, sub_mag_get_asa, NULL);
|
||||
static DEVICE_ATTR(status, 0444, sub_mag_get_status, NULL);
|
||||
#ifdef CONFIG_SEC_FACTORY
|
||||
static DEVICE_ATTR(dhr_sensor_info, 0444, sub_mag_dhr_sensor_info_show, NULL);
|
||||
#else
|
||||
static DEVICE_ATTR(dhr_sensor_info, 0440, sub_mag_dhr_sensor_info_show, NULL);
|
||||
#endif
|
||||
|
||||
static struct device_attribute *sub_mag_attrs[] = {
|
||||
&dev_attr_name,
|
||||
&dev_attr_vendor,
|
||||
&dev_attr_raw_data,
|
||||
&dev_attr_dac,
|
||||
&dev_attr_chk_registers,
|
||||
&dev_attr_selftest,
|
||||
&dev_attr_asa,
|
||||
&dev_attr_status,
|
||||
&dev_attr_dhr_sensor_info,
|
||||
NULL,
|
||||
};
|
||||
|
||||
int mag_sub_factory_init(void)
|
||||
{
|
||||
adsp_factory_register(MSG_MAG_SUB, sub_mag_attrs);
|
||||
|
||||
pr_info("[FACTORY] %s\n", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mag_sub_factory_exit(void)
|
||||
{
|
||||
adsp_factory_unregister(MSG_MAG_SUB);
|
||||
|
||||
pr_info("[FACTORY] %s\n", __func__);
|
||||
}
|
436
drivers/adsp_factory/pressure_factory.c
Executable file
436
drivers/adsp_factory/pressure_factory.c
Executable file
@@ -0,0 +1,436 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
#define CALIBRATION_FILE_PATH "/efs/FactoryApp/baro_delta"
|
||||
|
||||
#define PR_MAX 8388607 /* 24 bit 2'compl */
|
||||
#define PR_MIN -8388608
|
||||
#define SNS_SUCCESS 0
|
||||
#define ST_PASS 1
|
||||
#define ST_FAIL 0
|
||||
|
||||
#define PRESS_DEVICE_LIST_MAX 5
|
||||
|
||||
enum {
|
||||
OPTION_TYPE_PRESS_GET_DEVICE_ID,
|
||||
OPTION_TYPE_PRESS_MAX
|
||||
};
|
||||
|
||||
static int sea_level_pressure;
|
||||
static int pressure_cal;
|
||||
|
||||
static const struct device_id_t press_device_list[PRESS_DEVICE_LIST_MAX] = {
|
||||
/* ID, Vendor, Name */
|
||||
{0x00, "Unknown", "Unknown"},
|
||||
{0xB1, "STM", "LPS22HB"},
|
||||
{0xB3, "STM", "LPS22HH"},
|
||||
{0xB4, "STM", "LPS22DF"},
|
||||
{0x50, "Bosch", "BMP580"}
|
||||
};
|
||||
|
||||
static void press_get_device_id(struct adsp_data *data)
|
||||
{
|
||||
int32_t cmd = OPTION_TYPE_PRESS_GET_DEVICE_ID, i;
|
||||
int32_t device_index = UNKNOWN_INDEX;
|
||||
uint8_t cnt = 0, device_id = 0;
|
||||
|
||||
adsp_unicast(&cmd, sizeof(cmd), MSG_PRESSURE, 0, MSG_TYPE_OPTION_DEFINE);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_OPTION_DEFINE]
|
||||
& 1 << MSG_PRESSURE) && cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(1000, 1100);
|
||||
|
||||
data->ready_flag[MSG_TYPE_OPTION_DEFINE] &= ~(1 << MSG_PRESSURE);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT)
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
else
|
||||
device_id = (uint8_t)data->msg_buf[MSG_PRESSURE][2];
|
||||
pr_err("[FACTORY] %s: device_id : %d,%d,%d,%d\n", __func__, device_id,
|
||||
(int)data->msg_buf[MSG_PRESSURE][0],
|
||||
(int)data->msg_buf[MSG_PRESSURE][1],
|
||||
(int)data->msg_buf[MSG_PRESSURE][2]);
|
||||
|
||||
if (device_id == 0) {
|
||||
pr_err("[FACTORY] %s: No information\n", __func__);
|
||||
} else {
|
||||
for (i = 0; i < PRESS_DEVICE_LIST_MAX; i++)
|
||||
if (device_id == press_device_list[i].device_id)
|
||||
break;
|
||||
if (i >= PRESS_DEVICE_LIST_MAX)
|
||||
pr_err("[FACTORY] %s: Unknown ID - (0x%x)\n",
|
||||
__func__, device_id);
|
||||
else
|
||||
device_index = i;
|
||||
}
|
||||
|
||||
memcpy(data->press_device_vendor,
|
||||
press_device_list[device_index].device_vendor,
|
||||
sizeof(char) * DEVICE_INFO_LENGTH);
|
||||
memcpy(data->press_device_name,
|
||||
press_device_list[device_index].device_name,
|
||||
sizeof(char) * DEVICE_INFO_LENGTH);
|
||||
|
||||
pr_info("[FACTORY] %s: Device ID - %s(%s)\n", __func__,
|
||||
data->press_device_name, data->press_device_vendor);
|
||||
}
|
||||
|
||||
static ssize_t pressure_vendor_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
if (!strcmp(data->press_device_vendor, press_device_list[0].device_vendor))
|
||||
press_get_device_id(data);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", data->press_device_vendor);
|
||||
}
|
||||
|
||||
static ssize_t pressure_name_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
if (!strcmp(data->press_device_name, press_device_list[0].device_name))
|
||||
press_get_device_id(data);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", data->press_device_name);
|
||||
}
|
||||
|
||||
static ssize_t sea_level_pressure_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", sea_level_pressure);
|
||||
}
|
||||
|
||||
static ssize_t sea_level_pressure_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
if (sscanf(buf, "%10d", &sea_level_pressure) != 1) {
|
||||
pr_err("[FACTORY] %s: sscanf error\n", __func__);
|
||||
return size;
|
||||
}
|
||||
|
||||
sea_level_pressure = sea_level_pressure / 100;
|
||||
|
||||
pr_info("[FACTORY] %s: sea_level_pressure = %d\n", __func__,
|
||||
sea_level_pressure);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/*
|
||||
int pressure_open_calibration(struct adsp_data *data)
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
return error;
|
||||
}
|
||||
*/
|
||||
|
||||
static ssize_t pressure_cabratioin_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
|
||||
schedule_delayed_work(&data->pressure_cal_work, 0);
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t pressure_cabratioin_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
//struct adsp_data *data = dev_get_drvdata(dev);
|
||||
|
||||
//pressure_open_calibration(data);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", pressure_cal);
|
||||
}
|
||||
|
||||
static ssize_t temperature_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
uint8_t cnt = 0;
|
||||
|
||||
adsp_unicast(NULL, 0, MSG_PRESSURE_TEMP, 0, MSG_TYPE_GET_RAW_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_RAW_DATA] &
|
||||
1 << MSG_PRESSURE_TEMP) && cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_RAW_DATA] &= ~(1 << MSG_PRESSURE_TEMP);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
return snprintf(buf, PAGE_SIZE, "-99\n");
|
||||
}
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||
data->msg_buf[MSG_PRESSURE_TEMP][0]);
|
||||
}
|
||||
|
||||
static ssize_t selftest_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
uint8_t cnt = 0;
|
||||
|
||||
adsp_unicast(NULL, 0, MSG_PRESSURE, 0, MSG_TYPE_ST_SHOW_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_ST_SHOW_DATA] &
|
||||
1 << MSG_PRESSURE) && cnt++ < TIMEOUT_CNT)
|
||||
msleep(26);
|
||||
|
||||
data->ready_flag[MSG_TYPE_ST_SHOW_DATA] &= ~(1 << MSG_PRESSURE);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
return snprintf(buf, PAGE_SIZE, "0\n");
|
||||
}
|
||||
|
||||
pr_info("[FACTORY] %s : P:%d, T:%d, RES:%d\n",
|
||||
__func__, data->msg_buf[MSG_PRESSURE][0],
|
||||
data->msg_buf[MSG_PRESSURE][1], data->msg_buf[MSG_PRESSURE][2]);
|
||||
|
||||
if (SNS_SUCCESS == data->msg_buf[MSG_PRESSURE][2])
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", ST_PASS);
|
||||
else
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", ST_FAIL);
|
||||
}
|
||||
|
||||
static ssize_t pressure_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;
|
||||
int i = 0;
|
||||
|
||||
adsp_unicast(NULL, 0, MSG_PRESSURE, 0, MSG_TYPE_GET_DHR_INFO);
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_DHR_INFO] & 1 << MSG_PRESSURE) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_DHR_INFO] &= ~(1 << MSG_PRESSURE);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
} else {
|
||||
for (i = 0; i < 8; i++) {
|
||||
pr_info("[FACTORY] %s - %02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x\n",
|
||||
__func__,
|
||||
data->msg_buf[MSG_PRESSURE][i * 16 + 0],
|
||||
data->msg_buf[MSG_PRESSURE][i * 16 + 1],
|
||||
data->msg_buf[MSG_PRESSURE][i * 16 + 2],
|
||||
data->msg_buf[MSG_PRESSURE][i * 16 + 3],
|
||||
data->msg_buf[MSG_PRESSURE][i * 16 + 4],
|
||||
data->msg_buf[MSG_PRESSURE][i * 16 + 5],
|
||||
data->msg_buf[MSG_PRESSURE][i * 16 + 6],
|
||||
data->msg_buf[MSG_PRESSURE][i * 16 + 7],
|
||||
data->msg_buf[MSG_PRESSURE][i * 16 + 8],
|
||||
data->msg_buf[MSG_PRESSURE][i * 16 + 9],
|
||||
data->msg_buf[MSG_PRESSURE][i * 16 + 10],
|
||||
data->msg_buf[MSG_PRESSURE][i * 16 + 11],
|
||||
data->msg_buf[MSG_PRESSURE][i * 16 + 12],
|
||||
data->msg_buf[MSG_PRESSURE][i * 16 + 13],
|
||||
data->msg_buf[MSG_PRESSURE][i * 16 + 14],
|
||||
data->msg_buf[MSG_PRESSURE][i * 16 + 15]);
|
||||
}
|
||||
}
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", "Done");
|
||||
}
|
||||
|
||||
static ssize_t pressure_sw_offset_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;
|
||||
int input = 0;
|
||||
int sw_offset = 0;
|
||||
int ret;
|
||||
|
||||
ret = kstrtoint(buf, 10, &input);
|
||||
if (ret < 0) {
|
||||
pr_err("[FACTORY] %s: kstrtoint fail\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pr_info("[FACTORY] %s: write value = %d\n", __func__, input);
|
||||
|
||||
adsp_unicast(&input, sizeof(int),
|
||||
MSG_PRESSURE, 0, MSG_TYPE_SET_THRESHOLD);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_SET_THRESHOLD] & 1 << MSG_PRESSURE) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_SET_THRESHOLD] &= ~(1 << MSG_PRESSURE);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
} else {
|
||||
sw_offset = data->msg_buf[MSG_PRESSURE][0];
|
||||
}
|
||||
|
||||
pr_info("[FACTORY] %s: sw_offset %d\n", __func__, sw_offset);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t pressure_sw_offset_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
uint8_t cnt = 0;
|
||||
|
||||
adsp_unicast(NULL, 0, MSG_PRESSURE, 0, MSG_TYPE_GET_THRESHOLD);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_THRESHOLD] &
|
||||
1 << MSG_PRESSURE) && cnt++ < TIMEOUT_CNT)
|
||||
msleep(20);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_THRESHOLD] &= ~(1 << MSG_PRESSURE);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
return snprintf(buf, PAGE_SIZE, "0\n");
|
||||
}
|
||||
|
||||
pr_info("[FACTORY] %s : sw_offset %d\n",
|
||||
__func__, data->msg_buf[MSG_PRESSURE][0]);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", data->msg_buf[MSG_PRESSURE][0]);
|
||||
}
|
||||
|
||||
static ssize_t pressure_esn_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
uint8_t cnt = 0;
|
||||
|
||||
adsp_unicast(NULL, 0, MSG_PRESSURE, 0, MSG_TYPE_GET_REGISTER);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_REGISTER] &
|
||||
1 << MSG_PRESSURE) && cnt++ < TIMEOUT_CNT)
|
||||
msleep(20);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_REGISTER] &= ~(1 << MSG_PRESSURE);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
return snprintf(buf, PAGE_SIZE, "0\n");
|
||||
}
|
||||
|
||||
pr_info("[FACTORY] %s : esn %02X%02X%02X%02X%02X%02X%02X%02X\n",
|
||||
__func__, data->msg_buf[MSG_PRESSURE][0], data->msg_buf[MSG_PRESSURE][1],
|
||||
data->msg_buf[MSG_PRESSURE][2], data->msg_buf[MSG_PRESSURE][3],
|
||||
data->msg_buf[MSG_PRESSURE][4], data->msg_buf[MSG_PRESSURE][5],
|
||||
data->msg_buf[MSG_PRESSURE][6], data->msg_buf[MSG_PRESSURE][7]);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%02X%02X%02X%02X%02X%02X%02X%02X\n",
|
||||
data->msg_buf[MSG_PRESSURE][0], data->msg_buf[MSG_PRESSURE][1],
|
||||
data->msg_buf[MSG_PRESSURE][2], data->msg_buf[MSG_PRESSURE][3],
|
||||
data->msg_buf[MSG_PRESSURE][4], data->msg_buf[MSG_PRESSURE][5],
|
||||
data->msg_buf[MSG_PRESSURE][6], data->msg_buf[MSG_PRESSURE][7]);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(vendor, 0444, pressure_vendor_show, NULL);
|
||||
static DEVICE_ATTR(name, 0444, pressure_name_show, NULL);
|
||||
static DEVICE_ATTR(calibration, 0664,
|
||||
pressure_cabratioin_show, pressure_cabratioin_store);
|
||||
static DEVICE_ATTR(sea_level_pressure, 0664,
|
||||
sea_level_pressure_show, sea_level_pressure_store);
|
||||
static DEVICE_ATTR(temperature, 0444, temperature_show, NULL);
|
||||
static DEVICE_ATTR(selftest, 0444, selftest_show, NULL);
|
||||
#ifdef CONFIG_SEC_FACTORY
|
||||
static DEVICE_ATTR(dhr_sensor_info, 0444,
|
||||
pressure_dhr_sensor_info_show, NULL);
|
||||
#else
|
||||
static DEVICE_ATTR(dhr_sensor_info, 0440,
|
||||
pressure_dhr_sensor_info_show, NULL);
|
||||
#endif
|
||||
static DEVICE_ATTR(sw_offset, 0664,
|
||||
pressure_sw_offset_show, pressure_sw_offset_store);
|
||||
static DEVICE_ATTR(esn, 0440, pressure_esn_show, NULL);
|
||||
|
||||
static struct device_attribute *pressure_attrs[] = {
|
||||
&dev_attr_vendor,
|
||||
&dev_attr_name,
|
||||
&dev_attr_calibration,
|
||||
&dev_attr_sea_level_pressure,
|
||||
&dev_attr_temperature,
|
||||
&dev_attr_selftest,
|
||||
&dev_attr_dhr_sensor_info,
|
||||
&dev_attr_sw_offset,
|
||||
&dev_attr_esn,
|
||||
NULL,
|
||||
};
|
||||
|
||||
void pressure_cal_work_func(struct work_struct *work)
|
||||
{
|
||||
struct adsp_data *data = container_of((struct delayed_work *)work,
|
||||
struct adsp_data, pressure_cal_work);
|
||||
int cnt = 0;
|
||||
int temp = 0;
|
||||
|
||||
adsp_unicast(&temp, sizeof(temp), MSG_PRESSURE, 0, MSG_TYPE_SET_CAL_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_SET_CAL_DATA] & 1 << MSG_PRESSURE) &&
|
||||
cnt++ < 3)
|
||||
msleep(30);
|
||||
|
||||
data->ready_flag[MSG_TYPE_SET_CAL_DATA] &= ~(1 << MSG_PRESSURE);
|
||||
|
||||
if (cnt >= 3) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
pressure_cal = data->msg_buf[MSG_PRESSURE][0];
|
||||
if (!strcmp(data->press_device_vendor, press_device_list[0].device_vendor) ||
|
||||
!strcmp(data->press_device_name, press_device_list[0].device_name))
|
||||
press_get_device_id(data);
|
||||
|
||||
pr_info("[FACTORY] %s: pressure_cal = %d (lsb)\n", __func__, data->msg_buf[MSG_PRESSURE][0]);
|
||||
}
|
||||
EXPORT_SYMBOL(pressure_cal_work_func);
|
||||
void pressure_factory_init_work(struct adsp_data *data)
|
||||
{
|
||||
memcpy(data->press_device_vendor,
|
||||
press_device_list[0].device_vendor,
|
||||
sizeof(char) * DEVICE_INFO_LENGTH);
|
||||
memcpy(data->press_device_name,
|
||||
press_device_list[0].device_name,
|
||||
sizeof(char) * DEVICE_INFO_LENGTH);
|
||||
|
||||
schedule_delayed_work(&data->pressure_cal_work, msecs_to_jiffies(8000));
|
||||
}
|
||||
EXPORT_SYMBOL(pressure_factory_init_work);
|
||||
|
||||
int __init pressure_factory_init(void)
|
||||
{
|
||||
adsp_factory_register(MSG_PRESSURE, pressure_attrs);
|
||||
|
||||
pr_info("[FACTORY] %s\n", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
void __exit pressure_factory_exit(void)
|
||||
{
|
||||
adsp_factory_unregister(MSG_PRESSURE);
|
||||
|
||||
pr_info("[FACTORY] %s\n", __func__);
|
||||
}
|
991
drivers/adsp_factory/prox_factory.c
Executable file
991
drivers/adsp_factory/prox_factory.c
Executable file
@@ -0,0 +1,991 @@
|
||||
/*
|
||||
* 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"
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_CONTROL_PROX_LED_GPIO)
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#define PROX_LED_EN_GPIO 113
|
||||
#endif
|
||||
#define PROX_AVG_COUNT 40
|
||||
#define PROX_ALERT_THRESHOLD 200
|
||||
#define PROX_TH_READ 0
|
||||
#define PROX_TH_WRITE 1
|
||||
#define BUFFER_MAX 128
|
||||
#define PROX_REG_START 0x80
|
||||
#define PROX_DETECT_HIGH_TH 16368
|
||||
#define PROX_DETECT_LOW_TH 1000
|
||||
|
||||
struct prox_data {
|
||||
struct hrtimer prox_timer;
|
||||
struct work_struct work_prox;
|
||||
struct workqueue_struct *prox_wq;
|
||||
struct adsp_data *dev_data;
|
||||
int min;
|
||||
int max;
|
||||
int avg;
|
||||
int val;
|
||||
int offset;
|
||||
int reg_backup[2];
|
||||
int debug_info_cmd;
|
||||
short avgwork_check;
|
||||
short avgtimer_enabled;
|
||||
};
|
||||
|
||||
enum {
|
||||
PRX_THRESHOLD_DETECT_H,
|
||||
PRX_THRESHOLD_HIGH_DETECT_L,
|
||||
PRX_THRESHOLD_HIGH_DETECT_H,
|
||||
PRX_THRESHOLD_RELEASE_L,
|
||||
};
|
||||
|
||||
enum {
|
||||
PROX_CMD_TYPE_GET_TRIM_CHECK,
|
||||
PROX_CMD_TYPE_GET_CAL_DATA,
|
||||
PROX_CMD_TYPE_INIT_CAL_DATA,
|
||||
PROX_CMD_TYPE_LED_CONTROL,
|
||||
PROX_CMD_TYPE_SAVE_CAL_DATA,
|
||||
PROX_CMD_TYPE_TOUCH_PROX,
|
||||
PROX_CMD_TYPE_MAX
|
||||
};
|
||||
|
||||
static struct prox_data *pdata;
|
||||
|
||||
static int get_prox_sidx(struct adsp_data *data)
|
||||
{
|
||||
int ret = MSG_PROX;
|
||||
#if defined(CONFIG_SUPPORT_DUAL_OPTIC) && !defined(CONFIG_SUPPORT_DUAL_OPTIC_BUT_SUPPORT_SINGLE_PROX)
|
||||
switch (data->fac_fstate) {
|
||||
case FSTATE_INACTIVE:
|
||||
case FSTATE_FAC_INACTIVE:
|
||||
ret = MSG_PROX;
|
||||
break;
|
||||
case FSTATE_ACTIVE:
|
||||
case FSTATE_FAC_ACTIVE:
|
||||
case FSTATE_FAC_INACTIVE_2:
|
||||
ret = MSG_PROX_SUB;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_PROX_CALIBRATION)
|
||||
void prox_send_cal_data(struct adsp_data *data, uint16_t prox_idx, bool fac_cal)
|
||||
{
|
||||
int32_t msg = -1, cnt = 0, prox_cal;
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_CONTROL_PROX_LED_GPIO)
|
||||
if (prox_idx == MSG_PROX) {
|
||||
int led_gpio, ret;
|
||||
struct device_node *np = of_find_node_by_name(NULL, "ssc_prox_led_en_gpio");
|
||||
|
||||
if (np == NULL) {
|
||||
pr_info("[SSC_FAC] %s: ssc_prox_led_en_gpio is NULL\n", __func__);
|
||||
} else {
|
||||
led_gpio = of_get_named_gpio_flags(np, "qcom,prox_led-en-gpio",
|
||||
0, NULL);
|
||||
if (led_gpio >= 0) {
|
||||
ret = gpio_request(led_gpio, NULL);
|
||||
if (ret >= 0) {
|
||||
pr_info("[SSC_FAC] %s: prox_led_en_gpio set\n",
|
||||
__func__);
|
||||
gpio_direction_output(led_gpio, 1);
|
||||
gpio_free(led_gpio);
|
||||
} else {
|
||||
pr_err("[SSC_FAC] %s - gpio_request fail(%d)\n",
|
||||
__func__, ret);
|
||||
}
|
||||
} else {
|
||||
pr_err("[SSC_FAC] %s: prox_led_en_gpio fail(%d)\n",
|
||||
__func__, led_gpio);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (prox_idx == MSG_PROX)
|
||||
prox_cal = data->prox_cal;
|
||||
else
|
||||
prox_cal = data->prox_sub_cal;
|
||||
|
||||
if (!fac_cal || (prox_cal == 0)) {
|
||||
#if IS_ENABLED(CONFIG_SEC_FACTORY)
|
||||
pr_info("[SSC_FAC] %s[%d]: No cal data (%d)\n",
|
||||
__func__, (int)prox_idx - MSG_PROX, prox_cal);
|
||||
#else
|
||||
mutex_lock(&data->prox_factory_mutex);
|
||||
adsp_unicast(&msg, sizeof(int32_t),
|
||||
prox_idx, 0, MSG_TYPE_SET_CAL_DATA);
|
||||
while (!(data->ready_flag[MSG_TYPE_SET_CAL_DATA] &
|
||||
1 << prox_idx) && cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
if (cnt >= TIMEOUT_CNT)
|
||||
pr_err("[SSC_FAC] %s[%d]: Timeout!!!\n",
|
||||
__func__, prox_idx);
|
||||
data->ready_flag[MSG_TYPE_SET_CAL_DATA] &= ~(1 << prox_idx);
|
||||
mutex_unlock(&data->prox_factory_mutex);
|
||||
pr_info("[SSC_FAC] %s[%d]: Excute in-use cal\n",
|
||||
__func__, (int)prox_idx - MSG_PROX);
|
||||
#endif
|
||||
} else if (prox_cal > 0) {
|
||||
mutex_lock(&data->prox_factory_mutex);
|
||||
msg = prox_cal;
|
||||
adsp_unicast(&msg, sizeof(int32_t),
|
||||
prox_idx, 0, MSG_TYPE_SET_CAL_DATA);
|
||||
while (!(data->ready_flag[MSG_TYPE_SET_CAL_DATA] &
|
||||
1 << prox_idx) && cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
if (cnt >= TIMEOUT_CNT)
|
||||
pr_err("[SSC_FAC] %s[%d]: Timeout!!!\n",
|
||||
__func__, (int)prox_idx - MSG_PROX);
|
||||
data->ready_flag[MSG_TYPE_SET_CAL_DATA] &= ~(1 << prox_idx);
|
||||
mutex_unlock(&data->prox_factory_mutex);
|
||||
pr_info("[SSC_FAC] %s[%d]: Cal data: %d\n", __func__,
|
||||
(int)prox_idx - MSG_PROX, msg);
|
||||
} else {
|
||||
pr_info("[SSC_FAC] %s[%d]: No cal data\n",
|
||||
__func__, (int)prox_idx - MSG_PROX);
|
||||
}
|
||||
}
|
||||
|
||||
void prox_cal_init_work(struct adsp_data *data)
|
||||
{
|
||||
data->prox_cal = 0;
|
||||
data->prox_sub_cal = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static ssize_t prox_vendor_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_LIGHT_FACTORY)
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
int32_t display_idx = (get_prox_sidx(data) == MSG_PROX) ? 0 : 1;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n",
|
||||
data->light_device_vendor[display_idx]);
|
||||
#else
|
||||
return snprintf(buf, PAGE_SIZE, "UNKNOWN\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
static ssize_t prox_name_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_LIGHT_FACTORY)
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
int32_t display_idx = (get_prox_sidx(data) == MSG_PROX) ? 0 : 1;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n",
|
||||
data->light_device_name[display_idx]);
|
||||
#else
|
||||
return snprintf(buf, PAGE_SIZE, "UNKNOWN\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
int get_prox_raw_data(struct adsp_data *data, int *raw_data, int *offset)
|
||||
{
|
||||
uint8_t cnt = 0;
|
||||
uint16_t prox_idx = get_prox_sidx(data);
|
||||
|
||||
mutex_lock(&data->prox_factory_mutex);
|
||||
adsp_unicast(NULL, 0, prox_idx, 0, MSG_TYPE_GET_RAW_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_RAW_DATA] & 1 << prox_idx) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_RAW_DATA] &= ~(1 << prox_idx);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
mutex_unlock(&data->prox_factory_mutex);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*raw_data = data->msg_buf[prox_idx][0];
|
||||
*offset = data->msg_buf[prox_idx][1];
|
||||
mutex_unlock(&data->prox_factory_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t prox_raw_data_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
|
||||
if (pdata->avgwork_check == 0)
|
||||
get_prox_raw_data(data, &pdata->val, &pdata->offset);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", pdata->val);
|
||||
}
|
||||
|
||||
static ssize_t prox_avg_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%d,%d,%d\n", pdata->min,
|
||||
pdata->avg, pdata->max);
|
||||
}
|
||||
|
||||
static ssize_t prox_avg_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
int new_value;
|
||||
|
||||
if (sysfs_streq(buf, "0"))
|
||||
new_value = 0;
|
||||
else
|
||||
new_value = 1;
|
||||
|
||||
if (new_value == pdata->avgtimer_enabled)
|
||||
return size;
|
||||
|
||||
if (new_value == 0) {
|
||||
pdata->avgtimer_enabled = 0;
|
||||
hrtimer_cancel(&pdata->prox_timer);
|
||||
cancel_work_sync(&pdata->work_prox);
|
||||
} else {
|
||||
pdata->avgtimer_enabled = 1;
|
||||
pdata->dev_data = data;
|
||||
hrtimer_start(&pdata->prox_timer,
|
||||
ns_to_ktime(2000 * NSEC_PER_MSEC),
|
||||
HRTIMER_MODE_REL);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static void prox_work_func(struct work_struct *work)
|
||||
{
|
||||
int min = 0, max = 0, avg = 0;
|
||||
int i;
|
||||
|
||||
pdata->avgwork_check = 1;
|
||||
for (i = 0; i < PROX_AVG_COUNT; i++) {
|
||||
msleep(20);
|
||||
|
||||
get_prox_raw_data(pdata->dev_data, &pdata->val, &pdata->offset);
|
||||
avg += pdata->val;
|
||||
|
||||
if (!i)
|
||||
min = pdata->val;
|
||||
else if (pdata->val < min)
|
||||
min = pdata->val;
|
||||
|
||||
if (pdata->val > max)
|
||||
max = pdata->val;
|
||||
}
|
||||
avg /= PROX_AVG_COUNT;
|
||||
|
||||
pdata->min = min;
|
||||
pdata->avg = avg;
|
||||
pdata->max = max;
|
||||
pdata->avgwork_check = 0;
|
||||
}
|
||||
|
||||
static enum hrtimer_restart prox_timer_func(struct hrtimer *timer)
|
||||
{
|
||||
queue_work(pdata->prox_wq, &pdata->work_prox);
|
||||
hrtimer_forward_now(&pdata->prox_timer,
|
||||
ns_to_ktime(2000 * NSEC_PER_MSEC));
|
||||
return HRTIMER_RESTART;
|
||||
}
|
||||
|
||||
|
||||
static void prox_led_control(struct adsp_data *data, int led_number)
|
||||
{
|
||||
uint16_t prox_idx = get_prox_sidx(data);
|
||||
int cnt = 0;
|
||||
int32_t msg[2];
|
||||
|
||||
msg[0] = PROX_CMD_TYPE_LED_CONTROL;
|
||||
msg[1] = led_number;
|
||||
|
||||
mutex_lock(&data->prox_factory_mutex);
|
||||
adsp_unicast(&msg, sizeof(msg), prox_idx, 0, MSG_TYPE_GET_CAL_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_CAL_DATA] & 1 << prox_idx) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_CAL_DATA] &= ~(1 << prox_idx);
|
||||
mutex_unlock(&data->prox_factory_mutex);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT)
|
||||
pr_err("[SSC_FAC] %s: Timeout!!!\n", __func__);
|
||||
}
|
||||
|
||||
static ssize_t prox_led_test_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
int data_buf, offset = 0, ret = 0, result = 1;
|
||||
|
||||
prox_led_control(data, 0);
|
||||
msleep(200);
|
||||
ret = get_prox_raw_data(data, &data_buf, &offset);
|
||||
prox_led_control(data, 4);
|
||||
|
||||
if (ret != 0)
|
||||
result = -1;
|
||||
|
||||
pr_info("[SSC_FAC] %s: [%d] %d\n", __func__, result, data_buf);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d,%d,%d,%d,%d\n", result,
|
||||
data_buf, data_buf, data_buf, data_buf);
|
||||
}
|
||||
|
||||
static int prox_get_threshold(struct adsp_data *data, int type)
|
||||
{
|
||||
uint8_t cnt = 0;
|
||||
uint16_t prox_idx = get_prox_sidx(data);
|
||||
int32_t msg_buf[2];
|
||||
int ret = 0;
|
||||
|
||||
msg_buf[0] = type;
|
||||
msg_buf[1] = 0;
|
||||
|
||||
mutex_lock(&data->prox_factory_mutex);
|
||||
adsp_unicast(msg_buf, sizeof(msg_buf),
|
||||
prox_idx, 0, MSG_TYPE_GET_THRESHOLD);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_THRESHOLD] & 1 << prox_idx) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_THRESHOLD] &= ~(1 << prox_idx);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[SSC_FAC] %s: Timeout!!!\n", __func__);
|
||||
mutex_unlock(&data->prox_factory_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = data->msg_buf[prox_idx][0];
|
||||
mutex_unlock(&data->prox_factory_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void prox_set_threshold(struct adsp_data *data, int type, int val)
|
||||
{
|
||||
uint8_t cnt = 0;
|
||||
uint16_t prox_idx = get_prox_sidx(data);
|
||||
int32_t msg_buf[2];
|
||||
|
||||
msg_buf[0] = type;
|
||||
msg_buf[1] = val;
|
||||
|
||||
mutex_lock(&data->prox_factory_mutex);
|
||||
adsp_unicast(msg_buf, sizeof(msg_buf),
|
||||
prox_idx, 0, MSG_TYPE_SET_THRESHOLD);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_SET_THRESHOLD] & 1 << prox_idx) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_SET_THRESHOLD] &= ~(1 << prox_idx);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT)
|
||||
pr_err("[SSC_FAC] %s: Timeout!!!\n", __func__);
|
||||
|
||||
mutex_unlock(&data->prox_factory_mutex);
|
||||
}
|
||||
|
||||
static ssize_t prox_cal_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_PROX_CALIBRATION)
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
|
||||
if (get_prox_sidx(data) == MSG_PROX)
|
||||
return snprintf(buf, PAGE_SIZE, "%d,0,0\n", data->prox_cal);
|
||||
else
|
||||
return snprintf(buf, PAGE_SIZE, "%d,0,0\n", data->prox_sub_cal);
|
||||
#else
|
||||
return snprintf(buf, PAGE_SIZE, "0,0,0\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
static ssize_t prox_cal_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_PROX_CALIBRATION)
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
int32_t cmd, msg_buf[2], cnt = 0;
|
||||
uint16_t prox_idx = get_prox_sidx(data);
|
||||
|
||||
if (sysfs_streq(buf, "1")) {
|
||||
cmd = PROX_CMD_TYPE_GET_CAL_DATA;
|
||||
} else if (sysfs_streq(buf, "0")) {
|
||||
cmd = PROX_CMD_TYPE_INIT_CAL_DATA;
|
||||
} else {
|
||||
pr_err("[SSC_FAC] %s: wrong value\n", __func__);
|
||||
return size;
|
||||
}
|
||||
|
||||
pr_info("[SSC_FAC] %s[%d]: msg %d\n",
|
||||
__func__, (int)prox_idx - MSG_PROX, cmd);
|
||||
|
||||
mutex_lock(&data->prox_factory_mutex);
|
||||
adsp_unicast(&cmd, sizeof(int32_t), prox_idx, 0, MSG_TYPE_GET_CAL_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_CAL_DATA] & 1 << prox_idx) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
msleep(20);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_CAL_DATA] &= ~(1 << prox_idx);
|
||||
mutex_unlock(&data->prox_factory_mutex);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[SSC_FAC] %s[%d]: Timeout!!!\n", __func__,
|
||||
(int)prox_idx - MSG_PROX);
|
||||
return size;
|
||||
} else if (data->msg_buf[prox_idx][0] < 0) {
|
||||
pr_err("[SSC_FAC] %s[%d]: fail! %d\n", __func__,
|
||||
(int)prox_idx - MSG_PROX,
|
||||
data->msg_buf[prox_idx][0]);
|
||||
return size;
|
||||
}
|
||||
|
||||
cnt = 0;
|
||||
msg_buf[0] = PROX_CMD_TYPE_SAVE_CAL_DATA;
|
||||
msg_buf[1] = data->msg_buf[prox_idx][0];
|
||||
|
||||
if (prox_idx == MSG_PROX)
|
||||
data->prox_cal = data->msg_buf[prox_idx][0];
|
||||
else
|
||||
data->prox_sub_cal = data->msg_buf[prox_idx][0];
|
||||
|
||||
mutex_lock(&data->prox_factory_mutex);
|
||||
adsp_unicast(msg_buf, sizeof(msg_buf), prox_idx, 0,
|
||||
MSG_TYPE_SET_TEMPORARY_MSG);
|
||||
while (!(data->ready_flag[MSG_TYPE_SET_TEMPORARY_MSG] & 1 << prox_idx) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
msleep(20);
|
||||
if (cnt >= TIMEOUT_CNT)
|
||||
pr_err("[SSC_FAC] %s[%d]: SAVE_CAL_DATA Timeout!!!\n",
|
||||
__func__, (int)prox_idx - MSG_PROX);
|
||||
|
||||
data->ready_flag[MSG_TYPE_SET_TEMPORARY_MSG] &= ~(1 << prox_idx);
|
||||
mutex_unlock(&data->prox_factory_mutex);
|
||||
if ((prox_idx == MSG_PROX) && (data->prox_cal > 0))
|
||||
prox_send_cal_data(data, prox_idx, true);
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_DUAL_OPTIC)
|
||||
else if ((prox_idx == MSG_PROX_SUB) && (data->prox_sub_cal > 0))
|
||||
prox_send_cal_data(data, prox_idx, true);
|
||||
#endif
|
||||
|
||||
#else
|
||||
pr_info("[SSC_FAC] %s: unsupported prox cal!\n", __func__);
|
||||
#endif
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t prox_thresh_high_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
int thd;
|
||||
|
||||
thd = prox_get_threshold(data, PRX_THRESHOLD_DETECT_H);
|
||||
pr_info("[SSC_FAC] %s: %d\n", __func__, thd);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", thd);
|
||||
}
|
||||
|
||||
static ssize_t prox_thresh_high_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
int thd = 0;
|
||||
|
||||
if (kstrtoint(buf, 10, &thd)) {
|
||||
pr_err("[SSC_FAC] %s: kstrtoint fail\n", __func__);
|
||||
return size;
|
||||
}
|
||||
|
||||
prox_set_threshold(data, PRX_THRESHOLD_DETECT_H, thd);
|
||||
pr_info("[SSC_FAC] %s: %d\n", __func__, thd);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t prox_thresh_low_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
int thd;
|
||||
|
||||
thd = prox_get_threshold(data, PRX_THRESHOLD_RELEASE_L);
|
||||
pr_info("[SSC_FAC] %s: %d\n", __func__, thd);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", thd);
|
||||
}
|
||||
|
||||
static ssize_t prox_thresh_low_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
int thd = 0;
|
||||
|
||||
if (kstrtoint(buf, 10, &thd)) {
|
||||
pr_err("[SSC_FAC] %s: kstrtoint fail\n", __func__);
|
||||
return size;
|
||||
}
|
||||
|
||||
prox_set_threshold(data, PRX_THRESHOLD_RELEASE_L, thd);
|
||||
pr_info("[SSC_FAC] %s: %d\n", __func__, thd);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t prox_thresh_detect_high_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
int thd;
|
||||
|
||||
thd = prox_get_threshold(data, PRX_THRESHOLD_HIGH_DETECT_H);
|
||||
pr_info("[SSC_FAC] %s: %d\n", __func__, thd);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", thd);
|
||||
}
|
||||
|
||||
static ssize_t prox_thresh_detect_high_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
int thd = 0;
|
||||
|
||||
if (kstrtoint(buf, 10, &thd)) {
|
||||
pr_err("[SSC_FAC] %s: kstrtoint fail\n", __func__);
|
||||
return size;
|
||||
}
|
||||
|
||||
prox_set_threshold(data, PRX_THRESHOLD_HIGH_DETECT_H, thd);
|
||||
pr_info("[SSC_FAC] %s: %d\n", __func__, thd);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t prox_thresh_detect_low_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
int thd;
|
||||
|
||||
thd = prox_get_threshold(data, PRX_THRESHOLD_HIGH_DETECT_L);
|
||||
pr_info("[SSC_FAC] %s: %d\n", __func__, thd);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", thd);
|
||||
}
|
||||
|
||||
static ssize_t prox_thresh_detect_low_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
int thd = 0;
|
||||
|
||||
if (kstrtoint(buf, 10, &thd)) {
|
||||
pr_err("[SSC_FAC] %s: kstrtoint fail\n", __func__);
|
||||
return size;
|
||||
}
|
||||
|
||||
prox_set_threshold(data, PRX_THRESHOLD_HIGH_DETECT_L, thd);
|
||||
pr_info("[SSC_FAC] %s: %d\n", __func__, thd);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t prox_cancel_pass_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_SUPPORT_PROX_CALIBRATION)
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
|
||||
if (get_prox_sidx(data) == MSG_PROX)
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||
(data->prox_cal > 0) ? 1 : 0);
|
||||
else
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||
(data->prox_sub_cal > 0) ? 1 : 0);
|
||||
#else
|
||||
return snprintf(buf, PAGE_SIZE, "1\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
static ssize_t prox_default_trim_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", pdata->offset);
|
||||
}
|
||||
|
||||
static ssize_t prox_alert_thresh_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", PROX_ALERT_THRESHOLD);
|
||||
}
|
||||
|
||||
static ssize_t prox_register_read_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
uint16_t prox_idx = get_prox_sidx(data);
|
||||
int cnt = 0;
|
||||
int32_t msg_buf[1];
|
||||
|
||||
msg_buf[0] = pdata->reg_backup[0];
|
||||
|
||||
mutex_lock(&data->prox_factory_mutex);
|
||||
adsp_unicast(msg_buf, sizeof(msg_buf),
|
||||
prox_idx, 0, MSG_TYPE_GET_REGISTER);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_REGISTER] & 1 << prox_idx) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_REGISTER] &= ~(1 << prox_idx);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT)
|
||||
pr_err("[SSC_FAC] %s: Timeout!!!\n", __func__);
|
||||
|
||||
pdata->reg_backup[1] = data->msg_buf[prox_idx][0];
|
||||
pr_info("[SSC_FAC] %s: [0x%x]: %d\n",
|
||||
__func__, pdata->reg_backup[0], pdata->reg_backup[1]);
|
||||
|
||||
mutex_unlock(&data->prox_factory_mutex);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", pdata->reg_backup[1]);
|
||||
}
|
||||
|
||||
static ssize_t prox_register_read_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
int reg = 0;
|
||||
|
||||
if (sscanf(buf, "%3d", ®) != 1) {
|
||||
pr_err("[SSC_FAC]: %s - The number of data are wrong\n",
|
||||
__func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pdata->reg_backup[0] = reg;
|
||||
pr_info("[SSC_FAC] %s: [0x%x]\n", __func__, pdata->reg_backup[0]);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t prox_register_write_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
uint16_t prox_idx = get_prox_sidx(data);
|
||||
int cnt = 0;
|
||||
int32_t msg_buf[2];
|
||||
|
||||
if (sscanf(buf, "%3d,%5d", &msg_buf[0], &msg_buf[1]) != 2) {
|
||||
pr_err("[SSC_FAC]: %s - The number of data are wrong\n",
|
||||
__func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&data->prox_factory_mutex);
|
||||
adsp_unicast(msg_buf, sizeof(msg_buf),
|
||||
prox_idx, 0, MSG_TYPE_SET_REGISTER);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_SET_REGISTER] & 1 << prox_idx) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_SET_REGISTER] &= ~(1 << prox_idx);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT)
|
||||
pr_err("[SSC_FAC] %s: Timeout!!!\n", __func__);
|
||||
|
||||
pdata->reg_backup[0] = msg_buf[0];
|
||||
pr_info("[SSC_FAC] %s: 0x%x - %d\n",
|
||||
__func__, msg_buf[0], data->msg_buf[prox_idx][0]);
|
||||
mutex_unlock(&data->prox_factory_mutex);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t prox_touch_prox_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
uint16_t prox_idx = get_prox_sidx(data);
|
||||
int cnt = 0;
|
||||
int32_t msg_buf[2];
|
||||
|
||||
if (sscanf(buf, "%2d", &msg_buf[1]) != 1) {
|
||||
pr_err("[SSC_FAC]: %s - The number of data are wrong\n",
|
||||
__func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
msg_buf[0] = PROX_CMD_TYPE_TOUCH_PROX;
|
||||
|
||||
mutex_lock(&data->prox_factory_mutex);
|
||||
adsp_unicast(msg_buf, sizeof(msg_buf), prox_idx, 0, MSG_TYPE_GET_CAL_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_CAL_DATA] & 1 << prox_idx) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_CAL_DATA] &= ~(1 << prox_idx);
|
||||
|
||||
pr_info("[SSC_FAC] %s: event: %d\n", __func__, msg_buf[1]);
|
||||
mutex_unlock(&data->prox_factory_mutex);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT)
|
||||
pr_err("[SSC_FAC] %s: Timeout!!!\n", __func__);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t prox_debug_info_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
uint16_t prox_idx = get_prox_sidx(data);
|
||||
int cnt = 0;
|
||||
int32_t msg_buf[1];
|
||||
|
||||
msg_buf[0] = pdata->debug_info_cmd;
|
||||
|
||||
mutex_lock(&data->prox_factory_mutex);
|
||||
adsp_unicast(msg_buf, sizeof(msg_buf),
|
||||
prox_idx, 0, MSG_TYPE_GET_DUMP_REGISTER);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_DUMP_REGISTER] & 1 << prox_idx)
|
||||
&& cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_DUMP_REGISTER] &= ~(1 << prox_idx);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT)
|
||||
pr_err("[SSC_FAC] %s: Timeout!!!\n", __func__);
|
||||
|
||||
mutex_unlock(&data->prox_factory_mutex);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
|
||||
data->msg_buf[prox_idx][0], data->msg_buf[prox_idx][1],
|
||||
data->msg_buf[prox_idx][2], data->msg_buf[prox_idx][3],
|
||||
data->msg_buf[prox_idx][4], data->msg_buf[prox_idx][5],
|
||||
data->msg_buf[prox_idx][6], data->msg_buf[prox_idx][7],
|
||||
data->msg_buf[prox_idx][8], data->msg_buf[prox_idx][9],
|
||||
data->msg_buf[prox_idx][10], data->msg_buf[prox_idx][11]);
|
||||
}
|
||||
|
||||
static ssize_t prox_debug_info_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
int reg = 0;
|
||||
|
||||
if (sscanf(buf, "%3d", ®) != 1) {
|
||||
pr_err("[SSC_FAC]: %s - The number of data are wrong\n",
|
||||
__func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pdata->debug_info_cmd = reg;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t prox_light_get_dhr_sensor_info_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
uint16_t prox_idx = get_prox_sidx(data);
|
||||
uint8_t cnt = 0;
|
||||
int offset = 0;
|
||||
int32_t *info = data->msg_buf[prox_idx];
|
||||
|
||||
mutex_lock(&data->prox_factory_mutex);
|
||||
adsp_unicast(NULL, 0, prox_idx, 0, MSG_TYPE_GET_DHR_INFO);
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_DHR_INFO] & 1 << prox_idx) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_DHR_INFO] &= ~(1 << prox_idx);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT)
|
||||
pr_err("[SSC_FAC] %s: Timeout!!!\n", __func__);
|
||||
|
||||
pr_info("[SSC_FAC] %d,%d,%d,%d,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%d\n",
|
||||
info[0], info[1], info[2], info[3], info[4], info[5],
|
||||
info[6], info[7], info[8], info[9], info[10], info[11]);
|
||||
|
||||
offset += snprintf(buf + offset, PAGE_SIZE - offset,
|
||||
"\"THD\":\"%d %d %d %d\",", info[0], info[1], info[2], info[3]);
|
||||
offset += snprintf(buf + offset, PAGE_SIZE - offset,
|
||||
"\"PDRIVE_CURRENT\":\"%02x\",", info[4]);
|
||||
offset += snprintf(buf + offset, PAGE_SIZE - offset,
|
||||
"\"PERSIST_TIME\":\"%02x\",", info[5]);
|
||||
offset += snprintf(buf + offset, PAGE_SIZE - offset,
|
||||
"\"PPULSE\":\"%02x\",", info[6]);
|
||||
offset += snprintf(buf + offset, PAGE_SIZE - offset,
|
||||
"\"PGAIN\":\"%02x\",", info[7]);
|
||||
offset += snprintf(buf + offset, PAGE_SIZE - offset,
|
||||
"\"PTIME\":\"%02x\",", info[8]);
|
||||
offset += snprintf(buf + offset, PAGE_SIZE - offset,
|
||||
"\"PPLUSE_LEN\":\"%02x\",", info[9]);
|
||||
offset += snprintf(buf + offset, PAGE_SIZE - offset,
|
||||
"\"ATIME\":\"%02x\",", info[10]);
|
||||
offset += snprintf(buf + offset, PAGE_SIZE - offset,
|
||||
"\"POFFSET\":\"%d\"\n", info[11]);
|
||||
|
||||
mutex_unlock(&data->prox_factory_mutex);
|
||||
return offset;
|
||||
}
|
||||
|
||||
static ssize_t prox_wakelock_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t prox_trim_check_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
uint16_t prox_idx = get_prox_sidx(data);
|
||||
int cnt = 0;
|
||||
int32_t msg = PROX_CMD_TYPE_GET_TRIM_CHECK;
|
||||
|
||||
mutex_lock(&data->prox_factory_mutex);
|
||||
adsp_unicast(&msg, sizeof(int32_t), prox_idx, 0, MSG_TYPE_GET_CAL_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_CAL_DATA] & 1 << prox_idx) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_CAL_DATA] &= ~(1 << prox_idx);
|
||||
mutex_unlock(&data->prox_factory_mutex);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[SSC_FAC] %s: Timeout!!!\n", __func__);
|
||||
return snprintf(buf, PAGE_SIZE, "NG\n");
|
||||
}
|
||||
|
||||
pr_info("[SSC_FAC] %s: [%s]: 0x%x, 0x%x\n",
|
||||
__func__, (data->msg_buf[prox_idx][0] > 0) ? "TRIM" : "UNTRIM",
|
||||
(uint16_t)data->msg_buf[prox_idx][1],
|
||||
(uint16_t)data->msg_buf[prox_idx][2]);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n",
|
||||
(data->msg_buf[prox_idx][0] > 0) ? "TRIM" : "UNTRIM");
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(vendor, 0444, prox_vendor_show, NULL);
|
||||
static DEVICE_ATTR(name, 0444, prox_name_show, NULL);
|
||||
static DEVICE_ATTR(state, 0444, prox_raw_data_show, NULL);
|
||||
static DEVICE_ATTR(raw_data, 0444, prox_raw_data_show, NULL);
|
||||
static DEVICE_ATTR(prox_led_test, 0444, prox_led_test_show, NULL);
|
||||
static DEVICE_ATTR(prox_avg, 0664,
|
||||
prox_avg_show, prox_avg_store);
|
||||
static DEVICE_ATTR(prox_cal, 0664,
|
||||
prox_cal_show, prox_cal_store);
|
||||
static DEVICE_ATTR(thresh_high, 0664,
|
||||
prox_thresh_high_show, prox_thresh_high_store);
|
||||
static DEVICE_ATTR(thresh_low, 0664,
|
||||
prox_thresh_low_show, prox_thresh_low_store);
|
||||
static DEVICE_ATTR(register_write, 0220,
|
||||
NULL, prox_register_write_store);
|
||||
static DEVICE_ATTR(register_read, 0664,
|
||||
prox_register_read_show, prox_register_read_store);
|
||||
static DEVICE_ATTR(prox_offset_pass, 0444, prox_cancel_pass_show, NULL);
|
||||
static DEVICE_ATTR(prox_trim, 0444, prox_default_trim_show, NULL);
|
||||
static DEVICE_ATTR(thresh_detect_high, 0664,
|
||||
prox_thresh_detect_high_show, prox_thresh_detect_high_store);
|
||||
static DEVICE_ATTR(thresh_detect_low, 0664,
|
||||
prox_thresh_detect_low_show, prox_thresh_detect_low_store);
|
||||
static DEVICE_ATTR(prox_alert_thresh, 0444, prox_alert_thresh_show, NULL);
|
||||
static DEVICE_ATTR(dhr_sensor_info, 0440,
|
||||
prox_light_get_dhr_sensor_info_show, NULL);
|
||||
static DEVICE_ATTR(prox_wakelock, 0220, NULL, prox_wakelock_store);
|
||||
static DEVICE_ATTR(trim_check, 0444, prox_trim_check_show, NULL);
|
||||
static DEVICE_ATTR(debug_info, 0664,
|
||||
prox_debug_info_show, prox_debug_info_store);
|
||||
static DEVICE_ATTR(touch_prox, 0220, NULL, prox_touch_prox_store);
|
||||
|
||||
static struct device_attribute *prox_attrs[] = {
|
||||
&dev_attr_vendor,
|
||||
&dev_attr_name,
|
||||
&dev_attr_state,
|
||||
&dev_attr_raw_data,
|
||||
&dev_attr_prox_led_test,
|
||||
&dev_attr_prox_avg,
|
||||
&dev_attr_prox_cal,
|
||||
&dev_attr_thresh_high,
|
||||
&dev_attr_thresh_low,
|
||||
&dev_attr_prox_offset_pass,
|
||||
&dev_attr_prox_trim,
|
||||
&dev_attr_thresh_detect_high,
|
||||
&dev_attr_thresh_detect_low,
|
||||
&dev_attr_prox_alert_thresh,
|
||||
&dev_attr_dhr_sensor_info,
|
||||
&dev_attr_register_write,
|
||||
&dev_attr_register_read,
|
||||
&dev_attr_prox_wakelock,
|
||||
&dev_attr_trim_check,
|
||||
&dev_attr_debug_info,
|
||||
&dev_attr_touch_prox,
|
||||
NULL,
|
||||
};
|
||||
|
||||
int prox_factory_init(void)
|
||||
{
|
||||
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
|
||||
adsp_factory_register(MSG_PROX, prox_attrs);
|
||||
pr_info("[SSC_FAC] %s\n", __func__);
|
||||
|
||||
hrtimer_init(&pdata->prox_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||
pdata->prox_timer.function = prox_timer_func;
|
||||
pdata->prox_wq = create_singlethread_workqueue("prox_wq");
|
||||
|
||||
/* this is the thread function we run on the work queue */
|
||||
INIT_WORK(&pdata->work_prox, prox_work_func);
|
||||
|
||||
pdata->avgwork_check = 0;
|
||||
pdata->avgtimer_enabled = 0;
|
||||
pdata->avg = 0;
|
||||
pdata->min = 0;
|
||||
pdata->max = 0;
|
||||
pdata->offset = 0;
|
||||
pdata->debug_info_cmd = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void prox_factory_exit(void)
|
||||
{
|
||||
if (pdata->avgtimer_enabled == 1) {
|
||||
hrtimer_cancel(&pdata->prox_timer);
|
||||
cancel_work_sync(&pdata->work_prox);
|
||||
}
|
||||
destroy_workqueue(pdata->prox_wq);
|
||||
adsp_factory_unregister(MSG_PROX);
|
||||
kfree(pdata);
|
||||
pr_info("[SSC_FAC] %s\n", __func__);
|
||||
}
|
1980
drivers/adsp_factory/ssc_core.c
Executable file
1980
drivers/adsp_factory/ssc_core.c
Executable file
File diff suppressed because it is too large
Load Diff
685
drivers/adsp_factory/sub2_accel.c
Executable file
685
drivers/adsp_factory/sub2_accel.c
Executable file
@@ -0,0 +1,685 @@
|
||||
/*
|
||||
* 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"
|
||||
#define VENDOR "STM"
|
||||
|
||||
#define CHIP_ID "LSM6DSVW"
|
||||
#define ACCEL_ST_TRY_CNT 3
|
||||
#define ACCEL_FACTORY_CAL_CNT 20
|
||||
#define ACCEL_RAW_DATA_CNT 3
|
||||
#define MAX_ACCEL_1G 2048
|
||||
#define PASS 0
|
||||
|
||||
#define STM_LSM6DSV_INT_CHECK_RUNNING 4
|
||||
#define STM_LSM6DSV_INT_CHECK_SKIP_IBI 5
|
||||
|
||||
struct sub2_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 sub2_accel_data *pdata;
|
||||
|
||||
static ssize_t sub2_accel_vendor_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", VENDOR);
|
||||
}
|
||||
|
||||
static ssize_t sub2_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_sub2_accel_cal_data(struct adsp_data *data, int32_t *cal_data)
|
||||
{
|
||||
uint8_t cnt = 0;
|
||||
|
||||
adsp_unicast(NULL, 0, MSG_ACCEL_SUB2, 0, MSG_TYPE_GET_CAL_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_CAL_DATA] & 1 << MSG_ACCEL_SUB2) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_CAL_DATA] &= ~(1 << MSG_ACCEL_SUB2);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (data->msg_buf[MSG_ACCEL_SUB2][3] != ACCEL_RAW_DATA_CNT) {
|
||||
pr_err("[FACTORY] %s: Reading Bytes Num %d!!!\n",
|
||||
__func__, data->msg_buf[MSG_ACCEL_SUB2][3]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cal_data[0] = data->msg_buf[MSG_ACCEL_SUB2][0];
|
||||
cal_data[1] = data->msg_buf[MSG_ACCEL_SUB2][1];
|
||||
cal_data[2] = data->msg_buf[MSG_ACCEL_SUB2][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_SUB2][3]);
|
||||
|
||||
return data->msg_buf[MSG_ACCEL_SUB2][3];
|
||||
}
|
||||
|
||||
void set_sub2_accel_cal_data(struct adsp_data *data)
|
||||
{
|
||||
uint8_t cnt = 0;
|
||||
|
||||
pr_info("[FACTORY] %s(1): %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_SUB2, 0, MSG_TYPE_SET_CAL_DATA);
|
||||
pr_info("[FACTORY] %s(2): %d, %d, %d\n", __func__, pdata->avg_data[0],
|
||||
pdata->avg_data[1], pdata->avg_data[2]);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_SET_CAL_DATA] & 1 << MSG_ACCEL_SUB2) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_SET_CAL_DATA] &= ~(1 << MSG_ACCEL_SUB2);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
} else if (data->msg_buf[MSG_ACCEL_SUB2][0] != ACCEL_RAW_DATA_CNT) {
|
||||
pr_err("[FACTORY] %s: Write Bytes Num %d!!!\n",
|
||||
__func__, data->msg_buf[MSG_ACCEL_SUB2][0]);
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t sub2_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_sub2_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_sub2_accel_cal_data fail\n", __func__);
|
||||
return snprintf(buf, PAGE_SIZE, "%d,%d,%d,%d\n", 0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t sub2_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_sub2_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_sub2_accel_cal_data(data);
|
||||
mutex_unlock(&data->accel_factory_mutex);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static void sub2_accel_work_func(struct work_struct *work)
|
||||
{
|
||||
struct sub2_accel_data *data = container_of((struct work_struct *)work,
|
||||
struct sub2_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_SUB2, 0, MSG_TYPE_SET_CAL_DATA);
|
||||
msleep(30); /* for init of bias */
|
||||
for (i = 0; i < ACCEL_FACTORY_CAL_CNT; i++) {
|
||||
msleep(20);
|
||||
get_sub2_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 sub2_accel_cal_work_func(struct work_struct *work)
|
||||
{
|
||||
struct adsp_data *data = container_of((struct delayed_work *)work,
|
||||
struct adsp_data, sub2_accel_cal_work);
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&data->accel_factory_mutex);
|
||||
ret = get_sub2_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_sub2_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 sub2_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 0 //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_SUB2, 0, MSG_TYPE_ST_SHOW_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_ST_SHOW_DATA] & 1 << MSG_ACCEL_SUB2) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
msleep(26);
|
||||
|
||||
data->ready_flag[MSG_TYPE_ST_SHOW_DATA] &= ~(1 << MSG_ACCEL_SUB2);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
data->msg_buf[MSG_ACCEL_SUB2][1] = -1;
|
||||
#ifdef CONFIG_SEC_FACTORY
|
||||
panic("sensor force crash : sub2 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_SUB2][0],
|
||||
data->msg_buf[MSG_ACCEL_SUB2][1], data->msg_buf[MSG_ACCEL_SUB2][2],
|
||||
data->msg_buf[MSG_ACCEL_SUB2][3], data->msg_buf[MSG_ACCEL_SUB2][4],
|
||||
data->msg_buf[MSG_ACCEL_SUB2][5], data->msg_buf[MSG_ACCEL_SUB2][6],
|
||||
data->msg_buf[MSG_ACCEL_SUB2][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_SUB2][8],
|
||||
data->msg_buf[MSG_ACCEL_SUB2][9], data->msg_buf[MSG_ACCEL_SUB2][10],
|
||||
data->msg_buf[MSG_ACCEL_SUB2][11], data->msg_buf[MSG_ACCEL_SUB2][12],
|
||||
data->msg_buf[MSG_ACCEL_SUB2][13], data->msg_buf[MSG_ACCEL_SUB2][14],
|
||||
data->msg_buf[MSG_ACCEL_SUB2][15], data->msg_buf[MSG_ACCEL_SUB2][16],
|
||||
data->msg_buf[MSG_ACCEL_SUB2][17], data->msg_buf[MSG_ACCEL_SUB2][18],
|
||||
data->msg_buf[MSG_ACCEL_SUB2][19]);
|
||||
|
||||
if (data->msg_buf[MSG_ACCEL_SUB2][1] == 1) {
|
||||
pr_info("[FACTORY] %s : Pass - result = %d, retry = %d\n",
|
||||
__func__, data->msg_buf[MSG_ACCEL_SUB2][1], retry);
|
||||
} else {
|
||||
data->msg_buf[MSG_ACCEL_SUB2][1] = -5;
|
||||
pr_err("[FACTORY] %s : Fail - result = %d, retry = %d\n",
|
||||
__func__, data->msg_buf[MSG_ACCEL_SUB2][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 0 //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_SUB2][1],
|
||||
(int)abs(data->msg_buf[MSG_ACCEL_SUB2][2]),
|
||||
(int)abs(data->msg_buf[MSG_ACCEL_SUB2][3]),
|
||||
(int)abs(data->msg_buf[MSG_ACCEL_SUB2][4]),
|
||||
(int)abs(data->msg_buf[MSG_ACCEL_SUB2][5]),
|
||||
(int)abs(data->msg_buf[MSG_ACCEL_SUB2][6]),
|
||||
(int)abs(data->msg_buf[MSG_ACCEL_SUB2][7]));
|
||||
}
|
||||
|
||||
static ssize_t sub2_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;
|
||||
#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_sub2_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 : sub2 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 sub2_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_SUB2,
|
||||
0, MSG_TYPE_GET_REGISTER);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_REGISTER] & 1 << MSG_ACCEL_SUB2) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_REGISTER] &= ~(1 << MSG_ACCEL_SUB2);
|
||||
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_SUB2][0]);
|
||||
|
||||
if (data->msg_buf[MSG_ACCEL_SUB2][0] == 0)
|
||||
success = true;
|
||||
|
||||
if (data->msg_buf[MSG_ACCEL_SUB2][0] == STM_LSM6DSV_INT_CHECK_SKIP_IBI) {
|
||||
pr_info("[FACTORY]: %s - IBI mode. Ignore Interrupt Check Test\n", __func__);
|
||||
success = true;
|
||||
}
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", (int)success);
|
||||
}
|
||||
|
||||
static ssize_t sub2_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_SUB2,
|
||||
0, MSG_TYPE_GET_REGISTER);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_REGISTER] & 1 << MSG_ACCEL_SUB2) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_REGISTER] &= ~(1 << MSG_ACCEL_SUB2);
|
||||
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_SUB2][0] == STM_LSM6DSV_INT_CHECK_RUNNING)
|
||||
pr_info("[FACTORY]: %s - STM_LSM6DSV_INT_CHECK_RUNNING\n", __func__);
|
||||
else if (data->msg_buf[MSG_ACCEL_SUB2][0] == STM_LSM6DSV_INT_CHECK_SKIP_IBI)
|
||||
pr_info("[FACTORY]: %s - IBI mode. Ignore Interrupt Check Test\n", __func__);
|
||||
else
|
||||
pr_info("[FACTORY]: %s - Something wrong\n", __func__);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t sub2_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;
|
||||
} else if (sysfs_streq(buf, "0")) {
|
||||
msg_buf = 0;
|
||||
#ifdef CONFIG_SEC_FACTORY
|
||||
} else if (sysfs_streq(buf, "2")) {
|
||||
msg_buf = 2;
|
||||
pr_info("[FACTORY] %s: Pretest\n", __func__);
|
||||
#endif
|
||||
} else {
|
||||
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_SUB2,
|
||||
0, MSG_TYPE_SET_ACCEL_LPF);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_SET_ACCEL_LPF] & 1 << MSG_ACCEL_SUB2) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_SET_ACCEL_LPF] &= ~(1 << MSG_ACCEL_SUB2);
|
||||
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_SUB2][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_SUB2][0], data->msg_buf[MSG_ACCEL_SUB2][1],
|
||||
data->msg_buf[MSG_ACCEL_SUB2][2], data->msg_buf[MSG_ACCEL_SUB2][3]);
|
||||
#else
|
||||
pr_info("[FACTORY] %s: %d, 0x0A:%02x 0x0D:%02x 0x10:%02x\n", __func__,
|
||||
data->msg_buf[MSG_ACCEL_SUB2][0], data->msg_buf[MSG_ACCEL_SUB2][1],
|
||||
data->msg_buf[MSG_ACCEL_SUB2][2], data->msg_buf[MSG_ACCEL_SUB2][3]);
|
||||
#endif
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t sub2_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_SUB2, 0, MSG_TYPE_GET_DHR_INFO);
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_DHR_INFO] & 1 << MSG_ACCEL_SUB2) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(500, 550);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_DHR_INFO] &= ~(1 << MSG_ACCEL_SUB2);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT)
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
|
||||
ctrl1_xl = data->msg_buf[MSG_ACCEL_SUB2][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);
|
||||
}
|
||||
|
||||
#if 0 //IS_ENABLED(CONFIG_SUPPORT_REF_ANGLE_WITHOUT_DIGITAL_HALL) || defined(CONFIG_SUPPORT_REF_ANGLE_WITHOUT_DIGITAL_HALL)
|
||||
static ssize_t ref_angle_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
uint8_t cnt = 0;
|
||||
int32_t result = PASS;
|
||||
|
||||
mutex_lock(&data->accel_factory_mutex);
|
||||
adsp_unicast(NULL, 0, MSG_REF_ANGLE, 0, MSG_TYPE_GET_RAW_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_RAW_DATA] & 1 << MSG_REF_ANGLE) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
msleep(20);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_RAW_DATA] &= ~(1 << MSG_REF_ANGLE);
|
||||
mutex_unlock(&data->accel_factory_mutex);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
return snprintf(buf, PAGE_SIZE, "-1\n");
|
||||
}
|
||||
|
||||
pr_info("[FACTORY] %s - st %d/%d, akm %d/%d, lf %d/%d, hall %d/%d/%d(uT)\n",
|
||||
__func__, data->msg_buf[MSG_REF_ANGLE][0],
|
||||
data->msg_buf[MSG_REF_ANGLE][1],
|
||||
data->msg_buf[MSG_REF_ANGLE][2],
|
||||
data->msg_buf[MSG_REF_ANGLE][3],
|
||||
data->msg_buf[MSG_REF_ANGLE][4],
|
||||
data->msg_buf[MSG_REF_ANGLE][5],
|
||||
data->msg_buf[MSG_REF_ANGLE][6],
|
||||
data->msg_buf[MSG_REF_ANGLE][7],
|
||||
data->msg_buf[MSG_REF_ANGLE][8]);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d,%d\n",
|
||||
data->msg_buf[MSG_REF_ANGLE][0], result);
|
||||
}
|
||||
|
||||
static ssize_t angle_read_data_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
uint8_t cnt = 0;
|
||||
|
||||
mutex_lock(&data->accel_factory_mutex);
|
||||
adsp_unicast(NULL, 0, MSG_REF_ANGLE, 0, MSG_TYPE_GET_RAW_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_RAW_DATA] & 1 << MSG_REF_ANGLE) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
msleep(20);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_RAW_DATA] &= ~(1 << MSG_REF_ANGLE);
|
||||
mutex_unlock(&data->accel_factory_mutex);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
return snprintf(buf, PAGE_SIZE, "-1\n");
|
||||
}
|
||||
|
||||
pr_info("[FACTORY] %s - st %d/%d, akm %d/%d, lf %d/%d, hall %d/%d/%d(uT)\n",
|
||||
__func__, data->msg_buf[MSG_REF_ANGLE][0],
|
||||
data->msg_buf[MSG_REF_ANGLE][1],
|
||||
data->msg_buf[MSG_REF_ANGLE][2],
|
||||
data->msg_buf[MSG_REF_ANGLE][3],
|
||||
data->msg_buf[MSG_REF_ANGLE][4],
|
||||
data->msg_buf[MSG_REF_ANGLE][5],
|
||||
data->msg_buf[MSG_REF_ANGLE][6],
|
||||
data->msg_buf[MSG_REF_ANGLE][7],
|
||||
data->msg_buf[MSG_REF_ANGLE][8]);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
|
||||
data->msg_buf[MSG_REF_ANGLE][0],
|
||||
data->msg_buf[MSG_REF_ANGLE][1],
|
||||
data->msg_buf[MSG_REF_ANGLE][2],
|
||||
data->msg_buf[MSG_REF_ANGLE][3],
|
||||
data->msg_buf[MSG_REF_ANGLE][4],
|
||||
data->msg_buf[MSG_REF_ANGLE][5],
|
||||
data->msg_buf[MSG_REF_ANGLE][6],
|
||||
data->msg_buf[MSG_REF_ANGLE][7],
|
||||
data->msg_buf[MSG_REF_ANGLE][8]);
|
||||
}
|
||||
#endif
|
||||
|
||||
static DEVICE_ATTR(name, 0444, sub2_accel_name_show, NULL);
|
||||
static DEVICE_ATTR(vendor, 0444, sub2_accel_vendor_show, NULL);
|
||||
static DEVICE_ATTR(type, 0444, sensor_type_show, NULL);
|
||||
static DEVICE_ATTR(calibration, 0664,
|
||||
sub2_accel_calibration_show, sub2_accel_calibration_store);
|
||||
static DEVICE_ATTR(selftest, 0440,
|
||||
sub2_accel_selftest_show, NULL);
|
||||
static DEVICE_ATTR(raw_data, 0444, sub2_accel_raw_data_show, NULL);
|
||||
static DEVICE_ATTR(reactive_alert, 0664,
|
||||
sub2_accel_reactive_show, sub2_accel_reactive_store);
|
||||
static DEVICE_ATTR(lowpassfilter, 0220,
|
||||
NULL, sub2_accel_lowpassfilter_store);
|
||||
#ifdef CONFIG_SEC_FACTORY
|
||||
static DEVICE_ATTR(dhr_sensor_info, 0444,
|
||||
sub2_accel_dhr_sensor_info_show, NULL);
|
||||
#else
|
||||
static DEVICE_ATTR(dhr_sensor_info, 0440,
|
||||
sub2_accel_dhr_sensor_info_show, NULL);
|
||||
#endif
|
||||
#if 0 //IS_ENABLED(CONFIG_SUPPORT_REF_ANGLE_WITHOUT_DIGITAL_HALL) || defined(CONFIG_SUPPORT_REF_ANGLE_WITHOUT_DIGITAL_HALL)
|
||||
static DEVICE_ATTR(ref_angle, 0444, ref_angle_show, NULL);
|
||||
static DEVICE_ATTR(read_angle_data, 0444, angle_read_data_show, NULL);
|
||||
#endif
|
||||
|
||||
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,
|
||||
#if 0 //IS_ENABLED(CONFIG_SUPPORT_REF_ANGLE_WITHOUT_DIGITAL_HALL) || defined(CONFIG_SUPPORT_REF_ANGLE_WITHOUT_DIGITAL_HALL)
|
||||
&dev_attr_ref_angle,
|
||||
&dev_attr_read_angle_data,
|
||||
#endif
|
||||
NULL,
|
||||
};
|
||||
|
||||
void sub2_accel_factory_init_work(struct adsp_data *data)
|
||||
{
|
||||
schedule_delayed_work(&data->sub2_accel_cal_work, msecs_to_jiffies(8000));
|
||||
}
|
||||
|
||||
int __init sub2_accel_factory_init(void)
|
||||
{
|
||||
adsp_factory_register(MSG_ACCEL_SUB2, acc_attrs);
|
||||
|
||||
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
|
||||
pdata->accel_wq = create_singlethread_workqueue("sub2_accel_wq");
|
||||
INIT_WORK(&pdata->work_accel, sub2_accel_work_func);
|
||||
|
||||
pdata->lpf_onoff = true;
|
||||
pdata->st_complete = true;
|
||||
pr_info("[FACTORY] %s\n", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __exit sub2_accel_factory_exit(void)
|
||||
{
|
||||
adsp_factory_unregister(MSG_ACCEL_SUB2);
|
||||
pr_info("[FACTORY] %s\n", __func__);
|
||||
}
|
211
drivers/adsp_factory/sub2_gyro.c
Executable file
211
drivers/adsp_factory/sub2_gyro.c
Executable file
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
* 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"
|
||||
#define VENDOR "STM"
|
||||
#define CHIP_ID "LSM6DSVW"
|
||||
#define ST_PASS 1
|
||||
#define ST_FAIL 0
|
||||
#define STARTUP_BIT_FAIL 2
|
||||
#define G_ZRL_DELTA_FAIL 4
|
||||
#define SFLP_FAIL 6
|
||||
#define SELFTEST_REVISED 1
|
||||
|
||||
static ssize_t sub2_gyro_vendor_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", VENDOR);
|
||||
}
|
||||
|
||||
static ssize_t sub2_gyro_name_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", CHIP_ID);
|
||||
}
|
||||
|
||||
static ssize_t selftest_revised_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", SELFTEST_REVISED);
|
||||
}
|
||||
|
||||
static ssize_t gyro_power_off(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
pr_info("[FACTORY]: %s\n", __func__);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", 1);
|
||||
}
|
||||
|
||||
static ssize_t gyro_power_on(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
pr_info("[FACTORY]: %s\n", __func__);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", 1);
|
||||
}
|
||||
|
||||
static ssize_t sub2_gyro_temp_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
uint8_t cnt = 0;
|
||||
|
||||
adsp_unicast(NULL, 0, MSG_GYRO_SUB2_TEMP, 0, MSG_TYPE_GET_RAW_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_GET_RAW_DATA] & 1 << MSG_GYRO_SUB2_TEMP)
|
||||
&& cnt++ < TIMEOUT_CNT)
|
||||
msleep(20);
|
||||
|
||||
data->ready_flag[MSG_TYPE_GET_RAW_DATA] &= ~(1 << MSG_GYRO_SUB2_TEMP);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
return snprintf(buf, PAGE_SIZE, "-99\n");
|
||||
}
|
||||
|
||||
pr_info("[FACTORY] %s: sub2_gyro_temp = %d\n", __func__,
|
||||
data->msg_buf[MSG_GYRO_SUB2_TEMP][0]);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||
data->msg_buf[MSG_GYRO_SUB2_TEMP][0]);
|
||||
}
|
||||
|
||||
static ssize_t sub2_gyro_selftest_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adsp_data *data = dev_get_drvdata(dev);
|
||||
uint8_t cnt = 0;
|
||||
int st_diff_res = ST_FAIL;
|
||||
int st_zro_res = ST_FAIL;
|
||||
#if 0 //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
|
||||
|
||||
pr_info("[FACTORY] %s - start", __func__);
|
||||
adsp_unicast(NULL, 0, MSG_GYRO_SUB2, 0, MSG_TYPE_ST_SHOW_DATA);
|
||||
|
||||
while (!(data->ready_flag[MSG_TYPE_ST_SHOW_DATA] & 1 << MSG_GYRO_SUB2) &&
|
||||
cnt++ < TIMEOUT_CNT)
|
||||
usleep_range(30000, 30100); /* 30 * 200 = 6 sec */
|
||||
|
||||
data->ready_flag[MSG_TYPE_ST_SHOW_DATA] &= ~(1 << MSG_GYRO_SUB2);
|
||||
|
||||
if (cnt >= TIMEOUT_CNT) {
|
||||
pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
|
||||
#if 0 //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,
|
||||
"0,0,0,0,0,0,0,0,0,0,0,0,%d,%d\n",
|
||||
ST_FAIL, ST_FAIL);
|
||||
}
|
||||
|
||||
if (data->msg_buf[MSG_GYRO_SUB2][1] != 0) {
|
||||
pr_info("[FACTORY] %s - failed(%d, %d)\n", __func__,
|
||||
data->msg_buf[MSG_GYRO_SUB2][1],
|
||||
data->msg_buf[MSG_GYRO_SUB2][5]);
|
||||
|
||||
pr_info("[FACTORY]: %s - %d,%d,%d\n", __func__,
|
||||
data->msg_buf[MSG_GYRO_SUB2][2],
|
||||
data->msg_buf[MSG_GYRO_SUB2][3],
|
||||
data->msg_buf[MSG_GYRO_SUB2][4]);
|
||||
|
||||
#if 0 //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
|
||||
|
||||
if (data->msg_buf[MSG_GYRO_SUB2][5] == G_ZRL_DELTA_FAIL)
|
||||
pr_info("[FACTORY] %s - ZRL Delta fail\n", __func__);
|
||||
return snprintf(buf, PAGE_SIZE, "%d,%d,%d\n",
|
||||
data->msg_buf[MSG_GYRO_SUB2][2],
|
||||
data->msg_buf[MSG_GYRO_SUB2][3],
|
||||
data->msg_buf[MSG_GYRO_SUB2][4]);
|
||||
} else {
|
||||
st_zro_res = ST_PASS;
|
||||
}
|
||||
|
||||
if (!data->msg_buf[MSG_GYRO_SUB2][5])
|
||||
st_diff_res = ST_PASS;
|
||||
else if (data->msg_buf[MSG_GYRO_SUB2][5] == STARTUP_BIT_FAIL)
|
||||
pr_info("[FACTORY] %s - Gyro Start Up Bit fail\n", __func__);
|
||||
else if (data->msg_buf[MSG_GYRO_SUB2][5] == SFLP_FAIL) {
|
||||
pr_info("[FACTORY] %s - SFLP sanity test fail\n", __func__);
|
||||
st_diff_res = SFLP_FAIL;
|
||||
}
|
||||
|
||||
pr_info("[FACTORY]: %s - %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
|
||||
__func__,
|
||||
data->msg_buf[MSG_GYRO_SUB2][2], data->msg_buf[MSG_GYRO_SUB2][3],
|
||||
data->msg_buf[MSG_GYRO_SUB2][4], data->msg_buf[MSG_GYRO_SUB2][6],
|
||||
data->msg_buf[MSG_GYRO_SUB2][7], data->msg_buf[MSG_GYRO_SUB2][8],
|
||||
data->msg_buf[MSG_GYRO_SUB2][9], data->msg_buf[MSG_GYRO_SUB2][10],
|
||||
data->msg_buf[MSG_GYRO_SUB2][11], data->msg_buf[MSG_GYRO_SUB2][12],
|
||||
data->msg_buf[MSG_GYRO_SUB2][13], data->msg_buf[MSG_GYRO_SUB2][14],
|
||||
st_diff_res, st_zro_res);
|
||||
|
||||
#if 0 //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,%d,%d,%d,%d,%d,%d,%d\n",
|
||||
data->msg_buf[MSG_GYRO_SUB2][2], data->msg_buf[MSG_GYRO_SUB2][3],
|
||||
data->msg_buf[MSG_GYRO_SUB2][4], data->msg_buf[MSG_GYRO_SUB2][6],
|
||||
data->msg_buf[MSG_GYRO_SUB2][7], data->msg_buf[MSG_GYRO_SUB2][8],
|
||||
data->msg_buf[MSG_GYRO_SUB2][9], data->msg_buf[MSG_GYRO_SUB2][10],
|
||||
data->msg_buf[MSG_GYRO_SUB2][11], data->msg_buf[MSG_GYRO_SUB2][12],
|
||||
data->msg_buf[MSG_GYRO_SUB2][13], data->msg_buf[MSG_GYRO_SUB2][14],
|
||||
st_diff_res, st_zro_res);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(name, 0444, sub2_gyro_name_show, NULL);
|
||||
static DEVICE_ATTR(vendor, 0444, sub2_gyro_vendor_show, NULL);
|
||||
static DEVICE_ATTR(selftest, 0440, sub2_gyro_selftest_show, NULL);
|
||||
static DEVICE_ATTR(power_on, 0444, gyro_power_on, NULL);
|
||||
static DEVICE_ATTR(power_off, 0444, gyro_power_off, NULL);
|
||||
static DEVICE_ATTR(temperature, 0440, sub2_gyro_temp_show, NULL);
|
||||
static DEVICE_ATTR(selftest_revised, 0440, selftest_revised_show, NULL);
|
||||
|
||||
static struct device_attribute *gyro_attrs[] = {
|
||||
&dev_attr_name,
|
||||
&dev_attr_vendor,
|
||||
&dev_attr_selftest,
|
||||
&dev_attr_power_on,
|
||||
&dev_attr_power_off,
|
||||
&dev_attr_temperature,
|
||||
&dev_attr_selftest_revised,
|
||||
NULL,
|
||||
};
|
||||
|
||||
int __init sub2_gyro_factory_init(void)
|
||||
{
|
||||
adsp_factory_register(MSG_GYRO_SUB2, gyro_attrs);
|
||||
|
||||
pr_info("[FACTORY] %s\n", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __exit sub2_gyro_factory_exit(void)
|
||||
{
|
||||
adsp_factory_unregister(MSG_GYRO_SUB2);
|
||||
|
||||
pr_info("[FACTORY] %s\n", __func__);
|
||||
}
|
Reference in New Issue
Block a user