Last active
December 30, 2022 16:36
-
-
Save sourajitk/b27ae962638c21f62485fe4fba4fbed2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
commit a2d3da571019990e7c442652dd76651e59e867ad | |
Author: Sourajit Karmakar <sourajitk@statixos.com> | |
Date: Fri Dec 30 11:34:59 2022 -0500 | |
drivers/input: misc: Import qcom-hv-haptic changes for AI2202 | |
diff --git a/drivers/input/misc/qcom-hv-haptics.c b/drivers/input/misc/qcom-hv-haptics.c | |
index 8262c3c5f383..4f19a71f1aa0 100644 | |
--- a/drivers/input/misc/qcom-hv-haptics.c | |
+++ b/drivers/input/misc/qcom-hv-haptics.c | |
@@ -18,60 +18,47 @@ | |
#include <linux/nvmem-consumer.h> | |
#include <linux/of.h> | |
#include <linux/of_address.h> | |
-#include <linux/of_device.h> | |
#include <linux/platform_device.h> | |
#include <linux/regmap.h> | |
#include <linux/regulator/driver.h> | |
#include <linux/slab.h> | |
-#include <linux/suspend.h> | |
#include <linux/types.h> | |
#include <linux/uaccess.h> | |
#include <linux/qpnp/qpnp-pbs.h> | |
-#include <linux/soc/qcom/battery_charger.h> | |
- | |
-#define CREATE_TRACE_POINTS | |
-#include <trace/events/qcom_haptics.h> | |
- | |
/* status register definitions in HAPTICS_CFG module */ | |
-#define HAP_CFG_REVISION1_REG 0x00 | |
+#define HAP_CFG_REVISION2_REG 0x01 | |
#define HAP_CFG_V1 0x1 | |
#define HAP_CFG_V2 0x2 | |
-#define HAP_CFG_V3 0x3 | |
-#define HAP_CFG_V4 0x4 | |
#define HAP_CFG_STATUS_DATA_MSB_REG 0x09 | |
/* STATUS_DATA_MSB definitions while MOD_STATUS_SEL is 0 */ | |
#define AUTO_RES_CAL_DONE_BIT BIT(5) | |
#define CAL_TLRA_CL_STS_MSB_MASK GENMASK(4, 0) | |
-/* STATUS_DATA_MSB definition while MOD_STATUS_SEL is 3 */ | |
-#define LAST_GOOD_TLRA_CL_MSB_MASK GENMASK(4, 0) | |
-/* STATUS_DATA_MSB definition while MOD_STATUS_SEL is 4 */ | |
+/* STATUS_DATA_MSB definition in V2 while MOD_STATUS_SEL is 3 */ | |
+#define LAST_GOOD_TLRA_CL_MSB_MASK GENMASK(4, 0) | |
+/* STATUS_DATA_MSB definition in V2 while MOD_STATUS_SEL is 4 */ | |
#define TLRA_CL_ERR_MSB_MASK GENMASK(4, 0) | |
-/* STATUS_DATA_MSB when MOD_STATUS_SEL is 5 and MOD_STATUS_XT.SEL is 1 */ | |
+/* STATUS_DATA_MSB definition in V1 while MOD_STATUS_SEL is 5 */ | |
+#define FIFO_REAL_TIME_FILL_STATUS_MASK_V1 GENMASK(6, 0) | |
+/* STATUS_DATA_MSB in V2 when MOD_STATUS_SEL is 5 and MOD_STATUS_XT.SEL is 1 */ | |
#define FIFO_REAL_TIME_FILL_STATUS_MSB_MASK_V2 GENMASK(1, 0) | |
-#define FIFO_REAL_TIME_FILL_STATUS_MSB_MASK_V3 GENMASK(2, 0) | |
-#define FIFO_REAL_TIME_FILL_STATUS_MSB_MASK_V4 GENMASK(3, 0) | |
-#define FIFO_EMPTY_FLAG_BIT BIT(6) | |
-#define FIFO_FULL_FLAG_BIT BIT(5) | |
+#define FIFO_EMPTY_FLAG_BIT_V2 BIT(6) | |
+#define FIFO_FULL_FLAG_BIT_V2 BIT(5) | |
#define HAP_CFG_STATUS_DATA_LSB_REG 0x0A | |
-/* STATUS_DATA_LSB definition while MOD_STATUS_SEL is 0 */ | |
+/* STATUS_DATA_MSB definition while MOD_STATUS_SEL is 0 */ | |
#define CAL_TLRA_CL_STS_LSB_MASK GENMASK(7, 0) | |
-/* STATUS_DATA_LSB when MOD_STATUS_SEL is 5 and MOD_STATUS_XT.SEL is 1 */ | |
-#define FIFO_REAL_TIME_FILL_STATUS_LSB_MASK GENMASK(7, 0) | |
-/* STATUS_DATA_LSB when MOD_STATUS_SEL is 5 and MOD_STATUS_XT.SEL is 0 */ | |
-#define HAP_DRV_PATTERN_SRC_STATUS_MASK GENMASK(2, 0) | |
+/* STATUS_DATA_LSB in V2 when MOD_STATUS_SEL is 5 and MOD_STATUS_XT.SEL is 1 */ | |
+#define FIFO_REAL_TIME_FILL_STATUS_LSB_MASK_V2 GENMASK(7, 0) | |
+/* STATUS_DATA_LSB in V2 when MOD_STATUS_SEL is 5 and MOD_STATUS_XT.SEL is 0 */ | |
+#define HAP_DRV_PATTERN_SRC_STATUS_MASK_V2 GENMASK(2, 0) | |
#define HAP_CFG_FAULT_STATUS_REG 0x0C | |
#define SC_FLAG_BIT BIT(2) | |
#define AUTO_RES_ERROR_BIT BIT(1) | |
#define HPRW_RDY_FAULT_BIT BIT(0) | |
-/* Only for HAP525_HV */ | |
-#define HAP_CFG_REAL_TIME_LRA_IMPEDANCE_REG 0x0E | |
-#define LRA_IMPEDANCE_MOHMS_LSB 250 | |
- | |
#define HAP_CFG_INT_RT_STS_REG 0x10 | |
#define FIFO_EMPTY_BIT BIT(1) | |
@@ -84,11 +71,8 @@ | |
#define DRV_SLEW_RATE_MASK GENMASK(2, 0) | |
#define HAP_CFG_VMAX_REG 0x48 | |
-#define VMAX_HV_STEP_MV 50 | |
-#define VMAX_MV_STEP_MV 32 | |
+#define VMAX_STEP_MV 50 | |
#define MAX_VMAX_MV 11000 | |
-#define MAX_HV_VMAX_MV 10000 | |
-#define MAX_MV_VMAX_MV 6000 | |
#define CLAMPED_VMAX_MV 5000 | |
#define DEFAULT_VMAX_MV 5000 | |
@@ -103,7 +87,6 @@ | |
#define HAP_CFG_SPMI_PLAY_REG 0x4C | |
#define PLAY_EN_BIT BIT(7) | |
-#define PATX_MEM_SEL_MASK GENMASK(5, 4) /* This is only for HAP525_HV */ | |
#define BRAKE_EN_BIT BIT(3) | |
#define PAT_SRC_MASK GENMASK(2, 0) | |
@@ -160,15 +143,6 @@ | |
#define EN_HW_RECOVERY_BIT BIT(1) | |
#define SW_ERR_DRV_FREQ_BIT BIT(0) | |
-#define HAP_CFG_ISC_CFG_REG 0x65 | |
-#define ILIM_CC_EN_BIT BIT(7) | |
-/* Following bits are only for HAP525_HV */ | |
-#define EN_SC_DET_P_HAP525_HV_BIT BIT(6) | |
-#define EN_SC_DET_N_HAP525_HV_BIT BIT(5) | |
-#define EN_IMP_DET_HAP525_HV_BIT BIT(4) | |
-#define ILIM_PULSE_DENSITY_MASK GENMASK(3, 2) | |
-#define ILIM_DENSITY_8_OVER_64_CYCLES 0 | |
- | |
#define HAP_CFG_FAULT_CLR_REG 0x66 | |
#define SC_CLR_BIT BIT(2) | |
#define AUTO_RES_ERR_CLR_BIT BIT(1) | |
@@ -180,11 +154,18 @@ | |
#define VMAX_HDRM_MAX_MV 6350 | |
#define HAP_CFG_VSET_CFG_REG 0x68 | |
-#define FORCE_VSET_ACK_BIT BIT(1) /* This is only for HAP525_HV */ | |
#define FORCE_VREG_RDY_BIT BIT(0) | |
#define HAP_CFG_MOD_STATUS_SEL_REG 0x70 | |
-#define HAP_CFG_MOD_STATUS_XT_REG 0x71 | |
+#define MOD_STATUS_SEL_CAL_TLRA_CL_STS_VAL 0 | |
+#define MOD_STATUS_SEL_LAST_GOOD_TLRA_VAL 3 | |
+#define MOD_STATUS_SEL_TLRA_CL_ERR_STS_VAL 4 | |
+#define MOD_STATUS_SEL_FIFO_FILL_STATUS_VAL 5 | |
+#define MOD_STATUS_SEL_BRAKE_CAL_RNAT_RCAL_VAL 6 | |
+ | |
+#define HAP_CFG_MOD_STATUS_XT_V2_REG 0x71 | |
+#define MOD_STATUS_XT_V2_FIFO_FILL_STATUS_VAL 0x80 | |
+#define MOD_STATUS_XT_SEL_LAST_GOOD_TLRA_VAL 0 | |
#define HAP_CFG_CAL_EN_REG 0x72 | |
#define CAL_RC_CLK_MASK GENMASK(3, 2) | |
@@ -193,41 +174,10 @@ | |
#define CAL_RC_CLK_AUTO_VAL 1 | |
#define CAL_RC_CLK_MANUAL_VAL 2 | |
-/* For HAP520_MV and HAP525_HV */ | |
-#define HAP_CFG_ISC_CFG2_REG 0x77 | |
-#define EN_SC_DET_P_HAP520_MV_BIT BIT(6) | |
-#define EN_SC_DET_N_HAP520_MV_BIT BIT(5) | |
-#define ISC_THRESH_HAP520_MV_MASK GENMASK(2, 0) | |
-#define ISC_THRESH_HAP520_MV_140MA 0x01 | |
-#define ISC_THRESH_HAP525_HV_MASK GENMASK(4, 0) | |
-#define ISC_THRESH_HAP525_HV_125MA 0x11 | |
-#define ISC_THRESH_HAP525_HV_250MA 0x12 | |
- | |
-/* These registers are only applicable for HAP520_MV */ | |
-#define HAP_CFG_HW_CONFIG_REG 0x0D | |
-#define HV_HAP_DRIVER_BIT BIT(1) | |
- | |
-#define HAP_CFG_HPWR_INTF_CTL_REG 0x80 | |
-#define INTF_CTL_MASK GENMASK(1, 0) | |
-#define INTF_CTL_BOB 1 | |
-#define INTF_CTL_BHARGER 2 | |
- | |
-#define HAP_CFG_VHPWR_REG 0x84 | |
-#define VHPWR_STEP_MV 32 | |
- | |
-/* Only for HAP525_HV */ | |
-#define HAP_CFG_RT_LRA_IMPD_MEAS_CFG_REG 0xA4 | |
-#define LRA_IMPEDANCE_MEAS_EN_BIT BIT(7) | |
-#define LRA_IMPEDANCE_MEAS_CURRENT_SEL_BIT BIT(0) | |
-#define CURRENT_SEL_VAL_125MA 0 | |
-#define CURRENT_SEL_VAL_250MA 1 | |
- | |
/* version register definitions for HAPTICS_PATTERN module */ | |
#define HAP_PTN_REVISION2_REG 0x01 | |
#define HAP_PTN_V1 0x1 | |
#define HAP_PTN_V2 0x2 | |
-#define HAP_PTN_V3 0x3 | |
-#define HAP_PTN_V4 0x4 | |
/* status register definition for HAPTICS_PATTERN module */ | |
#define HAP_PTN_FIFO_READY_STS_REG 0x08 | |
@@ -236,20 +186,32 @@ | |
#define HAP_PTN_NUM_PAT_REG 0x09 | |
/* config register definition for HAPTICS_PATTERN module */ | |
-#define HAP_PTN_FIFO_DIN_0_REG 0x20 | |
-#define HAP_PTN_FIFO_DIN_NUM 4 | |
+/* FIFO configuration registers in V1 chip */ | |
+#define HAP_PTN_V1_FIFO_DIN_MSB_REG 0x20 | |
+#define HAP_PTN_V1_FIFO_DIN_MSB_BIT BIT(0) | |
+#define HAP_PTN_V1_FIFO_DIN_LSB_REG 0x21 | |
+#define HAP_PTN_V1_FIFO_DIN_LSB_MASK GENMASK(7, 0) | |
-#define HAP_PTN_FIFO_PLAY_RATE_REG 0x24 | |
-#define PAT_MEM_PLAY_RATE_MASK GENMASK(7, 4) | |
+#define HAP_PTN_V1_FIFO_PLAY_RATE_REG 0x22 | |
#define FIFO_PLAY_RATE_MASK GENMASK(3, 0) | |
-#define HAP_PTN_FIFO_EMPTY_CFG_REG 0x2A | |
+#define HAP_PTN_V1_FIFO_EMPTY_CFG_REG 0x23 | |
#define EMPTY_THRESH_MASK GENMASK(3, 0) | |
-#define HAP_PTN_FIFO_THRESH_LSB 40 | |
+#define HAP_PTN_V1_FIFO_THRESH_LSB 4 | |
+ | |
+#define HAP_PTN_V1_FIFO_DEPTH_CFG_REG 0x24 | |
+ | |
+/* FIFO configuration registers in V2 chip */ | |
+#define HAP_PTN_V2_FIFO_DIN_0_REG 0x20 | |
+#define HAP_PTN_V2_FIFO_DIN_NUM 4 | |
-#define HAP_PTN_FIFO_DEPTH_CFG_REG 0x2B | |
-#define HAP_PTN_FIFO_DIN_1B_REG 0x2C | |
+#define HAP_PTN_V2_FIFO_PLAY_RATE_REG 0x24 | |
+#define HAP_PTN_V2_FIFO_EMPTY_CFG_REG 0x2A | |
+#define HAP_PTN_V2_FIFO_THRESH_LSB 40 | |
+#define HAP_PTN_V2_FIFO_DEPTH_CFG_REG 0x2B | |
+#define HAP_PTN_V2_FIFO_DIN_1B_REG 0x2C | |
+/* shared registers between V1 and V2 chips */ | |
#define HAP_PTN_DIRECT_PLAY_REG 0x26 | |
#define DIRECT_PLAY_MAX_AMPLITUDE 0xFF | |
@@ -271,29 +233,11 @@ | |
#define HAP_PTN_BRAKE_AMP_REG 0x70 | |
-/* HAPTICS_PATTERN registers only present in HAP525_HV */ | |
-#define HAP_PTN_MEM_OP_ACCESS_REG 0x2D | |
-#define MEM_PAT_ACCESS_BIT BIT(7) | |
-#define MEM_PAT_RW_SEL_MASK GENMASK(5, 4) | |
-#define MEM_FLUSH_RELOAD_BIT BIT(0) | |
- | |
-#define HAP_PTN_MMAP_FIFO_REG 0xA0 | |
-#define MMAP_FIFO_EXIST_BIT BIT(7) | |
-#define MMAP_FIFO_LEN_MASK GENMASK(3, 0) | |
-#define MMAP_FIFO_LEN_PER_LSB 128 | |
- | |
-#define HAP_PTN_MMAP_PAT1_REG 0xA1 | |
-#define MMAP_PAT_LEN_PER_LSB 32 | |
-#define MMAP_PAT1_LEN_MASK GENMASK(6, 0) | |
-#define MMAP_PAT2_LEN_MASK GENMASK(5, 0) | |
-#define MMAP_PAT3_PAT4_LEN_MASK GENMASK(4, 0) | |
- | |
/* register in HBOOST module */ | |
#define HAP_BOOST_REVISION1 0x00 | |
#define HAP_BOOST_REVISION2 0x01 | |
#define HAP_BOOST_V0P0 0x0000 | |
#define HAP_BOOST_V0P1 0x0001 | |
-#define HAP_BOOST_V0P2 0x0002 | |
#define HAP_BOOST_STATUS4_REG 0x0B | |
#define BOOST_DTEST1_STATUS_BIT BIT(0) | |
@@ -306,14 +250,10 @@ | |
#define HAP_BOOST_VREG_EN_REG 0x46 | |
#define VREG_EN_BIT BIT(7) | |
-#define HAP_BOOST_CLAMP_REG 0x70 | |
+#define HAP_BOOST_V0P0_CLAMP_REG 0xF1 | |
+#define HAP_BOOST_V0P1_CLAMP_REG 0x70 | |
#define CLAMP_5V_BIT BIT(0) | |
-/* haptics SDAM registers offset definition */ | |
-#define HAP_STATUS_DATA_MSB_SDAM_OFFSET 0x46 | |
-#define HAP_LRA_NOMINAL_OHM_SDAM_OFFSET 0x75 | |
-#define HAP_LRA_DETECTED_OHM_SDAM_OFFSET 0x76 | |
- | |
/* constant parameters */ | |
#define SAMPLES_PER_PATTERN 8 | |
#define BRAKE_SAMPLE_COUNT 8 | |
@@ -327,15 +267,18 @@ | |
#define HW_BRAKE_CYCLES 5 | |
#define F_LRA_VARIATION_HZ 5 | |
#define NON_HBOOST_MAX_VMAX_MV 4000 | |
-/* below definitions are only for HAP525_HV */ | |
-#define MMAP_NUM_BYTES 2048 | |
-#define MMAP_FIFO_MIN_SIZE 640 | |
-#define FIFO_PRGM_INIT_SIZE 320 | |
+#define MAX_FIFO_SAMPLES(chip) \ | |
+ ((chip)->ptn_revision == HAP_PTN_V1 ? 104 : 640) | |
+#define FIFO_EMPTY_THRESHOLD(chip) \ | |
+ ((chip)->ptn_revision == HAP_PTN_V1 ? 48 : 280) | |
#define is_between(val, min, max) \ | |
(((min) <= (max)) && ((min) <= (val)) && ((val) <= (max))) | |
+#define HAP_BOOST_CLAMP_5V_REG_OFFSET(chip) \ | |
+ ((chip)->hbst_revision == HAP_BOOST_V0P0 ? \ | |
+ HAP_BOOST_V0P0_CLAMP_REG : HAP_BOOST_V0P1_CLAMP_REG) | |
-enum hap_status_sel { | |
+enum hap_status_sel_v2 { | |
CAL_TLRA_CL_STS = 0x00, | |
T_WIND_STS, | |
T_WIND_STS_PREV, | |
@@ -369,21 +312,12 @@ enum brake_sine_gain { | |
BRAKE_SINE_GAIN_X8, | |
}; | |
-enum pat_mem_sel { | |
- PAT1_MEM, | |
- PAT2_MEM, | |
- PAT3_MEM, | |
- PAT4_MEM, | |
- PAT_MEM_MAX, | |
-}; | |
- | |
enum pattern_src { | |
FIFO, | |
DIRECT_PLAY, | |
PATTERN1, | |
PATTERN2, | |
SWR, | |
- PATTERN_MEM, | |
SRC_RESERVED, | |
}; | |
@@ -413,25 +347,6 @@ enum custom_effect_param { | |
CUSTOM_DATA_LEN, | |
}; | |
-/* | |
- * HW type of the haptics module, the type value follows the | |
- * revision value of the HAPTICS_CFG/HAPTICS_PATTERN modules | |
- */ | |
-enum haptics_hw_type { | |
- HAP520 = 0x2, /* PM8350B */ | |
- HAP520_MV = 0x3, /* PM5100 */ | |
- HAP525_HV = 0x4, /* PMIC for kalama */ | |
-}; | |
- | |
-enum wa_flags { | |
- TOGGLE_CAL_RC_CLK = BIT(0), | |
- SW_CTRL_HBST = BIT(1), | |
- SLEEP_CLK_32K_SCALE = BIT(2), | |
- TOGGLE_EN_TO_FLUSH_FIFO = BIT(3), | |
- RECOVER_SWR_SLAVE = BIT(4), | |
- TOGGLE_MODULE_EN = BIT(5), | |
-}; | |
- | |
static const char * const src_str[] = { | |
"FIFO", | |
"DIRECT_PLAY", | |
@@ -484,7 +399,6 @@ struct fifo_cfg { | |
u32 num_s; | |
enum s_period period_per_s; | |
u32 play_length_us; | |
- bool preload; | |
}; | |
struct brake_cfg { | |
@@ -504,22 +418,9 @@ struct haptics_effect { | |
u32 vmax_mv; | |
u32 t_lra_us; | |
enum pattern_src src; | |
- enum pat_mem_sel pat_sel; | |
bool auto_res_disable; | |
}; | |
-struct mmap_partition { | |
- u32 max_size; | |
- u32 length; | |
- bool in_use; | |
-}; | |
- | |
-struct haptics_mmap { | |
- struct mmap_partition fifo_mmap; | |
- struct mmap_partition pat_sel_mmap[PAT_MEM_MAX]; | |
- enum s_period pat_play_rate; | |
-}; | |
- | |
/** | |
* struct fifo_play_status - Data used for recording the FIFO playing status | |
* | |
@@ -558,13 +459,11 @@ struct haptics_hw_config { | |
u32 lra_min_mohms; | |
u32 lra_max_mohms; | |
u32 lra_open_mohms; | |
- u32 lra_measured_mohms; | |
u32 preload_effect; | |
u32 fifo_empty_thresh; | |
u16 rc_clk_cal_count; | |
enum drv_sig_shape drv_wf; | |
bool is_erm; | |
- bool measure_lra_impedance; | |
}; | |
struct custom_fifo_data { | |
@@ -580,10 +479,8 @@ struct haptics_chip { | |
struct input_dev *input_dev; | |
struct haptics_hw_config config; | |
struct haptics_effect *effects; | |
- struct haptics_effect *primitives; | |
struct haptics_effect *custom_effect; | |
struct haptics_play_info play; | |
- struct haptics_mmap mmap; | |
struct dentry *debugfs_dir; | |
struct regulator_dev *swr_slave_rdev; | |
struct nvmem_cell *cl_brake_nvmem; | |
@@ -592,29 +489,19 @@ struct haptics_chip { | |
struct class hap_class; | |
struct regulator *hpwr_vreg; | |
struct hrtimer hbst_off_timer; | |
- struct notifier_block hboost_nb; | |
int fifo_empty_irq; | |
u32 hpwr_voltage_mv; | |
u32 effects_count; | |
- u32 primitives_count; | |
u32 cfg_addr_base; | |
u32 ptn_addr_base; | |
u32 hbst_addr_base; | |
- u32 clamped_vmax_mv; | |
- u32 wa_flags; | |
- u32 primitive_duration; | |
- u8 cfg_rev1; | |
u8 cfg_revision; | |
u8 ptn_revision; | |
- u8 hpwr_intf_ctl; | |
u16 hbst_revision; | |
- u16 max_vmax_mv; | |
- enum haptics_hw_type hw_type; | |
bool fifo_empty_irq_en; | |
bool swr_slave_enabled; | |
bool clamp_at_5v; | |
bool hpwr_vreg_enabled; | |
- bool is_hv_haptics; | |
bool hboost_enabled; | |
}; | |
@@ -623,82 +510,70 @@ struct haptics_reg_info { | |
u8 val; | |
}; | |
-static inline int get_max_fifo_samples(struct haptics_chip *chip) | |
-{ | |
- int val = 0; | |
- | |
- switch (chip->hw_type) { | |
- case HAP520: | |
- val = 640; | |
- break; | |
- case HAP520_MV: | |
- val = 1024; | |
- break; | |
- case HAP525_HV: | |
- val = chip->mmap.fifo_mmap.length ? | |
- chip->mmap.fifo_mmap.length : MMAP_FIFO_MIN_SIZE; | |
- break; | |
- default: | |
- pr_err("Invalid HW type\n"); | |
- break; | |
- } | |
- | |
- return val; | |
-} | |
+//#ifdef ASUS_DAVINCI_PROJECT | |
+#if 0 | |
-static int get_fifo_empty_threshold(struct haptics_chip *chip) | |
+#define CALI_FILE "/mnt/vendor/persist/haptic_cali.bin" | |
+static int write_cali_to_file(u32 cali_re) | |
{ | |
- int val = 0; | |
- | |
- switch (chip->hw_type) { | |
- case HAP520: | |
- val = 280; | |
- break; | |
- case HAP520_MV: | |
- case HAP525_HV: | |
- val = 288; | |
- break; | |
- default: | |
- pr_err("Invalid HW type\n"); | |
- break; | |
+ struct file *fp; | |
+ char buf[16] = {0}; | |
+ loff_t pos = 0; | |
+ //mm_segment_t fs; | |
+ | |
+ fp = filp_open(CALI_FILE, O_RDWR | O_CREAT, 0644); | |
+ if (IS_ERR(fp)) { | |
+ printk("haptic_d: %s: open %s failed!\n",__func__,CALI_FILE); | |
+ return -EINVAL; | |
} | |
- | |
- return val; | |
+ snprintf(buf, 16, "%d", cali_re); | |
+ //fs = get_fs(); | |
+ //set_fs(KERNEL_DS); | |
+ //vfs_write(fp, buf, strlen(buf), &pos); | |
+ //set_fs(fs); | |
+ kernel_write(fp, buf, strlen(buf), &pos); | |
+ printk("haptic_d: %s: cali_re=%d\n",__func__,cali_re); | |
+ filp_close(fp, NULL); | |
+ return 0; | |
} | |
-static int get_fifo_threshold_per_bit(struct haptics_chip *chip) | |
+static int get_cali_from_file(u32 *cali_re) | |
{ | |
- int val = -EINVAL; | |
- | |
- switch (chip->hw_type) { | |
- case HAP520: | |
- val = 40; | |
- break; | |
- case HAP520_MV: | |
- case HAP525_HV: | |
- val = 32; | |
- break; | |
- default: | |
- pr_err("Invalid HW type\n"); | |
- break; | |
+ struct file *fp; | |
+ /*struct inode *node;*/ | |
+ int f_size; | |
+ char *buf; | |
+ u32 int_cali_re = 0; | |
+ loff_t pos = 0; | |
+ //mm_segment_t fs; | |
+ | |
+ fp = filp_open(CALI_FILE, O_RDWR, 0); | |
+ if (IS_ERR(fp)) { | |
+ printk("haptic_d: %s: open %s failed!\n",__func__,CALI_FILE); | |
+ return -EINVAL; | |
} | |
- | |
- return val; | |
-} | |
- | |
-static bool is_haptics_external_powered(struct haptics_chip *chip) | |
-{ | |
- /* SW based explicit vote */ | |
- if (chip->hpwr_vreg) | |
- return true; | |
- | |
- /* Implicit voting by HW */ | |
- if (chip->hw_type == HAP520_MV) | |
- return true; | |
- | |
- /* Powered by HBOOST */ | |
- return false; | |
+ f_size = sizeof(u32); | |
+ buf = kzalloc(f_size + 1, GFP_ATOMIC); | |
+ if (!buf) { | |
+ pr_err("haptic_d: %s: malloc mem %d failed!\n", | |
+ __func__, f_size); | |
+ filp_close(fp, NULL); | |
+ return -EINVAL; | |
+ } | |
+ //fs = get_fs(); | |
+ //set_fs(KERNEL_DS); | |
+ //vfs_read(fp, buf, f_size, &pos); | |
+ //set_fs(fs); | |
+ kernel_read(fp, buf, f_size, &pos); | |
+ if (sscanf(buf, "%d", &int_cali_re) == 1) | |
+ *cali_re = int_cali_re; | |
+ else | |
+ *cali_re = 0xAA55; | |
+ printk("haptic_d: %s: cali_re=%d %d\n",__func__,*cali_re); | |
+ filp_close(fp, NULL); | |
+ return 0; | |
} | |
+#endif | |
static int haptics_read(struct haptics_chip *chip, | |
u16 base, u8 offset, u8 *val, u32 length) | |
@@ -708,7 +583,7 @@ static int haptics_read(struct haptics_chip *chip, | |
rc = regmap_bulk_read(chip->regmap, addr, val, length); | |
if (rc < 0) | |
- dev_err(chip->dev, "read addr %#x failed, rc=%d\n", addr, rc); | |
+ dev_err(chip->dev, "read addr %d failed, rc=%d\n", addr, rc); | |
return rc; | |
} | |
@@ -721,7 +596,7 @@ static int haptics_write(struct haptics_chip *chip, | |
rc = regmap_bulk_write(chip->regmap, addr, val, length); | |
if (rc < 0) | |
- dev_err(chip->dev, "write addr %#x failed, rc=%d\n", addr, rc); | |
+ dev_err(chip->dev, "write addr %d failed, rc=%d\n", addr, rc); | |
return rc; | |
} | |
@@ -734,13 +609,12 @@ static int haptics_masked_write(struct haptics_chip *chip, | |
regmap_update_bits(chip->regmap, addr, mask, val); | |
if (rc < 0) | |
- dev_err(chip->dev, "update addr %#x failed, rc=%d\n", addr, rc); | |
+ dev_err(chip->dev, "update addr %d failed, rc=%d\n", addr, rc); | |
return rc; | |
} | |
-static void __dump_effects(struct haptics_chip *chip, | |
- struct haptics_effect *effects, int effects_count) | |
+static void __dump_effects(struct haptics_chip *chip) | |
{ | |
struct haptics_effect *effect; | |
struct pattern_s *sample; | |
@@ -748,8 +622,8 @@ static void __dump_effects(struct haptics_chip *chip, | |
u32 size, pos; | |
int i, j; | |
- for (i = 0; i < effects_count; i++) { | |
- effect = &effects[i]; | |
+ for (i = 0; i < chip->effects_count; i++) { | |
+ effect = &chip->effects[i]; | |
if (!effect) | |
return; | |
@@ -787,9 +661,9 @@ static void __dump_effects(struct haptics_chip *chip, | |
dev_dbg(chip->dev, "%s\n", str); | |
kfree(str); | |
- dev_dbg(chip->dev, "FIFO data preload: %d, play rate: %s, play length: %uus\n", | |
- effect->fifo->preload, | |
- period_str[effect->fifo->period_per_s], | |
+ dev_dbg(chip->dev, "FIFO data play rate: %s\n", | |
+ period_str[effect->fifo->period_per_s]); | |
+ dev_dbg(chip->dev, "FIFO data play length: %dus\n", | |
effect->fifo->play_length_us); | |
} | |
@@ -964,26 +838,15 @@ static int get_brake_play_length_us(struct brake_cfg *brake, u32 t_lra_us) | |
} | |
static int haptics_get_status_data(struct haptics_chip *chip, | |
- enum hap_status_sel sel, u8 data[]) | |
+ enum hap_status_sel_v2 sel, u8 data[]) | |
{ | |
int rc; | |
u8 mod_sel_val[2]; | |
- const char *hap_status_name[BRAKE_CAL_SCALAR + 1] = { | |
- "CAL_TLRA_CL_STS", | |
- "T_WIND_STS", | |
- "T_WIND_STS_PREV", | |
- "LAST_GOOD_TLRA_CL_STS", | |
- "TLRA_CL_ERR_STS", | |
- "HAP_DRV_STS", | |
- "RNAT_RCAL_INT", | |
- "BRAKE_CAL_SCALAR", | |
- }; | |
- const char *name; | |
mod_sel_val[0] = sel & 0xff; | |
mod_sel_val[1] = (sel >> 8) & 0xff; | |
rc = haptics_write(chip, chip->cfg_addr_base, | |
- HAP_CFG_MOD_STATUS_XT_REG, &mod_sel_val[1], 1); | |
+ HAP_CFG_MOD_STATUS_XT_V2_REG, &mod_sel_val[1], 1); | |
if (rc < 0) | |
return rc; | |
@@ -997,50 +860,101 @@ static int haptics_get_status_data(struct haptics_chip *chip, | |
if (rc < 0) | |
return rc; | |
- if (sel <= BRAKE_CAL_SCALAR) | |
- name = hap_status_name[sel]; | |
- else if (sel == CLAMPED_DUTY_CYCLE_STS) | |
- name = "CLAMPED_DUTY_CYCLE_STS"; | |
- else if (sel == FIFO_REAL_TIME_STS) | |
- name = "FIFO_REAL_TIME_STS"; | |
- | |
- dev_dbg(chip->dev, "Get status data[%s] = (%#x, %#x)\n", name, data[0], data[1]); | |
- trace_qcom_haptics_status(name, data[0], data[1]); | |
+ dev_dbg(chip->dev, "Get status data[%x] = (%#x, %#x)\n", | |
+ sel, data[0], data[1]); | |
return 0; | |
} | |
-#define AUTO_CAL_CLK_SCALE_DEN 1000 | |
-#define AUTO_CAL_CLK_SCALE_NUM 1024 | |
+#define V1_CL_TLRA_STEP_AUTO_RES_CAL_NOT_DONE_NS 5000 | |
+#define V1_CL_TLRA_STEP_AUTO_RES_CAL_DONE_NS 3333 | |
+#define AUTO_CAL_CLK_SCALE_DEN 1000 | |
+#define AUTO_CAL_CLK_SCALE_NUM 1024 | |
static int haptics_adjust_lra_period(struct haptics_chip *chip, u32 *t_lra_us) | |
{ | |
int rc; | |
u8 val; | |
- if (chip->wa_flags & SLEEP_CLK_32K_SCALE) { | |
- rc = haptics_read(chip, chip->cfg_addr_base, | |
- HAP_CFG_CAL_EN_REG, &val, 1); | |
- if (rc < 0) | |
- return rc; | |
+ rc = haptics_read(chip, chip->cfg_addr_base, | |
+ HAP_CFG_CAL_EN_REG, &val, 1); | |
+ if (rc < 0) | |
+ return rc; | |
- if ((val & CAL_RC_CLK_MASK) == | |
- (CAL_RC_CLK_AUTO_VAL << CAL_RC_CLK_SHIFT)) | |
- *t_lra_us = div_u64((u64)(*t_lra_us) * AUTO_CAL_CLK_SCALE_NUM, | |
- AUTO_CAL_CLK_SCALE_DEN); | |
- } | |
+ if ((val & CAL_RC_CLK_MASK) == | |
+ (CAL_RC_CLK_AUTO_VAL << CAL_RC_CLK_SHIFT)) | |
+ *t_lra_us = div_u64((u64)(*t_lra_us) * AUTO_CAL_CLK_SCALE_NUM, | |
+ AUTO_CAL_CLK_SCALE_DEN); | |
+ | |
+ return 0; | |
+} | |
+ | |
+static int haptics_get_closeloop_lra_period_v1( | |
+ struct haptics_chip *chip) | |
+{ | |
+ struct haptics_hw_config *config = &chip->config; | |
+ int rc, freq_diff, f_lra, cl_f_lra; | |
+ u8 val[2]; | |
+ u32 tmp, step_ns; | |
+ bool auto_res_cal_done; | |
+ | |
+ val[0] = MOD_STATUS_SEL_CAL_TLRA_CL_STS_VAL; | |
+ rc = haptics_write(chip, chip->cfg_addr_base, | |
+ HAP_CFG_MOD_STATUS_SEL_REG, val, 1); | |
+ if (rc < 0) | |
+ return rc; | |
+ | |
+ rc = haptics_read(chip, chip->cfg_addr_base, | |
+ HAP_CFG_STATUS_DATA_MSB_REG, val, 2); | |
+ if (rc < 0) | |
+ return rc; | |
+ | |
+ /* | |
+ * Calculate the closed loop T_LRA with the following equations | |
+ * for PM8350B V1: | |
+ * LAST_GOOD_TLRA_CL_STS[12:0] = STATUS_DATA_MSB[4:0] | | |
+ * STATUS_DATA_LSB[7:0] | |
+ * CL_TLRA_STEP_US = STATUS_DATA_MSB[5] ? 3.333 us : 5 us | |
+ * LAST_GOOD_TLRA_CL = LAST_GOOD_TLRA_CL_STS[12:0] * | |
+ * CL_TLRA_STEP_US | |
+ */ | |
+ auto_res_cal_done = !!(val[0] & AUTO_RES_CAL_DONE_BIT); | |
+ if (auto_res_cal_done) | |
+ step_ns = V1_CL_TLRA_STEP_AUTO_RES_CAL_DONE_NS; | |
+ else | |
+ step_ns = V1_CL_TLRA_STEP_AUTO_RES_CAL_NOT_DONE_NS; | |
+ | |
+ tmp = ((val[0] & CAL_TLRA_CL_STS_MSB_MASK) << 8) | val[1]; | |
+ config->cl_t_lra_us = (tmp * step_ns) / 1000; | |
+ | |
+ rc = haptics_adjust_lra_period(chip, &config->cl_t_lra_us); | |
+ if (rc < 0) | |
+ return rc; | |
+ | |
+ /* calculate RC_CLK_CAL_COUNT */ | |
+ if (!config->t_lra_us || !config->cl_t_lra_us) | |
+ return -EINVAL; | |
+ | |
+ f_lra = USEC_PER_SEC / config->t_lra_us; | |
+ if (!f_lra) | |
+ return -EINVAL; | |
+ | |
+ cl_f_lra = USEC_PER_SEC / config->cl_t_lra_us; | |
+ freq_diff = cl_f_lra - f_lra; | |
+ | |
+ /* RC_CLK_CAL_COUNT = 600*(1-(clk_adjustment/Fifo_pat_freq)) */ | |
+ config->rc_clk_cal_count = 600 - ((600 * freq_diff) / f_lra); | |
return 0; | |
} | |
+/* The offset of SDAM register which saves STATUS_DATA_MSB value */ | |
+#define HAP_STATUS_DATA_MSB_SDAM_OFFSET 0x46 | |
+ | |
/* constant definitions for calculating TLRA */ | |
#define TLRA_AUTO_RES_ERR_NO_CAL_STEP_PSEC 1667000 | |
#define TLRA_AUTO_RES_NO_CAL_STEP_PSEC 3333000 | |
-#define TLRA_AUTO_RES_ERR_AUTO_CAL_STEP_PSEC \ | |
- ((chip->wa_flags & SLEEP_CLK_32K_SCALE) ? 1627700 : 1666667) | |
-#define TLRA_AUTO_RES_AUTO_CAL_STEP_PSEC \ | |
- ((chip->wa_flags & SLEEP_CLK_32K_SCALE) ? 813850 : 833333) | |
-#define SLEEP_CLK_CAL_DIVIDER \ | |
- ((chip->wa_flags & SLEEP_CLK_32K_SCALE) ? 600 : 586) | |
-static int haptics_get_closeloop_lra_period( | |
+#define TLRA_AUTO_RES_ERR_AUTO_CAL_STEP_PSEC 1627700 | |
+#define TLRA_AUTO_RES_AUTO_CAL_STEP_PSEC 813850 | |
+static int haptics_get_closeloop_lra_period_v2( | |
struct haptics_chip *chip, bool in_boot) | |
{ | |
struct haptics_hw_config *config = &chip->config; | |
@@ -1058,7 +972,7 @@ static int haptics_get_closeloop_lra_period( | |
rc_clk_cal = ((val[0] & CAL_RC_CLK_MASK) >> CAL_RC_CLK_SHIFT); | |
/* read auto resonance calibration result */ | |
- if (in_boot && ((chip->hw_type == HAP520) || (chip->hw_type == HAP520_MV))) { | |
+ if (in_boot) { | |
if (chip->hap_cfg_nvmem == NULL) { | |
dev_dbg(chip->dev, "nvmem device for hap_cfg is not defined\n"); | |
return -EINVAL; | |
@@ -1072,7 +986,14 @@ static int haptics_get_closeloop_lra_period( | |
return rc; | |
} | |
} else { | |
- rc = haptics_get_status_data(chip, CAL_TLRA_CL_STS, val); | |
+ val[0] = MOD_STATUS_SEL_CAL_TLRA_CL_STS_VAL; | |
+ rc = haptics_write(chip, chip->cfg_addr_base, | |
+ HAP_CFG_MOD_STATUS_SEL_REG, val, 1); | |
+ if (rc < 0) | |
+ return rc; | |
+ | |
+ rc = haptics_read(chip, chip->cfg_addr_base, | |
+ HAP_CFG_STATUS_DATA_MSB_REG, val, 2); | |
if (rc < 0) | |
return rc; | |
} | |
@@ -1082,7 +1003,14 @@ static int haptics_get_closeloop_lra_period( | |
((val[0] & CAL_TLRA_CL_STS_MSB_MASK) << 8) | val[1]; | |
/* read auto resonance calibration error status */ | |
- rc = haptics_get_status_data(chip, TLRA_CL_ERR_STS, val); | |
+ val[0] = MOD_STATUS_SEL_TLRA_CL_ERR_STS_VAL; | |
+ rc = haptics_write(chip, chip->cfg_addr_base, | |
+ HAP_CFG_MOD_STATUS_SEL_REG, val, 1); | |
+ if (rc < 0) | |
+ return rc; | |
+ | |
+ rc = haptics_read(chip, chip->cfg_addr_base, | |
+ HAP_CFG_STATUS_DATA_MSB_REG, val, 2); | |
if (rc < 0) | |
return rc; | |
@@ -1109,7 +1037,7 @@ static int haptics_get_closeloop_lra_period( | |
/* | |
* CAL_TLRA_OL = CAL_TLRA_CL_STS; | |
* TLRA_CL_ERR(us) = TLRA_CL_ERR_STS * | |
- * (TLRA_OL / CAL_TLRA_OL) * TLRA_AUTO_RES_ERR_AUTO_CAL_STEP_US | |
+ * (TLRA_OL / CAL_TLRA_OL) * 1.6277 us | |
*/ | |
/* read the TLRA_OL setting */ | |
@@ -1131,10 +1059,10 @@ static int haptics_get_closeloop_lra_period( | |
if (!config->t_lra_us || !config->cl_t_lra_us) | |
return -EINVAL; | |
/* | |
- * RC_CLK_CAL_COUNT = SLEEP_CLK_CAL_DIVIDER * (CAL_TLRA_OL / TLRA_OL) | |
- * * (SLEEP_CLK_CAL_DIVIDER / 586) * (CL_T_TLRA_US / OL_T_LRA_US) | |
+ * RC_CLK_CAL_COUNT = 600 * (CAL_TLRA_OL / TLRA_OL) | |
+ * * (600 / 586) * (CL_T_TLRA_US / OL_T_LRA_US) | |
*/ | |
- tmp = SLEEP_CLK_CAL_DIVIDER * SLEEP_CLK_CAL_DIVIDER; | |
+ tmp = 360000; | |
tmp *= cal_tlra_cl_sts * config->cl_t_lra_us; | |
tmp = div_u64(tmp, tlra_ol); | |
tmp = div_u64(tmp, 586); | |
@@ -1142,13 +1070,25 @@ static int haptics_get_closeloop_lra_period( | |
} else if (rc_clk_cal == CAL_RC_CLK_AUTO_VAL && auto_res_done) { | |
/* | |
* CAL_TLRA_CL_STS_W_CAL = CAL_TLRA_CL_STS; | |
- * TLRA_AUTO_RES(us) = LAST_GOOD_TLRA_CL_STS * | |
- * TLRA_AUTO_RES_AUTO_CAL_STEP_US * | |
+ * TLRA_AUTO_RES(us) = LAST_GOOD_TLRA_CL_STS * 0.81385 us * | |
* (LAST_GOOD_TLRA_CL_STS / CAL_TLRA_CL_STS_AUTO_CAL) | |
*/ | |
/* read LAST_GOOD_TLRA_CL_STS */ | |
- rc = haptics_get_status_data(chip, LAST_GOOD_TLRA_CL_STS, val); | |
+ val[0] = MOD_STATUS_XT_SEL_LAST_GOOD_TLRA_VAL; | |
+ rc = haptics_write(chip, chip->cfg_addr_base, | |
+ HAP_CFG_MOD_STATUS_XT_V2_REG, val, 1); | |
+ if (rc < 0) | |
+ return rc; | |
+ | |
+ val[0] = MOD_STATUS_SEL_LAST_GOOD_TLRA_VAL; | |
+ rc = haptics_write(chip, chip->cfg_addr_base, | |
+ HAP_CFG_MOD_STATUS_SEL_REG, val, 1); | |
+ if (rc < 0) | |
+ return rc; | |
+ | |
+ rc = haptics_read(chip, chip->cfg_addr_base, | |
+ HAP_CFG_STATUS_DATA_MSB_REG, val, 2); | |
if (rc < 0) | |
return rc; | |
@@ -1169,10 +1109,10 @@ static int haptics_get_closeloop_lra_period( | |
/* | |
* RC_CLK_CAL_COUNT = | |
- * SLEEP_CLK_CAL_DIVIDER * (CAL_TLRA_CL_STS_AUTO_CAL / LAST_GOOD_TLRA_CL_STS) | |
- * * (SLEEP_CLK_CAL_DIVIDER / 293) * (CL_T_TLRA_US / OL_T_LRA_US) | |
+ * 600 * (CAL_TLRA_CL_STS_AUTO_CAL / LAST_GOOD_TLRA_CL_STS) | |
+ * * (600 / 293) * (CL_T_TLRA_US / OL_T_LRA_US) | |
*/ | |
- tmp = SLEEP_CLK_CAL_DIVIDER * SLEEP_CLK_CAL_DIVIDER; | |
+ tmp = 360000; | |
tmp *= cal_tlra_cl_sts * config->cl_t_lra_us; | |
tmp = div_u64(tmp, last_good_tlra_cl_sts); | |
tmp = div_u64(tmp, 293); | |
@@ -1183,6 +1123,25 @@ static int haptics_get_closeloop_lra_period( | |
return -EINVAL; | |
} | |
+ return 0; | |
+} | |
+ | |
+static int haptics_get_closeloop_lra_period(struct haptics_chip *chip, | |
+ bool in_boot) | |
+{ | |
+ int rc = 0; | |
+ | |
+ if (chip->ptn_revision == HAP_PTN_V1) | |
+ rc = haptics_get_closeloop_lra_period_v1(chip); | |
+ else | |
+ rc = haptics_get_closeloop_lra_period_v2(chip, in_boot); | |
+ | |
+ if (rc < 0) { | |
+ dev_err(chip->dev, "get close loop T LRA failed, rc=%d\n", | |
+ rc); | |
+ return rc; | |
+ } | |
+ | |
dev_dbg(chip->dev, "OL_TLRA %u us, CL_TLRA %u us, RC_CLK_CAL_COUNT %#x\n", | |
chip->config.t_lra_us, chip->config.cl_t_lra_us, | |
chip->config.rc_clk_cal_count); | |
@@ -1192,29 +1151,24 @@ static int haptics_get_closeloop_lra_period( | |
static int haptics_set_vmax_mv(struct haptics_chip *chip, u32 vmax_mv) | |
{ | |
int rc = 0; | |
- u8 val, vmax_step; | |
+ u8 val; | |
- if (vmax_mv > chip->max_vmax_mv) { | |
- dev_dbg(chip->dev, "vmax (%d) exceed the max value: %d\n", | |
- vmax_mv, chip->max_vmax_mv); | |
- vmax_mv = chip->max_vmax_mv; | |
+ if (vmax_mv > MAX_VMAX_MV) { | |
+ dev_err(chip->dev, "vmax (%d) exceed the max value: %d\n", | |
+ vmax_mv, MAX_VMAX_MV); | |
+ return -EINVAL; | |
} | |
- if (vmax_mv > chip->clamped_vmax_mv) | |
- vmax_mv = chip->clamped_vmax_mv; | |
- | |
if (chip->clamp_at_5v && (vmax_mv > CLAMPED_VMAX_MV)) | |
vmax_mv = CLAMPED_VMAX_MV; | |
- vmax_step = (chip->is_hv_haptics) ? | |
- VMAX_HV_STEP_MV : VMAX_MV_STEP_MV; | |
- val = vmax_mv / vmax_step; | |
+ val = vmax_mv / VMAX_STEP_MV; | |
rc = haptics_write(chip, chip->cfg_addr_base, | |
HAP_CFG_VMAX_REG, &val, 1); | |
if (rc < 0) | |
dev_err(chip->dev, "config VMAX failed, rc=%d\n", rc); | |
else | |
- dev_dbg(chip->dev, "Set Vmax to %u mV\n", vmax_mv); | |
+ dev_err(chip->dev, "Set Vmax to %u mV\n", vmax_mv); | |
return rc; | |
} | |
@@ -1278,35 +1232,12 @@ static int haptics_set_direct_play(struct haptics_chip *chip, u8 amplitude) | |
HAP_PTN_DIRECT_PLAY_REG, &litude, 1); | |
if (rc < 0) | |
dev_err(chip->dev, "config DIRECT_PLAY failed, rc=%d\n", rc); | |
+ else | |
+ dev_err(chip->dev, "config DIRECT_PLAY amplitude=%d\n", amplitude); | |
return rc; | |
} | |
-static bool is_boost_vreg_enabled_in_open_loop(struct haptics_chip *chip) | |
-{ | |
- int rc; | |
- u8 val; | |
- | |
- if (is_haptics_external_powered(chip)) | |
- return false; | |
- | |
- rc = haptics_read(chip, chip->hbst_addr_base, HAP_BOOST_VREG_EN_REG, &val, 1); | |
- if (rc < 0) | |
- return false; | |
- | |
- chip->hboost_enabled = (val & VREG_EN_BIT); | |
- rc = haptics_read(chip, chip->hbst_addr_base, HAP_BOOST_HW_CTRL_FOLLOW_REG, &val, 1); | |
- if (rc < 0) | |
- return false; | |
- | |
- if (!(val & FOLLOW_HW_EN_BIT) && chip->hboost_enabled) { | |
- dev_dbg(chip->dev, "HBoost is enabled in open loop condition\n"); | |
- return true; | |
- } | |
- | |
- return false; | |
-} | |
- | |
#define PBS_ARG_REG 0x42 | |
#define HAP_VREG_ON_VAL 0x1 | |
#define HAP_VREG_OFF_VAL 0x2 | |
@@ -1317,23 +1248,11 @@ static int haptics_boost_vreg_enable(struct haptics_chip *chip, bool en) | |
int rc; | |
u8 val; | |
- if (is_haptics_external_powered(chip)) | |
- return 0; | |
- | |
- if (!(chip->wa_flags & SW_CTRL_HBST)) | |
- return 0; | |
- | |
if (chip->hap_cfg_nvmem == NULL) { | |
dev_dbg(chip->dev, "nvmem device for hap_cfg is not defined\n"); | |
return 0; | |
} | |
- if (is_boost_vreg_enabled_in_open_loop(chip)) { | |
- dev_dbg(chip->dev, "Ignore %s hBoost while it's enabled in open-loop mode\n", | |
- en ? "enabling" : "disabling"); | |
- return 0; | |
- } | |
- | |
if (chip->hboost_enabled == en) | |
return 0; | |
@@ -1368,12 +1287,31 @@ static bool is_swr_play_enabled(struct haptics_chip *chip) | |
if (rc < 0) | |
return false; | |
- if ((val[1] & HAP_DRV_PATTERN_SRC_STATUS_MASK) == SWR) | |
+ if ((val[1] & HAP_DRV_PATTERN_SRC_STATUS_MASK_V2) == SWR) | |
return true; | |
return false; | |
} | |
+static bool is_boost_vreg_enabled_in_open_loop(struct haptics_chip *chip) | |
+{ | |
+ int rc; | |
+ u8 val; | |
+ | |
+ rc = haptics_read(chip, chip->hbst_addr_base, | |
+ HAP_BOOST_HW_CTRL_FOLLOW_REG, &val, 1); | |
+ if (!rc && !(val & FOLLOW_HW_EN_BIT)) { | |
+ rc = haptics_read(chip, chip->hbst_addr_base, | |
+ HAP_BOOST_VREG_EN_REG, &val, 1); | |
+ if (!rc && (val & VREG_EN_BIT)) { | |
+ dev_dbg(chip->dev, "HBoost is enabled in open loop condition\n"); | |
+ return true; | |
+ } | |
+ } | |
+ | |
+ return false; | |
+} | |
+ | |
#define HBOOST_WAIT_READY_COUNT 100 | |
#define HBOOST_WAIT_READY_INTERVAL_US 200 | |
static int haptics_wait_hboost_ready(struct haptics_chip *chip) | |
@@ -1381,12 +1319,6 @@ static int haptics_wait_hboost_ready(struct haptics_chip *chip) | |
int i, rc; | |
u8 val; | |
- if (is_haptics_external_powered(chip)) | |
- return 0; | |
- | |
- if (!(chip->wa_flags & SW_CTRL_HBST)) | |
- return 0; | |
- | |
if ((hrtimer_get_remaining(&chip->hbst_off_timer) > 0) || | |
hrtimer_active(&chip->hbst_off_timer)) { | |
hrtimer_cancel(&chip->hbst_off_timer); | |
@@ -1482,35 +1414,20 @@ static int haptics_enable_hpwr_vreg(struct haptics_chip *chip, bool en) | |
return 0; | |
} | |
-static int haptics_force_vreg_ready(struct haptics_chip *chip, bool ready) | |
-{ | |
- u8 mask; | |
- | |
- mask = FORCE_VREG_RDY_BIT; | |
- if (chip->hw_type == HAP525_HV) | |
- mask |= FORCE_VSET_ACK_BIT; | |
- | |
- return haptics_masked_write(chip, chip->cfg_addr_base, | |
- HAP_CFG_VSET_CFG_REG, mask, ready ? mask : 0); | |
-} | |
- | |
static int haptics_open_loop_drive_config(struct haptics_chip *chip, bool en) | |
{ | |
int rc = 0; | |
u8 val; | |
if ((is_boost_vreg_enabled_in_open_loop(chip) || | |
- chip->hboost_enabled || is_haptics_external_powered(chip)) && en) { | |
- /* | |
- * Only set force-VREG-ready here if hBoost is not used by charger firmware. | |
- * In the case of charger firmware enabling hBoost, force-VREG-ready will be | |
- * set/reset based on the VMAX_CLAMP notification. | |
- */ | |
- if (chip->clamped_vmax_mv == MAX_HV_VMAX_MV) { | |
- rc = haptics_force_vreg_ready(chip, true); | |
- if (rc < 0) | |
- return rc; | |
- } | |
+ chip->hboost_enabled || | |
+ chip->hpwr_vreg != NULL) && en) { | |
+ /* Force VREG_RDY */ | |
+ rc = haptics_masked_write(chip, chip->cfg_addr_base, | |
+ HAP_CFG_VSET_CFG_REG, FORCE_VREG_RDY_BIT, | |
+ FORCE_VREG_RDY_BIT); | |
+ if (rc < 0) | |
+ return rc; | |
/* Toggle RC_CLK_CAL_EN if it's in auto mode */ | |
rc = haptics_read(chip, chip->cfg_addr_base, | |
@@ -1518,9 +1435,8 @@ static int haptics_open_loop_drive_config(struct haptics_chip *chip, bool en) | |
if (rc < 0) | |
return rc; | |
- if ((chip->wa_flags & TOGGLE_CAL_RC_CLK) && | |
- ((val & CAL_RC_CLK_MASK) == | |
- CAL_RC_CLK_AUTO_VAL << CAL_RC_CLK_SHIFT)) { | |
+ if ((val & CAL_RC_CLK_MASK) == | |
+ CAL_RC_CLK_AUTO_VAL << CAL_RC_CLK_SHIFT) { | |
val = CAL_RC_CLK_DISABLED_VAL << CAL_RC_CLK_SHIFT; | |
rc = haptics_masked_write(chip, chip->cfg_addr_base, | |
HAP_CFG_CAL_EN_REG, CAL_RC_CLK_MASK, | |
@@ -1537,52 +1453,13 @@ static int haptics_open_loop_drive_config(struct haptics_chip *chip, bool en) | |
dev_dbg(chip->dev, "Toggle CAL_EN in open-loop-VREG playing\n"); | |
} | |
- } else if (!is_haptics_external_powered(chip) && | |
- (chip->clamped_vmax_mv == MAX_HV_VMAX_MV)) { | |
- /* | |
- * Reset force-VREG-ready only when hBoost is not | |
- * used by charger firmware. | |
- */ | |
- rc = haptics_force_vreg_ready(chip, false); | |
- if (rc < 0) | |
- return rc; | |
+ } else if (chip->hpwr_vreg == NULL) { | |
+ rc = haptics_masked_write(chip, chip->cfg_addr_base, | |
+ HAP_CFG_VSET_CFG_REG, | |
+ FORCE_VREG_RDY_BIT, 0); | |
} | |
- return 0; | |
-} | |
- | |
-static int haptics_module_enable(struct haptics_chip *chip, bool enable) | |
-{ | |
- u8 val; | |
- int rc; | |
- | |
- val = enable ? HAPTICS_EN_BIT : 0; | |
- rc = haptics_write(chip, chip->cfg_addr_base, | |
- HAP_CFG_EN_CTL_REG, &val, 1); | |
- if (rc < 0) | |
- return rc; | |
- | |
- dev_dbg(chip->dev, "haptics module %s\n", | |
- enable ? "enabled" : "disabled"); | |
- return 0; | |
-} | |
- | |
-static int haptics_toggle_module_enable(struct haptics_chip *chip) | |
-{ | |
- int rc; | |
- | |
- /* | |
- * Updating HAPTICS_EN would vote hBoost enable status. Add 100us | |
- * delay before updating HAPTICS_EN for hBoost to have enough time | |
- * to handle its power transition. | |
- */ | |
- usleep_range(100, 101); | |
- rc = haptics_module_enable(chip, false); | |
- if (rc < 0) | |
- return rc; | |
- | |
- usleep_range(100, 101); | |
- return haptics_module_enable(chip, true); | |
+ return rc; | |
} | |
#define BOOST_VREG_OFF_DELAY_SECONDS 2 | |
@@ -1606,9 +1483,6 @@ static int haptics_enable_play(struct haptics_chip *chip, bool en) | |
return rc; | |
val = play->pattern_src; | |
- if (chip->hw_type == HAP525_HV && play->pattern_src == PATTERN_MEM) | |
- val |= FIELD_PREP(PATX_MEM_SEL_MASK, play->effect->pat_sel); | |
- | |
if (play->brake && !play->brake->disabled) | |
val |= BRAKE_EN_BIT; | |
@@ -1622,25 +1496,19 @@ static int haptics_enable_play(struct haptics_chip *chip, bool en) | |
return rc; | |
} | |
- if (chip->wa_flags & SW_CTRL_HBST) { | |
- if (en) { | |
- rc = haptics_boost_vreg_enable(chip, true); | |
- if (rc < 0) { | |
- dev_err(chip->dev, "Keep boost vreg on failed, rc=%d\n", | |
- rc); | |
- return rc; | |
- } | |
- } else { | |
- hrtimer_start(&chip->hbst_off_timer, | |
- ktime_set(BOOST_VREG_OFF_DELAY_SECONDS, 0), | |
- HRTIMER_MODE_REL); | |
+ if (en) { | |
+ rc = haptics_boost_vreg_enable(chip, true); | |
+ if (rc < 0) { | |
+ dev_err(chip->dev, "Keep boost vreg on failed, rc=%d\n", | |
+ rc); | |
+ return rc; | |
} | |
+ } else { | |
+ hrtimer_start(&chip->hbst_off_timer, | |
+ ktime_set(BOOST_VREG_OFF_DELAY_SECONDS, 0), | |
+ HRTIMER_MODE_REL); | |
} | |
- if ((chip->wa_flags & TOGGLE_MODULE_EN) && !en) | |
- rc = haptics_toggle_module_enable(chip); | |
- | |
- trace_qcom_haptics_play(en); | |
return rc; | |
} | |
@@ -1733,54 +1601,60 @@ static int haptics_set_pattern(struct haptics_chip *chip, | |
} | |
-static int haptics_update_memory_data(struct haptics_chip *chip, | |
- u8 *data, u32 length) | |
+static int haptics_update_fifo_sample_v1(struct haptics_chip *chip, u8 sample) | |
{ | |
- int rc, count, i; | |
- u32 left; | |
- u8 tmp[HAP_PTN_FIFO_DIN_NUM] = {0}; | |
+ int rc = 0; | |
+ u8 val; | |
- if (!length) | |
- return 0; | |
+ /* | |
+ * Fill FIFO_DIN registers to update FIFO memory, | |
+ * need to fill LSB first then MSB. | |
+ * The FIFO memory width in V1 chip is 9-bit so shift | |
+ * 1 bit to left on the 8-bit FIFO sample to achieve a | |
+ * 9-bit data and fill it into the FIFO_DIN registers. | |
+ */ | |
+ val = (sample << 1) & HAP_PTN_V1_FIFO_DIN_LSB_MASK; | |
+ rc = haptics_write(chip, chip->ptn_addr_base, | |
+ HAP_PTN_V1_FIFO_DIN_LSB_REG, &val, 1); | |
+ if (rc < 0) { | |
+ dev_err(chip->dev, "write FIFO LSB failed, rc=%d\n", | |
+ rc); | |
+ return rc; | |
+ } | |
+ | |
+ val = (sample >> 7) & HAP_PTN_V1_FIFO_DIN_MSB_BIT; | |
+ rc = haptics_write(chip, chip->ptn_addr_base, | |
+ HAP_PTN_V1_FIFO_DIN_MSB_REG, &val, 1); | |
+ if (rc < 0) { | |
+ dev_err(chip->dev, "write FIFO MSB failed, rc=%d\n", | |
+ rc); | |
+ return rc; | |
+ } | |
+ | |
+ return 0; | |
+} | |
+ | |
+static int haptics_update_fifo_sample_v2(struct haptics_chip *chip, | |
+ u8 *samples, u32 num) | |
+{ | |
+ int rc, i; | |
- count = length / HAP_PTN_FIFO_DIN_NUM; | |
- for (i = 0; i < count; i++) { | |
+ if (num > HAP_PTN_V2_FIFO_DIN_NUM) | |
+ return -EINVAL; | |
+ | |
+ if (num == HAP_PTN_V2_FIFO_DIN_NUM) { | |
rc = haptics_write(chip, chip->ptn_addr_base, | |
- HAP_PTN_FIFO_DIN_0_REG, data, | |
- HAP_PTN_FIFO_DIN_NUM); | |
+ HAP_PTN_V2_FIFO_DIN_0_REG, samples, num); | |
if (rc < 0) { | |
dev_err(chip->dev, "bulk write FIFO_DIN failed, rc=%d\n", | |
rc); | |
return rc; | |
} | |
- | |
- data += HAP_PTN_FIFO_DIN_NUM; | |
- } | |
- | |
- left = length % HAP_PTN_FIFO_DIN_NUM; | |
- if (left) { | |
- /* | |
- * In HAP520 module, when 1-byte FIFO write clashes | |
- * with the HW FIFO read operation, the HW will only read | |
- * 1 valid byte in every 4 bytes FIFO samples. So avoid | |
- * this by keeping the samples 4-byte aligned and always | |
- * use 4-byte write for HAP520 module. | |
- */ | |
- if (chip->hw_type == HAP520) { | |
- memcpy(tmp, data, left); | |
- rc = haptics_write(chip, chip->ptn_addr_base, | |
- HAP_PTN_FIFO_DIN_0_REG, tmp, | |
- HAP_PTN_FIFO_DIN_NUM); | |
- if (rc < 0) | |
- dev_err(chip->dev, "write FIFO_DIN failed, rc=%d\n", rc); | |
- | |
- return rc; | |
- } | |
- | |
- for (i = 0; i < left; i++) { | |
+ } else if (num < HAP_PTN_V2_FIFO_DIN_NUM) { | |
+ for (i = 0; i < num; i++) { | |
rc = haptics_write(chip, chip->ptn_addr_base, | |
- HAP_PTN_FIFO_DIN_1B_REG, | |
- (data + i), 1); | |
+ HAP_PTN_V2_FIFO_DIN_1B_REG, | |
+ (samples + i), 1); | |
if (rc < 0) { | |
dev_err(chip->dev, "write FIFO_DIN_1B failed, rc=%d\n", | |
rc); | |
@@ -1792,104 +1666,50 @@ static int haptics_update_memory_data(struct haptics_chip *chip, | |
return 0; | |
} | |
-static int haptics_update_fifo_samples(struct haptics_chip *chip, | |
- u8 *samples, u32 length, bool refill) | |
+static int haptics_get_fifo_fill_status(struct haptics_chip *chip, u32 *fill) | |
{ | |
int rc; | |
- u8 val; | |
- | |
- if (!samples) { | |
- dev_err(chip->dev, "no data available to update FIFO\n"); | |
- return -EINVAL; | |
- } | |
+ u8 val[2]; | |
+ bool empty = false, full = false; | |
- if (chip->hw_type == HAP525_HV && !refill) { | |
- val = MEM_FLUSH_RELOAD_BIT; | |
- rc = haptics_write(chip, chip->ptn_addr_base, | |
- HAP_PTN_MEM_OP_ACCESS_REG, &val, 1); | |
+ if (chip->ptn_revision == HAP_PTN_V1) { | |
+ val[0] = MOD_STATUS_SEL_FIFO_FILL_STATUS_VAL; | |
+ rc = haptics_write(chip, chip->cfg_addr_base, | |
+ HAP_CFG_MOD_STATUS_SEL_REG, val, 1); | |
if (rc < 0) | |
return rc; | |
- val = 0; | |
- rc = haptics_write(chip, chip->ptn_addr_base, | |
- HAP_PTN_MEM_OP_ACCESS_REG, &val, 1); | |
+ rc = haptics_read(chip, chip->cfg_addr_base, | |
+ HAP_CFG_STATUS_DATA_MSB_REG, val, 1); | |
if (rc < 0) | |
return rc; | |
- } | |
- | |
- return haptics_update_memory_data(chip, samples, length); | |
-} | |
- | |
-static int haptics_update_pat_mem_samples(struct haptics_chip *chip, | |
- enum pat_mem_sel pat_sel, u8 *samples, u32 length) | |
-{ | |
- int rc; | |
- u8 val; | |
- | |
- if (!samples) { | |
- dev_err(chip->dev, "no data available to update PAT_MEM\n"); | |
- return -EINVAL; | |
- } | |
- | |
- /* only HAP525_HV supports PATx_MEM pattern source */ | |
- if (chip->hw_type != HAP525_HV) { | |
- dev_dbg(chip->dev, "HW type %d doesn't support PATx_MEM pattern source\n", | |
- chip->hw_type); | |
- return 0; | |
- } | |
- val = FIELD_PREP(MEM_PAT_RW_SEL_MASK, pat_sel); | |
- val |= MEM_PAT_ACCESS_BIT | MEM_FLUSH_RELOAD_BIT; | |
- rc = haptics_write(chip, chip->ptn_addr_base, | |
- HAP_PTN_MEM_OP_ACCESS_REG, &val, 1); | |
- if (rc < 0) | |
- return rc; | |
- | |
- val &= ~MEM_FLUSH_RELOAD_BIT; | |
- rc = haptics_write(chip, chip->ptn_addr_base, | |
- HAP_PTN_MEM_OP_ACCESS_REG, &val, 1); | |
- if (rc < 0) | |
- return rc; | |
- | |
- return haptics_update_memory_data(chip, samples, length); | |
-} | |
+ *fill = val[0] & FIFO_REAL_TIME_FILL_STATUS_MASK_V1; | |
+ } else { | |
+ val[0] = MOD_STATUS_XT_V2_FIFO_FILL_STATUS_VAL; | |
+ rc = haptics_write(chip, chip->cfg_addr_base, | |
+ HAP_CFG_MOD_STATUS_XT_V2_REG, val, 1); | |
+ if (rc < 0) | |
+ return rc; | |
-static int haptics_get_fifo_fill_status(struct haptics_chip *chip, u32 *fill) | |
-{ | |
- int rc; | |
- u8 val[2], fill_status_mask; | |
- u32 filled, available; | |
- bool empty = false, full = false; | |
+ val[0] = MOD_STATUS_SEL_FIFO_FILL_STATUS_VAL; | |
+ rc = haptics_write(chip, chip->cfg_addr_base, | |
+ HAP_CFG_MOD_STATUS_SEL_REG, val, 1); | |
+ if (rc < 0) | |
+ return rc; | |
- rc = haptics_get_status_data(chip, FIFO_REAL_TIME_STS, val); | |
- if (rc < 0) | |
- return rc; | |
+ rc = haptics_read(chip, chip->cfg_addr_base, | |
+ HAP_CFG_STATUS_DATA_MSB_REG, val, 2); | |
+ if (rc < 0) | |
+ return rc; | |
- switch (chip->hw_type) { | |
- case HAP520: | |
- fill_status_mask = FIFO_REAL_TIME_FILL_STATUS_MSB_MASK_V2; | |
- break; | |
- case HAP520_MV: | |
- fill_status_mask = FIFO_REAL_TIME_FILL_STATUS_MSB_MASK_V3; | |
- break; | |
- case HAP525_HV: | |
- fill_status_mask = FIFO_REAL_TIME_FILL_STATUS_MSB_MASK_V4; | |
- break; | |
- default: | |
- dev_err(chip->dev, "HW type %d is not supported\n", | |
- chip->hw_type); | |
- return -EINVAL; | |
+ *fill = ((val[0] & FIFO_REAL_TIME_FILL_STATUS_MSB_MASK_V2) | |
+ << 8) | val[1]; | |
+ empty = !!(val[0] & FIFO_EMPTY_FLAG_BIT_V2); | |
+ full = !!(val[0] & FIFO_FULL_FLAG_BIT_V2); | |
} | |
- filled = ((val[0] & fill_status_mask) << 8) | val[1]; | |
- empty = !!(val[0] & FIFO_EMPTY_FLAG_BIT); | |
- full = !!(val[0] & FIFO_FULL_FLAG_BIT); | |
- available = get_max_fifo_samples(chip) - filled; | |
- | |
- dev_dbg(chip->dev, "filled=%u, available=%u, full=%d, empty=%d\n", | |
- filled, available, full, empty); | |
- trace_qcom_haptics_fifo_hw_status(filled, available, full, empty); | |
- *fill = filled; | |
+ dev_dbg(chip->dev, "filled=%d, full=%d, empty=%d\n", *fill, full, empty); | |
return 0; | |
} | |
@@ -1902,16 +1722,16 @@ static int haptics_get_available_fifo_memory(struct haptics_chip *chip) | |
if (rc < 0) | |
return rc; | |
- if (fill > get_max_fifo_samples(chip)) { | |
+ if (fill > MAX_FIFO_SAMPLES(chip)) { | |
dev_err(chip->dev, "Filled FIFO number %d exceed the max %d\n", | |
- fill, get_max_fifo_samples(chip)); | |
+ fill, MAX_FIFO_SAMPLES(chip)); | |
return -EINVAL; | |
- } else if (fill == get_max_fifo_samples(chip)) { | |
+ } else if (fill == MAX_FIFO_SAMPLES(chip)) { | |
dev_err(chip->dev, "no FIFO space available\n"); | |
return -EBUSY; | |
} | |
- available = get_max_fifo_samples(chip) - fill; | |
+ available = MAX_FIFO_SAMPLES(chip) - fill; | |
return available; | |
} | |
@@ -1939,14 +1759,70 @@ static int haptics_set_manual_rc_clk_cal(struct haptics_chip *chip) | |
val[0]); | |
} | |
+static int haptics_update_fifo_samples(struct haptics_chip *chip, | |
+ u8 *samples, u32 length) | |
+{ | |
+ int rc = 0, count, i, remain; | |
+ u8 tmp[HAP_PTN_V2_FIFO_DIN_NUM] = {0}; | |
+ | |
+ if (samples == NULL) { | |
+ dev_err(chip->dev, "no FIFO samples available\n"); | |
+ return -EINVAL; | |
+ } | |
+ | |
+ if (!length) | |
+ return 0; | |
+ | |
+ if (chip->ptn_revision == HAP_PTN_V1) { | |
+ for (i = 0; i < length; i++) { | |
+ rc = haptics_update_fifo_sample_v1(chip, samples[i]); | |
+ if (rc < 0) | |
+ return rc; | |
+ } | |
+ } else { | |
+ count = length / HAP_PTN_V2_FIFO_DIN_NUM; | |
+ remain = length % HAP_PTN_V2_FIFO_DIN_NUM; | |
+ for (i = 0; i < count; i++) { | |
+ rc = haptics_update_fifo_sample_v2(chip, | |
+ samples, HAP_PTN_V2_FIFO_DIN_NUM); | |
+ if (rc < 0) | |
+ return rc; | |
+ | |
+ samples += HAP_PTN_V2_FIFO_DIN_NUM; | |
+ } | |
+ | |
+ if (remain) { | |
+ /* | |
+ * In HAP_PTN_V2 module, when 1-byte FIFO write clashes | |
+ * with the HW FIFO read operation, the HW will only read | |
+ * 1 valid byte in every 4 bytes FIFO samples. So avoid | |
+ * this by keeping the samples 4-byte aligned and always | |
+ * use 4-byte write for HAP_PTN_V2 module. | |
+ */ | |
+ if (chip->ptn_revision == HAP_PTN_V2) { | |
+ memcpy(tmp, samples, remain); | |
+ rc = haptics_update_fifo_sample_v2(chip, | |
+ tmp, HAP_PTN_V2_FIFO_DIN_NUM); | |
+ } else { | |
+ rc = haptics_update_fifo_sample_v2(chip, | |
+ samples, remain); | |
+ } | |
+ } | |
+ } | |
+ | |
+ return rc; | |
+} | |
+ | |
static int haptics_set_fifo_playrate(struct haptics_chip *chip, | |
enum s_period period_per_s) | |
{ | |
int rc; | |
+ u8 reg; | |
+ reg = (chip->ptn_revision == HAP_PTN_V1) ? | |
+ HAP_PTN_V1_FIFO_PLAY_RATE_REG : HAP_PTN_V2_FIFO_PLAY_RATE_REG; | |
rc = haptics_masked_write(chip, chip->ptn_addr_base, | |
- HAP_PTN_FIFO_PLAY_RATE_REG, | |
- FIFO_PLAY_RATE_MASK, period_per_s); | |
+ reg, FIFO_PLAY_RATE_MASK, period_per_s); | |
if (rc < 0) | |
dev_err(chip->dev, "Set FIFO play rate failed, rc=%d\n", rc); | |
@@ -1956,17 +1832,15 @@ static int haptics_set_fifo_playrate(struct haptics_chip *chip, | |
static int haptics_set_fifo_empty_threshold(struct haptics_chip *chip, | |
u32 thresh) | |
{ | |
- u8 thresh_per_bit; | |
+ u8 reg, thresh_per_bit; | |
int rc; | |
- rc = get_fifo_threshold_per_bit(chip); | |
- if (rc < 0) | |
- return rc; | |
- | |
- thresh_per_bit = rc; | |
+ reg = (chip->ptn_revision == HAP_PTN_V1) ? | |
+ HAP_PTN_V1_FIFO_EMPTY_CFG_REG : HAP_PTN_V2_FIFO_EMPTY_CFG_REG; | |
+ thresh_per_bit = (chip->ptn_revision == HAP_PTN_V1) ? | |
+ HAP_PTN_V1_FIFO_THRESH_LSB : HAP_PTN_V2_FIFO_THRESH_LSB; | |
rc = haptics_masked_write(chip, chip->ptn_addr_base, | |
- HAP_PTN_FIFO_EMPTY_CFG_REG, | |
- EMPTY_THRESH_MASK, (thresh / thresh_per_bit)); | |
+ reg, EMPTY_THRESH_MASK, thresh / thresh_per_bit); | |
if (rc < 0) | |
dev_err(chip->dev, "Set FIFO empty threshold failed, rc=%d\n", | |
rc); | |
@@ -1986,6 +1860,40 @@ static void haptics_fifo_empty_irq_config(struct haptics_chip *chip, | |
} | |
} | |
+static int haptics_module_enable(struct haptics_chip *chip, bool enable) | |
+{ | |
+ u8 val; | |
+ int rc; | |
+ | |
+ val = enable ? HAPTICS_EN_BIT : 0; | |
+ rc = haptics_write(chip, chip->cfg_addr_base, | |
+ HAP_CFG_EN_CTL_REG, &val, 1); | |
+ if (rc < 0) | |
+ return rc; | |
+ | |
+ dev_dbg(chip->dev, "haptics module %s\n", | |
+ enable ? "enabled" : "disabled"); | |
+ return 0; | |
+} | |
+ | |
+static int haptics_toggle_module_enable(struct haptics_chip *chip) | |
+{ | |
+ int rc; | |
+ | |
+ /* | |
+ * Updating HAPTICS_EN would vote hBoost enable status. Add 100us | |
+ * delay before updating HAPTICS_EN for hBoost to have enough time | |
+ * to handle its power transition. | |
+ */ | |
+ usleep_range(100, 101); | |
+ rc = haptics_module_enable(chip, false); | |
+ if (rc < 0) | |
+ return rc; | |
+ | |
+ usleep_range(100, 101); | |
+ return haptics_module_enable(chip, true); | |
+} | |
+ | |
static int haptics_set_fifo(struct haptics_chip *chip, struct fifo_cfg *fifo) | |
{ | |
struct fifo_play_status *status = &chip->play.fifo_status; | |
@@ -1997,6 +1905,13 @@ static int haptics_set_fifo(struct haptics_chip *chip, struct fifo_cfg *fifo) | |
return -EBUSY; | |
} | |
+ if (chip->ptn_revision == HAP_PTN_V1 && | |
+ fifo->period_per_s > F_8KHZ && | |
+ fifo->num_s > MAX_FIFO_SAMPLES(chip)) { | |
+ dev_err(chip->dev, "PM8350B v1 doesn't support playing long FIFO pattern higher than 8 KHz play rate\n"); | |
+ return -EINVAL; | |
+ } | |
+ | |
/* Configure FIFO play rate */ | |
rc = haptics_set_fifo_playrate(chip, fifo->period_per_s); | |
if (rc < 0) | |
@@ -2018,18 +1933,17 @@ static int haptics_set_fifo(struct haptics_chip *chip, struct fifo_cfg *fifo) | |
* more than MAX_FIFO_SAMPLES samples, the rest will be | |
* written if any FIFO memory is available after playing. | |
*/ | |
- num = min_t(u32, fifo->num_s, get_max_fifo_samples(chip)); | |
+ num = min_t(u32, fifo->num_s, MAX_FIFO_SAMPLES(chip)); | |
available = haptics_get_available_fifo_memory(chip); | |
if (available < 0) | |
return available; | |
num = min_t(u32, available, num); | |
- num = min_t(u32, num, FIFO_PRGM_INIT_SIZE); | |
/* Keep the FIFO programming 4-byte aligned if FIFO refilling is needed */ | |
- if ((num < fifo->num_s) && (num % HAP_PTN_FIFO_DIN_NUM)) | |
- num = round_down(num, HAP_PTN_FIFO_DIN_NUM); | |
+ if ((num < fifo->num_s) && (num % HAP_PTN_V2_FIFO_DIN_NUM)) | |
+ num = round_down(num, HAP_PTN_V2_FIFO_DIN_NUM); | |
- rc = haptics_update_fifo_samples(chip, fifo->samples, num, false); | |
+ rc = haptics_update_fifo_samples(chip, fifo->samples, num); | |
if (rc < 0) { | |
dev_err(chip->dev, "write FIFO samples failed, rc=%d\n", rc); | |
return rc; | |
@@ -2037,7 +1951,6 @@ static int haptics_set_fifo(struct haptics_chip *chip, struct fifo_cfg *fifo) | |
atomic_set(&status->is_busy, 1); | |
status->samples_written = num; | |
- trace_qcom_haptics_fifo_prgm_status(fifo->num_s, status->samples_written, num); | |
if (num == fifo->num_s) { | |
fifo_thresh = 0; | |
atomic_set(&status->written_done, 1); | |
@@ -2077,7 +1990,7 @@ static int haptics_load_constant_effect(struct haptics_chip *chip, u8 amplitude) | |
play->effect = NULL; | |
/* Fix Vmax to (hpwr_vreg_mv - hdrm_mv) in non-HBOOST regulator case */ | |
- if (is_haptics_external_powered(chip)) { | |
+ if (chip->hpwr_vreg) { | |
rc = haptics_get_vmax_headroom_mv(chip, &hdrm_mv); | |
if (rc < 0) | |
goto unlock; | |
@@ -2102,11 +2015,17 @@ static int haptics_load_constant_effect(struct haptics_chip *chip, u8 amplitude) | |
if (rc < 0) | |
goto unlock; | |
+#if 1 | |
+ /* Always disable LRA auto resonance for DIRECT_PLAY */ | |
+ rc = haptics_enable_autores(chip, chip->config.is_erm); | |
+ if (rc < 0) | |
+ goto unlock; | |
+#else | |
/* Always enable LRA auto resonance for DIRECT_PLAY */ | |
rc = haptics_enable_autores(chip, !chip->config.is_erm); | |
if (rc < 0) | |
goto unlock; | |
- | |
+#endif | |
play->pattern_src = DIRECT_PLAY; | |
unlock: | |
mutex_unlock(&chip->play.lock); | |
@@ -2129,14 +2048,15 @@ static int haptics_load_predefined_effect(struct haptics_chip *chip, | |
return rc; | |
play->pattern_src = play->effect->src; | |
- if (play->pattern_src == DIRECT_PLAY || | |
- play->pattern_src == SWR) { | |
+ if (play->pattern_src != PATTERN1 && | |
+ play->pattern_src != PATTERN2 && | |
+ play->pattern_src != FIFO) { | |
dev_err(chip->dev, "pattern src %d can't be used for predefined effect\n", | |
play->pattern_src); | |
return -EINVAL; | |
} | |
- if ((play->pattern_src == FIFO) && (chip->wa_flags & TOGGLE_EN_TO_FLUSH_FIFO)) { | |
+ if (play->pattern_src == FIFO) { | |
/* Toggle HAPTICS_EN for a clear start point of FIFO playing */ | |
rc = haptics_toggle_module_enable(chip); | |
if (rc < 0) | |
@@ -2174,25 +2094,6 @@ static int haptics_load_predefined_effect(struct haptics_chip *chip, | |
return rc; | |
} | |
- /* | |
- * PATTERN_MEM sources (PATx_MEM) introduced in HAP525_HV haptics | |
- * module are used for preload effects. The pattern for the preload | |
- * effect should have been programmed during boot up and it will be | |
- * retained until device is powered off, so it doesn't need to be | |
- * programmed at runtime. | |
- */ | |
- if (chip->hw_type == HAP525_HV && | |
- play->pattern_src == PATTERN_MEM) { | |
- if (!play->effect->fifo->preload) { | |
- dev_err(chip->dev, "effect %d has PAT_MEM src but not preloaded\n", | |
- play->effect->id); | |
- return -EINVAL; | |
- } | |
- | |
- dev_dbg(chip->dev, "Ignore loading data for preload FIFO effect: %d\n", | |
- play->effect->id); | |
- } | |
- | |
return 0; | |
} | |
@@ -2285,6 +2186,8 @@ static int haptics_load_custom_effect(struct haptics_chip *chip, | |
dev_dbg(chip->dev, "custom data length %d with play-rate %d Hz\n", | |
custom_data.length, custom_data.play_rate_hz); | |
+ printk("haptic_d: %s: custom data length %d with play-rate %d Hz\n", | |
+ __func__, custom_data.length, custom_data.play_rate_hz); | |
rc = haptics_convert_sample_period(chip, custom_data.play_rate_hz); | |
if (rc < 0) { | |
dev_err(chip->dev, "Can't support play rate: %d Hz\n", | |
@@ -2334,11 +2237,9 @@ static int haptics_load_custom_effect(struct haptics_chip *chip, | |
goto cleanup; | |
/* Toggle HAPTICS_EN for a clear start point of FIFO playing */ | |
- if (chip->wa_flags & TOGGLE_EN_TO_FLUSH_FIFO) { | |
- rc = haptics_toggle_module_enable(chip); | |
- if (rc < 0) | |
- goto cleanup; | |
- } | |
+ rc = haptics_toggle_module_enable(chip); | |
+ if (rc < 0) | |
+ goto cleanup; | |
rc = haptics_enable_autores(chip, !play->effect->auto_res_disable); | |
if (rc < 0) | |
@@ -2359,12 +2260,13 @@ static int haptics_load_custom_effect(struct haptics_chip *chip, | |
return rc; | |
} | |
-static u32 get_play_length_effect_us(struct haptics_effect *effect) | |
+static u32 get_play_length_us(struct haptics_play_info *play) | |
{ | |
+ struct haptics_effect *effect = play->effect; | |
u32 length_us = 0; | |
- if (effect->brake) | |
- length_us = effect->brake->play_length_us; | |
+ if (play->brake) | |
+ length_us = play->brake->play_length_us; | |
if ((effect->src == PATTERN1 || effect->src == PATTERN2) | |
&& effect->pattern) | |
@@ -2375,70 +2277,45 @@ static u32 get_play_length_effect_us(struct haptics_effect *effect) | |
return length_us; | |
} | |
-static inline u32 get_play_length_us(struct haptics_play_info *play) | |
-{ | |
- return get_play_length_effect_us(play->effect); | |
-} | |
- | |
-#define PRIMITIVE_EFFECT_ID_BIT BIT(15) | |
-#define PRIMITIVE_EFFECT_ID_MASK GENMASK(14, 0) | |
static int haptics_load_periodic_effect(struct haptics_chip *chip, | |
s16 __user *data, u32 length, s16 magnitude) | |
{ | |
struct haptics_play_info *play = &chip->play; | |
s16 custom_data[CUSTOM_DATA_LEN] = { 0 }; | |
- struct haptics_effect *effects = NULL; | |
- s16 custom_id = 0; | |
- int effects_count = 0; | |
int rc, i; | |
- bool primitive; | |
+ | |
+ if (chip->effects_count == 0) | |
+ return -EINVAL; | |
if (copy_from_user(custom_data, data, sizeof(custom_data))) | |
return -EFAULT; | |
- primitive = !!(custom_data[CUSTOM_DATA_EFFECT_IDX] & PRIMITIVE_EFFECT_ID_BIT); | |
- | |
- if (primitive) { | |
- if (chip->primitives_count == 0) | |
- return -EINVAL; | |
- | |
- custom_id = custom_data[CUSTOM_DATA_EFFECT_IDX] & PRIMITIVE_EFFECT_ID_MASK; | |
- effects = chip->primitives; | |
- effects_count = chip->primitives_count; | |
- } else { | |
- if (chip->effects_count == 0) | |
- return -EINVAL; | |
- | |
- custom_id = custom_data[CUSTOM_DATA_EFFECT_IDX]; | |
- effects = chip->effects; | |
- effects_count = chip->effects_count; | |
- } | |
- | |
- for (i = 0; i < effects_count; i++) | |
- if (effects[i].id == custom_id) | |
+ for (i = 0; i < chip->effects_count; i++) | |
+ if (chip->effects[i].id == custom_data[CUSTOM_DATA_EFFECT_IDX]) | |
break; | |
- if (i == effects_count) { | |
+ if (i == chip->effects_count) { | |
dev_err(chip->dev, "effect%d is not supported!\n", | |
custom_data[CUSTOM_DATA_EFFECT_IDX]); | |
return -EINVAL; | |
} | |
mutex_lock(&chip->play.lock); | |
+ | |
if (chip->play.in_calibration) { | |
dev_err(chip->dev, "calibration in progress, ignore playing predefined effect\n"); | |
rc = -EBUSY; | |
goto unlock; | |
} | |
- play->vmax_mv = (magnitude * effects[i].vmax_mv) / 0x7fff; | |
- dev_dbg(chip->dev, "upload %s effect %d, vmax=%d\n", primitive ? "primitive" : "predefined", | |
- effects[i].id, play->vmax_mv); | |
- | |
- rc = haptics_load_predefined_effect(chip, &effects[i]); | |
+ play->vmax_mv = (magnitude * chip->effects[i].vmax_mv) / 0x7fff; | |
+ | |
+ dev_err(chip->dev, "haptics_load_periodic_effect, effect_id:%d, play_vmax_mv:%d(play_vmax_mv:%d * magnitude:%d).\n", | |
+ chip->effects[i].id, play->vmax_mv, chip->effects[i].vmax_mv, magnitude); | |
+ rc = haptics_load_predefined_effect(chip, &chip->effects[i]); | |
if (rc < 0) { | |
dev_err(chip->dev, "Play predefined effect%d failed, rc=%d\n", | |
- effects[i].id, rc); | |
+ chip->effects[i].id, rc); | |
goto unlock; | |
} | |
mutex_unlock(&chip->play.lock); | |
@@ -2463,7 +2340,7 @@ static u8 get_direct_play_max_amplitude(struct haptics_chip *chip) | |
u32 amplitude = DIRECT_PLAY_MAX_AMPLITUDE, hdrm_mv; | |
int rc; | |
- if (is_haptics_external_powered(chip)) { | |
+ if (chip->hpwr_vreg) { | |
rc = haptics_get_vmax_headroom_mv(chip, &hdrm_mv); | |
if (rc < 0) | |
return 0; | |
@@ -2534,8 +2411,13 @@ static int haptics_upload_effect(struct input_dev *dev, | |
tmp = get_direct_play_max_amplitude(chip); | |
tmp *= level; | |
amplitude = tmp / 0x7fff; | |
- dev_dbg(chip->dev, "upload constant effect, length = %dus, amplitude = %#x\n", | |
- length_us, amplitude); | |
+ dev_err(chip->dev, "haptics_upload_effect FF_CONSTANT, length_us = %dus, effect strength = %d, amplitude = %#x\n", length_us, level, amplitude); | |
+ | |
+ if(amplitude > 235){ | |
+ amplitude = 235; | |
+ dev_err(chip->dev, "SZ limit the max amplitude to 235.\n"); | |
+ } | |
+ | |
haptics_load_constant_effect(chip, amplitude); | |
if (rc < 0) { | |
dev_err(chip->dev, "set direct play failed, rc=%d\n", | |
@@ -2549,7 +2431,9 @@ static int haptics_upload_effect(struct input_dev *dev, | |
dev_err(chip->dev, "Only support custom waveforms\n"); | |
return -EINVAL; | |
} | |
- | |
+ | |
+ dev_err(chip->dev, "haptics_upload_effect FF_PERIODIC, magnitude:%x\n", effect->u.periodic.magnitude); | |
+ | |
if (effect->u.periodic.custom_len == | |
sizeof(struct custom_fifo_data)) { | |
rc = haptics_load_custom_effect(chip, | |
@@ -2611,7 +2495,8 @@ static int haptics_playback(struct input_dev *dev, int effect_id, int val) | |
struct haptics_play_info *play = &chip->play; | |
int rc; | |
- dev_dbg(chip->dev, "playback val = %d\n", val); | |
+ dev_err(chip->dev, "haptics_playback, effect_id:%d, val:%d\n", effect_id, val); | |
+ | |
if (!!val) { | |
rc = haptics_enable_play(chip, true); | |
if (rc < 0) | |
@@ -2673,7 +2558,7 @@ static void haptics_set_gain(struct input_dev *dev, u16 gain) | |
if (gain > 0x7fff) | |
gain = 0x7fff; | |
- dev_dbg(chip->dev, "Set gain: %#x\n", gain); | |
+ dev_err(chip->dev, "Set gain: %#x\n", gain); | |
/* scale amplitude when playing in DIRECT_PLAY mode */ | |
if (chip->play.pattern_src == DIRECT_PLAY) { | |
@@ -2681,7 +2566,13 @@ static void haptics_set_gain(struct input_dev *dev, u16 gain) | |
amplitude *= gain; | |
amplitude /= 0x7fff; | |
- dev_dbg(chip->dev, "Set amplitude: %#x\n", amplitude); | |
+ dev_err(chip->dev, "Set amplitude: %#x\n", amplitude); | |
+ | |
+ if(amplitude > 235){ | |
+ amplitude = 235; | |
+ dev_err(chip->dev, "SZ limit the max amplitude to 235.\n"); | |
+ } | |
+ | |
haptics_set_direct_play(chip, (u8)amplitude); | |
return; | |
} | |
@@ -2701,16 +2592,23 @@ static void haptics_set_gain(struct input_dev *dev, u16 gain) | |
static int haptics_store_cl_brake_settings(struct haptics_chip *chip) | |
{ | |
int rc = 0; | |
- u8 val[2]; | |
+ u8 val; | |
if (!chip->cl_brake_nvmem) | |
return 0; | |
- rc = haptics_get_status_data(chip, RNAT_RCAL_INT, val); | |
+ val = MOD_STATUS_SEL_BRAKE_CAL_RNAT_RCAL_VAL; | |
+ rc = haptics_write(chip, chip->cfg_addr_base, | |
+ HAP_CFG_MOD_STATUS_SEL_REG, &val, 1); | |
+ if (rc < 0) | |
+ return rc; | |
+ | |
+ rc = haptics_read(chip, chip->cfg_addr_base, | |
+ HAP_CFG_STATUS_DATA_LSB_REG, &val, 1); | |
if (rc < 0) | |
return rc; | |
- rc = nvmem_cell_write(chip->cl_brake_nvmem, &val[1], 1); | |
+ rc = nvmem_cell_write(chip->cl_brake_nvmem, &val, sizeof(val)); | |
if (rc < 0) | |
dev_err(chip->dev, "store RNAT/RCAL to SDAM failed, rc=%d\n"); | |
@@ -2736,406 +2634,117 @@ static int haptics_config_openloop_lra_period(struct haptics_chip *chip, | |
HAP_CFG_TLRA_OL_HIGH_REG, val, 2); | |
} | |
-static int haptics_config_preload_fifo_effect(struct haptics_chip *chip, | |
- struct haptics_effect *effect) | |
-{ | |
- int rc; | |
- | |
- if (!effect->fifo->preload) { | |
- dev_err(chip->dev, "effect %d doesn't support preload\n", | |
- effect->id); | |
- return -EINVAL; | |
- } | |
- | |
- if (effect->src != PATTERN_MEM) { | |
- dev_err(chip->dev, "effect %d pattern_src is not PATTERN_MEM\n", | |
- effect->id); | |
- return -EINVAL; | |
- } | |
- | |
- rc = haptics_update_pat_mem_samples(chip, effect->pat_sel, | |
- effect->fifo->samples, effect->fifo->num_s); | |
- if (!rc) | |
- dev_dbg(chip->dev, "effect %d is preloaded in PAT_MEM %d\n", | |
- effect->id, effect->pat_sel); | |
- return rc; | |
-} | |
- | |
-static int haptics_mmap_config(struct haptics_chip *chip) | |
+static int haptics_hw_init(struct haptics_chip *chip) | |
{ | |
- int rc, i, left; | |
- u8 val[4]; | |
- | |
- /* | |
- * Make the FIFO memory size 128-byte aligned, and append | |
- * the leftover memory bytes to PAT1_MEM. | |
- */ | |
- left = chip->mmap.fifo_mmap.length % MMAP_FIFO_LEN_PER_LSB; | |
- if (left) { | |
- chip->mmap.fifo_mmap.length -= left; | |
- chip->mmap.pat_sel_mmap[PAT1_MEM].length += left; | |
- } | |
- | |
- /* config MMAP_FIFO */ | |
- val[0] = chip->mmap.fifo_mmap.length / MMAP_FIFO_LEN_PER_LSB; | |
- if (val[0]-- == 0) { | |
- dev_err(chip->dev, "fifo length %d is less than %d\n", | |
- chip->mmap.fifo_mmap.length, | |
- MMAP_FIFO_LEN_PER_LSB); | |
- return -EINVAL; | |
- } | |
+ struct haptics_hw_config *config = &chip->config; | |
+ struct haptics_effect *effect; | |
+ int rc = 0, i; | |
+ u8 val[2]; | |
+ u32 t_lra_us; | |
- val[0] &= MMAP_FIFO_LEN_MASK; | |
- val[0] |= MMAP_FIFO_EXIST_BIT; | |
- rc = haptics_write(chip, chip->ptn_addr_base, | |
- HAP_PTN_MMAP_FIFO_REG, val, 1); | |
+ /* Store CL brake settings */ | |
+ rc = haptics_store_cl_brake_settings(chip); | |
if (rc < 0) | |
return rc; | |
- /* config MMAP_PAT1/2/3/4 */ | |
- for (i = PAT1_MEM; i <= PAT4_MEM; i++) | |
- val[i] = min(chip->mmap.pat_sel_mmap[i].length, chip->mmap.pat_sel_mmap[i].max_size) | |
- / MMAP_PAT_LEN_PER_LSB; | |
+ rc = haptics_read(chip, chip->hbst_addr_base, | |
+ HAP_BOOST_CLAMP_5V_REG_OFFSET(chip), val, 1); | |
+ if (rc < 0) | |
+ return rc; | |
- rc = haptics_write(chip, chip->ptn_addr_base, | |
- HAP_PTN_MMAP_PAT1_REG, val, 4); | |
+ chip->clamp_at_5v = val[0] & CLAMP_5V_BIT; | |
+ /* Config VMAX */ | |
+ rc = haptics_set_vmax_mv(chip, config->vmax_mv); | |
if (rc < 0) | |
return rc; | |
- /* config PATx_PLAY_RATE */ | |
- rc = haptics_masked_write(chip, chip->ptn_addr_base, | |
- HAP_PTN_FIFO_PLAY_RATE_REG, PAT_MEM_PLAY_RATE_MASK, | |
- FIELD_PREP(PAT_MEM_PLAY_RATE_MASK, chip->mmap.pat_play_rate)); | |
- if (rc < 0) { | |
- dev_err(chip->dev, "Set pat_mem play rate failed, rc=%d\n", rc); | |
+ /* Config driver waveform shape */ | |
+ rc = haptics_masked_write(chip, chip->cfg_addr_base, | |
+ HAP_CFG_DRV_WF_SEL_REG, | |
+ DRV_WF_SEL_MASK, config->drv_wf); | |
+ if (rc < 0) | |
return rc; | |
- } | |
- dev_dbg(chip->dev, "haptics memory map configured with FIFO: %d, PAT1:%d, PAT2: %d, PAT3: %d, PAT4: %d\n", | |
- chip->mmap.fifo_mmap.length, | |
- chip->mmap.pat_sel_mmap[PAT1_MEM].length, | |
- chip->mmap.pat_sel_mmap[PAT2_MEM].length, | |
- chip->mmap.pat_sel_mmap[PAT3_MEM].length, | |
- chip->mmap.pat_sel_mmap[PAT4_MEM].length); | |
- return 0; | |
-} | |
+ /* Config brake mode and waveform shape */ | |
+ val[0] = (config->brake.mode << BRAKE_MODE_SHIFT) | |
+ | config->brake.sine_gain << BRAKE_SINE_GAIN_SHIFT | |
+ | config->brake.brake_wf; | |
+ rc = haptics_masked_write(chip, chip->cfg_addr_base, | |
+ HAP_CFG_BRAKE_MODE_CFG_REG, | |
+ BRAKE_MODE_MASK | BRAKE_SINE_GAIN_MASK | |
+ | BRAKE_WF_SEL_MASK, val[0]); | |
+ if (rc < 0) | |
+ return rc; | |
-static int haptics_mmap_preload_fifo_effect(struct haptics_chip *chip, | |
- struct haptics_effect *effect) | |
-{ | |
- int i; | |
- u32 length, fifo_length; | |
- | |
- if (!effect->fifo->preload) { | |
- dev_err(chip->dev, "effect %d doesn't support preload\n"); | |
- return -EINVAL; | |
- } | |
- | |
- if (chip->mmap.pat_play_rate == F_RESERVED) { | |
- chip->mmap.pat_play_rate = effect->fifo->period_per_s; | |
- } else if (chip->mmap.pat_play_rate != effect->fifo->period_per_s) { | |
- dev_warn(chip->dev, "PATx_MEM sources only support one play rate\n"); | |
- goto mmap_failed; | |
- } | |
- | |
- length = effect->fifo->num_s; | |
- if (length % MMAP_PAT_LEN_PER_LSB) | |
- length = (length / MMAP_PAT_LEN_PER_LSB + 1) * MMAP_PAT_LEN_PER_LSB; | |
- | |
- fifo_length = chip->mmap.fifo_mmap.length - length; | |
- if (fifo_length < MMAP_FIFO_MIN_SIZE) { | |
- dev_warn(chip->dev, "not enough space for preload FIFO effect\n"); | |
- goto mmap_failed; | |
- } | |
- | |
- for (i = PAT4_MEM; i >= PAT1_MEM; i--) { | |
- if (!chip->mmap.pat_sel_mmap[i].in_use && | |
- (length <= chip->mmap.pat_sel_mmap[i].max_size)) | |
- break; | |
- } | |
- | |
- if (i < PAT1_MEM) { | |
- dev_warn(chip->dev, "no PAT_MEM source available\n"); | |
- effect->fifo->preload = false; | |
- goto mmap_failed; | |
- } | |
- | |
- /* update the mmap configuration */ | |
- chip->mmap.pat_sel_mmap[i].in_use = true; | |
- chip->mmap.pat_sel_mmap[i].length = length; | |
- chip->mmap.fifo_mmap.length = fifo_length; | |
- | |
- /* Update the effect pattern_src and pat_sel for the preload effect */ | |
- effect->src = PATTERN_MEM; | |
- effect->pat_sel = i; | |
- return 0; | |
- | |
- /* if mmap is failed then the effect couldn't be preloaded */ | |
-mmap_failed: | |
- effect->fifo->preload = false; | |
- return -ENOSPC; | |
-} | |
- | |
-static void haptics_mmap_init(struct haptics_chip *chip) | |
-{ | |
- u32 max_pat_mem_size = MMAP_NUM_BYTES - MMAP_FIFO_MIN_SIZE; | |
- | |
- /* Assume that all memory space is used for FIFO mode by default */ | |
- chip->mmap.fifo_mmap.in_use = true; | |
- chip->mmap.fifo_mmap.length = MMAP_NUM_BYTES; | |
- chip->mmap.fifo_mmap.max_size = MMAP_NUM_BYTES; | |
- | |
- /* different PATx_MEM partition has different maximum size */ | |
- chip->mmap.pat_sel_mmap[PAT1_MEM].max_size = min(max_pat_mem_size, | |
- (u32)MMAP_PAT1_LEN_MASK * MMAP_PAT_LEN_PER_LSB); | |
- chip->mmap.pat_sel_mmap[PAT2_MEM].max_size = min(max_pat_mem_size, | |
- (u32)MMAP_PAT2_LEN_MASK * MMAP_PAT_LEN_PER_LSB); | |
- chip->mmap.pat_sel_mmap[PAT3_MEM].max_size = min(max_pat_mem_size, | |
- (u32)MMAP_PAT3_PAT4_LEN_MASK * MMAP_PAT_LEN_PER_LSB); | |
- chip->mmap.pat_sel_mmap[PAT4_MEM].max_size = min(max_pat_mem_size, | |
- (u32)MMAP_PAT3_PAT4_LEN_MASK * MMAP_PAT_LEN_PER_LSB); | |
- chip->mmap.pat_play_rate = F_RESERVED; | |
-} | |
- | |
-static int haptics_init_fifo_memory(struct haptics_chip *chip) | |
-{ | |
- struct haptics_effect *effect; | |
- int rc, i; | |
- | |
- if (chip->hw_type != HAP525_HV) { | |
- dev_dbg(chip->dev, "HW type %d doesn't support mmap\n", | |
- chip->hw_type); | |
- return 0; | |
- } | |
- | |
- haptics_mmap_init(chip); | |
- | |
- for (i = 0; i < chip->effects_count; i++) { | |
- effect = &chip->effects[i]; | |
- if (!effect->fifo || !effect->fifo->preload) | |
- continue; | |
- | |
- rc = haptics_mmap_preload_fifo_effect(chip, effect); | |
- if (rc < 0 && rc != -ENOSPC) | |
- return rc; | |
- } | |
- | |
- rc = haptics_mmap_config(chip); | |
- if (rc < 0) | |
- return rc; | |
- | |
- for (i = 0; i < chip->effects_count; i++) { | |
- effect = &chip->effects[i]; | |
- if (!effect->fifo || !effect->fifo->preload) | |
- continue; | |
- | |
- rc = haptics_config_preload_fifo_effect(chip, effect); | |
+ /* Force VREG_RDY if non-HBoost is used for powering haptics */ | |
+ if (chip->hpwr_vreg) { | |
+ rc = haptics_masked_write(chip, chip->cfg_addr_base, | |
+ HAP_CFG_VSET_CFG_REG, FORCE_VREG_RDY_BIT, | |
+ FORCE_VREG_RDY_BIT); | |
if (rc < 0) | |
return rc; | |
} | |
- return 0; | |
-} | |
- | |
-static int haptics_init_preload_pattern_effect(struct haptics_chip *chip) | |
-{ | |
- struct haptics_hw_config *config = &chip->config; | |
- struct haptics_effect *effect; | |
- int i; | |
- | |
- if (config->preload_effect == -EINVAL) | |
+ if (config->is_erm) | |
return 0; | |
+ | |
+#if 1 | |
- for (i = 0; i < chip->effects_count; i++) | |
- if (chip->effects[i].id == config->preload_effect) | |
- break; | |
- | |
- if (i == chip->effects_count) { | |
- dev_err(chip->dev, "preload effect %d is not found\n", | |
- config->preload_effect); | |
- return -EINVAL; | |
- } | |
- | |
- effect = &chip->effects[i]; | |
- return haptics_set_pattern(chip, effect->pattern, effect->src); | |
-} | |
- | |
-static int haptics_init_lra_period_config(struct haptics_chip *chip) | |
-{ | |
- int rc = 0; | |
- u8 val; | |
- u32 t_lra_us; | |
+ //directly use default value because init too early cannot get calibration value. | |
+ t_lra_us=chip->config.t_lra_us; | |
+ printk("haptic_d: %s: t_lra_us=%d (%d Hz)\n", __func__, t_lra_us, USEC_PER_SEC/t_lra_us); | |
+#else | |
/* set AUTO_mode RC CLK calibration by default */ | |
- val = FIELD_PREP(CAL_RC_CLK_MASK, CAL_RC_CLK_AUTO_VAL); | |
+ val[0] = CAL_RC_CLK_AUTO_VAL << CAL_RC_CLK_SHIFT; | |
rc = haptics_masked_write(chip, chip->cfg_addr_base, | |
- HAP_CFG_CAL_EN_REG, CAL_RC_CLK_MASK, val); | |
+ HAP_CFG_CAL_EN_REG, CAL_RC_CLK_MASK, val[0]); | |
if (rc < 0) | |
return rc; | |
- /* Config T_LRA */ | |
+ /* get calibrated close loop period */ | |
t_lra_us = chip->config.t_lra_us; | |
rc = haptics_get_closeloop_lra_period(chip, true); | |
if (!rc && chip->config.cl_t_lra_us != 0) | |
t_lra_us = chip->config.cl_t_lra_us; | |
else | |
- dev_warn(chip->dev, "get closeloop LRA period failed, rc=%d\n", rc); | |
- | |
- return haptics_config_openloop_lra_period(chip, t_lra_us); | |
-} | |
- | |
-static int haptics_init_hpwr_config(struct haptics_chip *chip) | |
-{ | |
- int rc; | |
- u8 val; | |
- | |
- if ((chip->hw_type == HAP520_MV) && !chip->hpwr_vreg) { | |
- /* Indicates if HPWR is BOB or Bharger */ | |
- rc = haptics_read(chip, chip->cfg_addr_base, | |
- HAP_CFG_HPWR_INTF_CTL_REG, &val, 1); | |
- if (rc < 0) | |
- return rc; | |
- | |
- chip->hpwr_intf_ctl = val & INTF_CTL_MASK; | |
- | |
- /* Read HPWR voltage to adjust the VMAX */ | |
- if (chip->hpwr_voltage_mv == 0 && | |
- chip->hpwr_intf_ctl == INTF_CTL_BOB) { | |
- rc = haptics_read(chip, chip->cfg_addr_base, | |
- HAP_CFG_VHPWR_REG, &val, 1); | |
- if (rc < 0) | |
- return rc; | |
- | |
- chip->hpwr_voltage_mv = val * VHPWR_STEP_MV; | |
- } | |
- } | |
- | |
- /* Force VREG_RDY if non-HBoost is used for powering haptics */ | |
- if (is_haptics_external_powered(chip)) | |
- return haptics_masked_write(chip, chip->cfg_addr_base, | |
- HAP_CFG_VSET_CFG_REG, FORCE_VREG_RDY_BIT, | |
- FORCE_VREG_RDY_BIT); | |
- | |
- return 0; | |
-} | |
- | |
-static int haptics_init_drive_config(struct haptics_chip *chip) | |
-{ | |
- struct haptics_hw_config *config = &chip->config; | |
- int rc; | |
- u8 val; | |
+ dev_warn(chip->dev, "get closeloop LRA period failed, rc=%d\n", | |
+ rc); | |
+#endif | |
+ /* Config T_LRA */ | |
+ rc = haptics_config_openloop_lra_period(chip, t_lra_us); | |
+ if (rc < 0) | |
+ return rc; | |
- /* Config driver waveform shape and use 2's complement data format */ | |
+ /* Config to use 2's complement values for sample data */ | |
rc = haptics_masked_write(chip, chip->cfg_addr_base, | |
- HAP_CFG_DRV_WF_SEL_REG, | |
- DRV_WF_SEL_MASK | DRV_WF_FMT_BIT, config->drv_wf); | |
+ HAP_CFG_DRV_WF_SEL_REG, DRV_WF_FMT_BIT, 0); | |
if (rc < 0) | |
return rc; | |
- /* Config brake mode and waveform shape */ | |
- val = FIELD_PREP(BRAKE_MODE_MASK, config->brake.mode); | |
- val |= FIELD_PREP(BRAKE_SINE_GAIN_MASK, config->brake.sine_gain); | |
- val |= FIELD_PREP(BRAKE_WF_SEL_MASK, config->brake.brake_wf); | |
- | |
- return haptics_masked_write(chip, chip->cfg_addr_base, | |
- HAP_CFG_BRAKE_MODE_CFG_REG, | |
- BRAKE_MODE_MASK | BRAKE_SINE_GAIN_MASK | |
- | BRAKE_WF_SEL_MASK, val); | |
-} | |
- | |
-static int haptics_init_vmax_config(struct haptics_chip *chip) | |
-{ | |
- int rc; | |
- u8 val; | |
+ /* preload effect */ | |
+ if (config->preload_effect != -EINVAL) { | |
+ for (i = 0; i < chip->effects_count; i++) | |
+ if (chip->effects[i].id == config->preload_effect) | |
+ break; | |
- if (!is_haptics_external_powered(chip)) { | |
- rc = haptics_read(chip, chip->hbst_addr_base, | |
- HAP_BOOST_CLAMP_REG, &val, 1); | |
- if (rc < 0) | |
- return rc; | |
+ if (i == chip->effects_count) { | |
+ dev_err(chip->dev, "preload effect %d is not found\n", | |
+ config->preload_effect); | |
+ return -EINVAL; | |
+ } | |
- chip->clamp_at_5v = val & CLAMP_5V_BIT; | |
- } | |
+ effect = &chip->effects[i]; | |
- chip->is_hv_haptics = true; | |
- chip->max_vmax_mv = MAX_VMAX_MV; | |
- if (chip->hw_type == HAP520_MV || chip->hw_type == HAP525_HV) { | |
- rc = haptics_read(chip, chip->cfg_addr_base, | |
- HAP_CFG_HW_CONFIG_REG, &val, 1); | |
- if (rc < 0) | |
+ rc = haptics_set_pattern(chip, effect->pattern, effect->src); | |
+ if (rc < 0) { | |
+ dev_err(chip->dev, "Preload effect failed, rc=%d\n", | |
+ rc); | |
return rc; | |
- | |
- chip->is_hv_haptics = val & HV_HAP_DRIVER_BIT; | |
- chip->max_vmax_mv = (chip->is_hv_haptics) ? | |
- MAX_HV_VMAX_MV : MAX_MV_VMAX_MV; | |
- } | |
- | |
- /* Set the initial clamped vmax value when hBoost is used by charger firmware */ | |
- chip->clamped_vmax_mv = MAX_HV_VMAX_MV; | |
- /* Config VMAX */ | |
- return haptics_set_vmax_mv(chip, chip->config.vmax_mv); | |
-} | |
- | |
-static int haptics_config_wa(struct haptics_chip *chip) | |
-{ | |
- switch (chip->hw_type) { | |
- case HAP520: | |
- chip->wa_flags |= TOGGLE_CAL_RC_CLK | SW_CTRL_HBST | SLEEP_CLK_32K_SCALE | | |
- TOGGLE_EN_TO_FLUSH_FIFO | RECOVER_SWR_SLAVE; | |
- break; | |
- case HAP520_MV: | |
- if (!chip->cfg_rev1) | |
- chip->wa_flags |= TOGGLE_MODULE_EN; | |
- break; | |
- case HAP525_HV: | |
- if (chip->hbst_revision == HAP_BOOST_V0P1) | |
- chip->wa_flags |= SW_CTRL_HBST; | |
- break; | |
- default: | |
- dev_err(chip->dev, "HW type %d does not match\n", | |
- chip->hw_type); | |
- return -EINVAL; | |
+ } | |
} | |
- return 0; | |
-} | |
- | |
-static int haptics_hw_init(struct haptics_chip *chip) | |
-{ | |
- int rc; | |
- | |
- rc = haptics_config_wa(chip); | |
- if (rc < 0) | |
- return rc; | |
- | |
- rc = haptics_store_cl_brake_settings(chip); | |
- if (rc < 0) | |
- return rc; | |
- | |
- rc = haptics_init_vmax_config(chip); | |
- if (rc < 0) | |
- return rc; | |
- | |
- rc = haptics_init_drive_config(chip); | |
- if (rc < 0) | |
- return rc; | |
- | |
- rc = haptics_init_hpwr_config(chip); | |
- if (rc < 0) | |
- return rc; | |
- | |
- if (chip->config.is_erm) | |
- return 0; | |
- | |
- rc = haptics_init_lra_period_config(chip); | |
- if (rc < 0) | |
- return rc; | |
- | |
- rc = haptics_init_preload_pattern_effect(chip); | |
- if (rc < 0) | |
- return rc; | |
- | |
- return haptics_init_fifo_memory(chip); | |
+ return rc; | |
} | |
static irqreturn_t fifo_empty_irq_handler(int irq, void *data) | |
@@ -3165,9 +2774,9 @@ static irqreturn_t fifo_empty_irq_handler(int irq, void *data) | |
* memory, defer the stop into erase() function. | |
*/ | |
num = haptics_get_available_fifo_memory(chip); | |
- if (num != get_max_fifo_samples(chip)) { | |
+ if (num != MAX_FIFO_SAMPLES(chip)) { | |
dev_dbg(chip->dev, "%d FIFO samples still in playing\n", | |
- get_max_fifo_samples(chip) - num); | |
+ MAX_FIFO_SAMPLES(chip) - num); | |
goto unlock; | |
} | |
@@ -3204,11 +2813,11 @@ static irqreturn_t fifo_empty_irq_handler(int irq, void *data) | |
* stop driving for the unexpected padding zeros. | |
*/ | |
if (num < samples_left) | |
- num = round_down(num, HAP_PTN_FIFO_DIN_NUM); | |
+ num = round_down(num, HAP_PTN_V2_FIFO_DIN_NUM); | |
else | |
num = samples_left; | |
- rc = haptics_update_fifo_samples(chip, samples, num, true); | |
+ rc = haptics_update_fifo_samples(chip, samples, num); | |
if (rc < 0) { | |
dev_err(chip->dev, "Update FIFO samples failed, rc=%d\n", | |
rc); | |
@@ -3216,7 +2825,6 @@ static irqreturn_t fifo_empty_irq_handler(int irq, void *data) | |
} | |
status->samples_written += num; | |
- trace_qcom_haptics_fifo_prgm_status(fifo->num_s, status->samples_written, num); | |
if (status->samples_written == fifo->num_s) { | |
dev_dbg(chip->dev, "FIFO programming is done\n"); | |
atomic_set(&chip->play.fifo_status.written_done, 1); | |
@@ -3774,59 +3382,344 @@ DEFINE_DEBUGFS_ATTRIBUTE(preload_effect_idx_dbgfs_ops, | |
preload_effect_idx_dbgfs_read, | |
preload_effect_idx_dbgfs_write, "%llu\n"); | |
-static int haptics_add_effects_debugfs(struct haptics_effect *effect, | |
- struct dentry *dir) | |
+//BSP add for vibrator test +++ | |
+static ssize_t short_vibrate_read(struct file *fp, | |
+ char __user *buf, size_t count, loff_t *ppos) | |
{ | |
- struct dentry *file, *pattern_dir, *fifo_dir, *brake_dir; | |
+ return -EPERM; | |
+} | |
- file = debugfs_create_file_unsafe("vmax_mv", 0644, dir, | |
- effect, &vmax_debugfs_ops); | |
- if (IS_ERR(file)) | |
- return PTR_ERR(file); | |
+static ssize_t short_vibrate_write(struct file *fp, | |
+ const char __user *buf, size_t count, loff_t *ppos) | |
+{ | |
+ struct haptics_chip *chip = fp->private_data; | |
+ struct haptics_play_info *play = &chip->play; | |
+ char *kbuf; | |
+ int rc; | |
- file = debugfs_create_file_unsafe("lra_auto_res_en", 0644, dir, | |
- effect, &auto_res_en_debugfs_ops); | |
- if (IS_ERR(file)) | |
- return PTR_ERR(file); | |
+ kbuf = kzalloc(count + 1, GFP_KERNEL); | |
+ if (!kbuf) | |
+ return -ENOMEM; | |
- /* effect can have either pattern or FIFO */ | |
- if (effect->pattern) { | |
- pattern_dir = debugfs_create_dir("pattern", dir); | |
- if (IS_ERR(pattern_dir)) | |
- return PTR_ERR(pattern_dir); | |
+ rc = copy_from_user(kbuf, buf, count); | |
+ if (rc > 0) { | |
+ rc = -EFAULT; | |
+ goto exit; | |
+ } | |
- file = debugfs_create_file("samples", 0644, pattern_dir, | |
- effect, &pattern_s_dbgfs_ops); | |
- if (IS_ERR(file)) | |
- return PTR_ERR(file); | |
+ kbuf[count] = '\0'; | |
+ *ppos += count; | |
+ printk("[vibrator] %s chip->ptn_revision=%d\n",__func__,chip->ptn_revision); | |
+ mutex_lock(&chip->play.lock); | |
- file = debugfs_create_file_unsafe("play_rate_us", 0644, | |
- pattern_dir, effect, | |
- &pattern_play_rate_dbgfs_ops); | |
- if (IS_ERR(file)) | |
- return PTR_ERR(file); | |
- } else if (effect->fifo) { | |
- fifo_dir = debugfs_create_dir("fifo", dir); | |
- if (IS_ERR(fifo_dir)) | |
- return PTR_ERR(fifo_dir); | |
+ if (chip->play.in_calibration) { | |
+ dev_err(chip->dev, "calibration in progress, ignore playing predefined effect\n"); | |
+ rc = -EBUSY; | |
+ goto unlock; | |
+ } | |
- file = debugfs_create_file("samples", 0644, fifo_dir, | |
- effect, &fifo_s_dbgfs_ops); | |
- if (IS_ERR(file)) | |
- return PTR_ERR(file); | |
+//Loading short vibration waveform++++++++++++++++++ | |
+ play->effect = &chip->effects[0]; | |
+ // play->vmax_mv = play->effect->vmax_mv; | |
+ /* Clamp VMAX for different vibration strength */ | |
+ rc = haptics_set_vmax_mv(chip, play->effect->vmax_mv); | |
+ if (rc < 0) | |
+ goto unlock; | |
- file = debugfs_create_file_unsafe("period", 0644, fifo_dir, | |
- effect, &fifo_period_dbgfs_ops); | |
- if (IS_ERR(file)) | |
- return PTR_ERR(file); | |
+ rc = haptics_enable_autores(chip, !play->effect->auto_res_disable); | |
+ if (rc < 0) | |
+ goto unlock; | |
+ | |
+ play->brake = play->effect->brake; | |
+ /* Config brake settings if it's necessary */ | |
+ if (play->brake) { | |
+ rc = haptics_set_brake(chip, play->brake); | |
+ if (rc < 0) | |
+ goto unlock; | |
} | |
+ | |
+ play->pattern_src = PATTERN1; | |
+ rc = haptics_set_pattern(chip, play->effect->pattern,play->pattern_src); | |
+ if (rc < 0) | |
+ goto unlock; | |
- if (effect->brake) { | |
- brake_dir = debugfs_create_dir("brake", dir); | |
- if (IS_ERR(brake_dir)) | |
- return PTR_ERR(brake_dir); | |
- | |
- file = debugfs_create_file("samples", 0644, brake_dir, | |
+ if (play->pattern_src == FIFO) { | |
+ rc = haptics_set_fifo(chip, play->effect->fifo); | |
+ if (rc < 0) | |
+ goto unlock; | |
+ } | |
+ | |
+//Loading short vibration waveform+++++++++++++++++++++ | |
+ rc = haptics_enable_play(chip, true); | |
+ mutex_unlock(&chip->play.lock); | |
+ rc = haptics_enable_play(chip, false); | |
+// rc = haptics_erase(chip->input_dev, 0); | |
+ | |
+ rc = count; | |
+ | |
+exit: | |
+ kfree(kbuf); | |
+ return rc; | |
+ | |
+unlock: | |
+ kfree(kbuf); | |
+ mutex_unlock(&chip->play.lock); | |
+ return rc; | |
+} | |
+ | |
+static const struct file_operations short_vibrate_ops = { | |
+ .read = short_vibrate_read, | |
+ .write = short_vibrate_write, | |
+ .open = simple_open, | |
+}; | |
+ | |
+static int constant_vmax_read(void *data, u64 *val) | |
+{ | |
+ struct haptics_chip *chip = data; | |
+ | |
+ *val = chip->config.vmax_mv; | |
+ | |
+ return 0; | |
+} | |
+ | |
+static int constant_vmax_write(void *data, u64 val) | |
+{ | |
+ struct haptics_chip *chip = data; | |
+ | |
+ chip->config.vmax_mv = val; | |
+ | |
+ return 0; | |
+} | |
+ | |
+DEFINE_DEBUGFS_ATTRIBUTE(constant_vmax_ops, | |
+ constant_vmax_read, | |
+ constant_vmax_write, "%llu\n"); | |
+ | |
+static ssize_t long_vibrate_read(struct file *fp, | |
+ char __user *buf, size_t count, loff_t *ppos) | |
+{ | |
+ return -EPERM; | |
+} | |
+ | |
+static ssize_t long_vibrate_write(struct file *fp, | |
+ const char __user *buf, size_t count, loff_t *ppos) | |
+{ | |
+ struct haptics_chip *chip = fp->private_data; | |
+ char *kbuf; | |
+ int rc; | |
+ | |
+ kbuf = kzalloc(count + 1, GFP_KERNEL); | |
+ if (!kbuf) | |
+ return -ENOMEM; | |
+ | |
+ rc = copy_from_user(kbuf, buf, count); | |
+ if (rc > 0) { | |
+ rc = -EFAULT; | |
+ goto exit; | |
+ } | |
+ | |
+ kbuf[count] = '\0'; | |
+ *ppos += count; | |
+ | |
+ chip->config.t_lra_us = 4878; | |
+ rc = haptics_config_openloop_lra_period(chip, chip->config.t_lra_us); | |
+ rc = haptics_load_constant_effect(chip,DIRECT_PLAY_MAX_AMPLITUDE); | |
+ if (rc < 0) { | |
+ dev_err(chip->dev, "Play constant waveform failed, rc=%d\n",rc); | |
+ return rc; | |
+ } | |
+ rc = haptics_playback(chip->input_dev, 0, 1); | |
+ rc = count; | |
+exit: | |
+ kfree(kbuf); | |
+ return rc; | |
+} | |
+ | |
+static const struct file_operations long_vibrate_ops = { | |
+ .read = long_vibrate_read, | |
+ .write = long_vibrate_write, | |
+ .open = simple_open, | |
+}; | |
+ | |
+static ssize_t fifo_vibrate_read(struct file *fp, | |
+ char __user *buf, size_t count, loff_t *ppos) | |
+{ | |
+ return -EPERM; | |
+} | |
+ | |
+static ssize_t fifo_vibrate_write(struct file *fp, | |
+ const char __user *buf, size_t count, loff_t *ppos) | |
+{ | |
+ struct haptics_chip *chip = fp->private_data; | |
+ struct haptics_play_info *play = &chip->play; | |
+ char *kbuf; | |
+ int rc; | |
+ | |
+ kbuf = kzalloc(count + 1, GFP_KERNEL); | |
+ if (!kbuf) | |
+ return -ENOMEM; | |
+ | |
+ rc = copy_from_user(kbuf, buf, count); | |
+ if (rc > 0) { | |
+ rc = -EFAULT; | |
+ goto exit; | |
+ } | |
+ | |
+ kbuf[count] = '\0'; | |
+ *ppos += count; | |
+ | |
+ mutex_lock(&chip->play.lock); | |
+ | |
+ if (chip->play.in_calibration) { | |
+ dev_err(chip->dev, "calibration in progress, ignore playing predefined effect\n"); | |
+ rc = -EBUSY; | |
+ goto unlock; | |
+ } | |
+ | |
+//Loading short vibration waveform++++++++++++++++++ | |
+ play->effect = &chip->effects[6]; | |
+ // play->vmax_mv = play->effect->vmax_mv; | |
+ /* Clamp VMAX for different vibration strength */ | |
+ rc = haptics_set_vmax_mv(chip, play->effect->vmax_mv); | |
+ if (rc < 0) | |
+ goto unlock; | |
+ | |
+ rc = haptics_enable_autores(chip, !play->effect->auto_res_disable); | |
+ if (rc < 0) | |
+ goto unlock; | |
+ | |
+ play->brake = play->effect->brake; | |
+ /* Config brake settings if it's necessary */ | |
+ if (play->brake) { | |
+ rc = haptics_set_brake(chip, play->brake); | |
+ if (rc < 0) | |
+ goto unlock; | |
+ } | |
+ | |
+ play->pattern_src = FIFO; | |
+ rc = haptics_set_fifo(chip, play->effect->fifo); | |
+ if (rc < 0) | |
+ goto unlock; | |
+//Loading short vibration waveform+++++++++++++++++++++ | |
+ rc = haptics_enable_play(chip, true); | |
+ haptics_fifo_empty_irq_config(chip, true); | |
+ mutex_unlock(&chip->play.lock); | |
+// rc = haptics_enable_play(chip, false); | |
+// rc = haptics_erase(chip->input_dev, 0); | |
+ | |
+ rc = count; | |
+exit: | |
+ kfree(kbuf); | |
+ return rc; | |
+ | |
+unlock: | |
+ kfree(kbuf); | |
+ mutex_unlock(&chip->play.lock); | |
+ return rc; | |
+} | |
+ | |
+static const struct file_operations fifo_vibrate_ops = { | |
+ .read = fifo_vibrate_read, | |
+ .write = fifo_vibrate_write, | |
+ .open = simple_open, | |
+}; | |
+ | |
+static ssize_t stop_vibrate_read(struct file *fp, | |
+ char __user *buf, size_t count, loff_t *ppos) | |
+{ | |
+ return -EPERM; | |
+} | |
+ | |
+static ssize_t stop_vibrate_write(struct file *fp, | |
+ const char __user *buf, size_t count, loff_t *ppos) | |
+{ | |
+ struct haptics_chip *chip = fp->private_data; | |
+ char *kbuf; | |
+ int rc; | |
+ | |
+ kbuf = kzalloc(count + 1, GFP_KERNEL); | |
+ if (!kbuf) | |
+ return -ENOMEM; | |
+ | |
+ rc = copy_from_user(kbuf, buf, count); | |
+ if (rc > 0) { | |
+ rc = -EFAULT; | |
+ goto exit; | |
+ } | |
+ | |
+ kbuf[count] = '\0'; | |
+ *ppos += count; | |
+ | |
+ rc = haptics_enable_play(chip, false); | |
+ rc = haptics_erase(chip->input_dev, 0); | |
+ | |
+ rc = count; | |
+exit: | |
+ kfree(kbuf); | |
+ return rc; | |
+} | |
+ | |
+static const struct file_operations stop_vibrate_ops = { | |
+ .read = stop_vibrate_read, | |
+ .write = stop_vibrate_write, | |
+ .open = simple_open, | |
+}; | |
+ | |
+//BSP add for vibrator test --- | |
+ | |
+static int haptics_add_effects_debugfs(struct haptics_effect *effect, | |
+ struct dentry *dir) | |
+{ | |
+ struct dentry *file, *pattern_dir, *fifo_dir, *brake_dir; | |
+ | |
+ file = debugfs_create_file_unsafe("vmax_mv", 0644, dir, | |
+ effect, &vmax_debugfs_ops); | |
+ if (IS_ERR(file)) | |
+ return PTR_ERR(file); | |
+ | |
+ file = debugfs_create_file_unsafe("lra_auto_res_en", 0644, dir, | |
+ effect, &auto_res_en_debugfs_ops); | |
+ if (IS_ERR(file)) | |
+ return PTR_ERR(file); | |
+ | |
+ /* effect can have either pattern or FIFO */ | |
+ if (effect->pattern) { | |
+ pattern_dir = debugfs_create_dir("pattern", dir); | |
+ if (IS_ERR(pattern_dir)) | |
+ return PTR_ERR(pattern_dir); | |
+ | |
+ file = debugfs_create_file("samples", 0644, pattern_dir, | |
+ effect, &pattern_s_dbgfs_ops); | |
+ if (IS_ERR(file)) | |
+ return PTR_ERR(file); | |
+ | |
+ file = debugfs_create_file_unsafe("play_rate_us", 0644, | |
+ pattern_dir, effect, | |
+ &pattern_play_rate_dbgfs_ops); | |
+ if (IS_ERR(file)) | |
+ return PTR_ERR(file); | |
+ } else if (effect->fifo) { | |
+ fifo_dir = debugfs_create_dir("fifo", dir); | |
+ if (IS_ERR(fifo_dir)) | |
+ return PTR_ERR(fifo_dir); | |
+ | |
+ file = debugfs_create_file("samples", 0644, fifo_dir, | |
+ effect, &fifo_s_dbgfs_ops); | |
+ if (IS_ERR(file)) | |
+ return PTR_ERR(file); | |
+ | |
+ file = debugfs_create_file_unsafe("period", 0644, fifo_dir, | |
+ effect, &fifo_period_dbgfs_ops); | |
+ if (IS_ERR(file)) | |
+ return PTR_ERR(file); | |
+ } | |
+ | |
+ if (effect->brake) { | |
+ brake_dir = debugfs_create_dir("brake", dir); | |
+ if (IS_ERR(brake_dir)) | |
+ return PTR_ERR(brake_dir); | |
+ | |
+ file = debugfs_create_file("samples", 0644, brake_dir, | |
effect, &brake_s_dbgfs_ops); | |
if (IS_ERR(file)) | |
return PTR_ERR(file); | |
@@ -3850,53 +3743,73 @@ static int haptics_add_effects_debugfs(struct haptics_effect *effect, | |
return 0; | |
} | |
-#define EFFECT_NAME_SIZE 15 | |
-static int haptics_add_debugfs(struct dentry *hap_dir, struct haptics_effect *effects, | |
- int count, char *effect_name) | |
+#define EFFECT_NAME_SIZE 12 | |
+static int haptics_create_debugfs(struct haptics_chip *chip) | |
{ | |
- struct dentry *effect_dir; | |
+ struct dentry *hap_dir, *effect_dir, *file, *test_dir; | |
char str[EFFECT_NAME_SIZE] = {0}; | |
- int rc = 0; | |
- int i = 0; | |
+ int rc, i; | |
- for (; i < count; i++) { | |
- scnprintf(str, ARRAY_SIZE(str), "%s%d", effect_name, effects[i].id); | |
+ hap_dir = debugfs_create_dir("haptics", NULL); | |
+ if (IS_ERR(hap_dir)) { | |
+ rc = PTR_ERR(hap_dir); | |
+ dev_err(chip->dev, "create haptics debugfs directory failed, rc=%d\n", | |
+ rc); | |
+ return rc; | |
+ } | |
+ | |
+ for (i = 0; i < chip->effects_count; i++) { | |
+ scnprintf(str, ARRAY_SIZE(str), "effect%d", | |
+ chip->effects[i].id); | |
effect_dir = debugfs_create_dir(str, hap_dir); | |
if (IS_ERR(effect_dir)) { | |
rc = PTR_ERR(effect_dir); | |
- pr_err("create %s debugfs directory failed, rc=%d\n", str, rc); | |
- return rc; | |
+ dev_err(chip->dev, "create %s debugfs directory failed, rc=%d\n", | |
+ str, rc); | |
+ goto exit; | |
} | |
- rc = haptics_add_effects_debugfs(&effects[i], effect_dir); | |
+ | |
+ rc = haptics_add_effects_debugfs(&chip->effects[i], effect_dir); | |
if (rc < 0) { | |
- pr_err("create debugfs nodes for %s failed, rc=%d\n", str, rc); | |
- return rc; | |
+ dev_err(chip->dev, "create debugfs nodes for %s failed, rc=%d\n", | |
+ str, rc); | |
+ goto exit; | |
} | |
} | |
- return rc; | |
-} | |
+//BSP add for vibrator test +++ | |
+ test_dir = debugfs_create_dir("vibrator_test", hap_dir); | |
+ if (IS_ERR(test_dir)) { | |
+ rc = PTR_ERR(test_dir); | |
+ dev_err(chip->dev, "create vibrator_test debugfs directory failed, rc=%d\n", rc); | |
+ goto exit; | |
+ } | |
-static int haptics_create_debugfs(struct haptics_chip *chip) | |
-{ | |
- struct dentry *hap_dir, *file; | |
- int rc = 0; | |
+ file = debugfs_create_file_unsafe("short_vibrate", 0644, test_dir, | |
+ chip, &short_vibrate_ops); | |
+ if (IS_ERR(file)) | |
+ return PTR_ERR(file); | |
- hap_dir = debugfs_create_dir("haptics", NULL); | |
- if (IS_ERR(hap_dir)) { | |
- rc = PTR_ERR(hap_dir); | |
- dev_err(chip->dev, "create haptics debugfs directory failed, rc=%d\n", | |
- rc); | |
- return rc; | |
- } | |
+ file = debugfs_create_file_unsafe("constant_vmax", 0644, test_dir, | |
+ chip, &constant_vmax_ops); | |
+ if (IS_ERR(file)) | |
+ return PTR_ERR(file); | |
- rc = haptics_add_debugfs(hap_dir, chip->effects, chip->effects_count, "effect"); | |
- if (rc < 0) | |
- goto exit; | |
+ file = debugfs_create_file_unsafe("long_vibrate", 0644, test_dir, | |
+ chip, &long_vibrate_ops); | |
+ if (IS_ERR(file)) | |
+ return PTR_ERR(file); | |
- rc = haptics_add_debugfs(hap_dir, chip->primitives, chip->primitives_count, "primitive"); | |
- if (rc < 0) | |
- goto exit; | |
+ file = debugfs_create_file_unsafe("fifo_vibrate", 0644, test_dir, | |
+ chip, &fifo_vibrate_ops); | |
+ if (IS_ERR(file)) | |
+ return PTR_ERR(file); | |
+ | |
+ file = debugfs_create_file_unsafe("stop_vibrate", 0644, test_dir, | |
+ chip, &stop_vibrate_ops); | |
+ if (IS_ERR(file)) | |
+ return PTR_ERR(file); | |
+//BSP add for vibrator test --- | |
file = debugfs_create_file_unsafe("preload_effect_idx", 0644, hap_dir, | |
chip, &preload_effect_idx_dbgfs_ops); | |
@@ -3909,6 +3822,7 @@ static int haptics_create_debugfs(struct haptics_chip *chip) | |
debugfs_create_u32("fifo_empty_thresh", 0600, hap_dir, | |
&chip->config.fifo_empty_thresh); | |
+ | |
chip->debugfs_dir = hap_dir; | |
return 0; | |
@@ -3918,169 +3832,175 @@ static int haptics_create_debugfs(struct haptics_chip *chip) | |
} | |
#endif | |
-static int haptics_parse_effect_pattern_data(struct haptics_chip *chip, | |
+static int haptics_parse_per_effect_dt(struct haptics_chip *chip, | |
struct device_node *node, struct haptics_effect *effect) | |
{ | |
struct haptics_hw_config *config = &chip->config; | |
u32 data[SAMPLES_PER_PATTERN * 3]; | |
int rc, tmp, i; | |
- effect->t_lra_us = config->t_lra_us; | |
- tmp = of_property_count_elems_of_size(node, | |
- "qcom,wf-pattern-data", sizeof(u32)); | |
- if (tmp <= 0) { | |
- dev_dbg(chip->dev, "qcom,wf-pattern-data is not defined properly for effect %d\n", | |
- effect->id); | |
- return 0; | |
- } | |
- | |
- if (tmp > SAMPLES_PER_PATTERN * 3) { | |
- dev_err(chip->dev, "Pattern src can only play 8 samples at max\n"); | |
+ if (!effect) | |
return -EINVAL; | |
- } | |
- | |
- effect->pattern = devm_kzalloc(chip->dev, | |
- sizeof(*effect->pattern), GFP_KERNEL); | |
- if (!effect->pattern) | |
- return -ENOMEM; | |
- rc = of_property_read_u32_array(node, | |
- "qcom,wf-pattern-data", data, tmp); | |
+ rc = of_property_read_u32(node, "qcom,effect-id", &effect->id); | |
if (rc < 0) { | |
- dev_err(chip->dev, "Read wf-pattern-data failed, rc=%d\n", | |
+ dev_err(chip->dev, "Read qcom,effect-id failed, rc=%d\n", | |
rc); | |
return rc; | |
} | |
- for (i = 0; i < tmp / 3; i++) { | |
- if (data[3 * i] > 0x1ff || data[3 * i + 1] > T_LRA_X_8 | |
- || data[3 * i + 2] > 1) { | |
- dev_err(chip->dev, "allowed tuples: [amplitude(<= 0x1ff) period(<=6(T_LRA_X_8)) f_lra_x2(0,1)]\n"); | |
- return -EINVAL; | |
- } | |
- | |
- effect->pattern->samples[i].amplitude = | |
- (u16)data[3 * i]; | |
- effect->pattern->samples[i].period = | |
- (enum s_period)data[3 * i + 1]; | |
- effect->pattern->samples[i].f_lra_x2 = | |
- (bool)data[3 * i + 2]; | |
- } | |
- | |
- effect->pattern->preload = of_property_read_bool(node, | |
- "qcom,wf-pattern-preload"); | |
- /* | |
- * Use PATTERN1 src by default, effect with preloaded | |
- * pattern will use PATTERN2 by default and only the | |
- * 1st preloaded pattern will be served. | |
- */ | |
- effect->src = PATTERN1; | |
- if (effect->pattern->preload) { | |
- if (config->preload_effect != -EINVAL) { | |
- dev_err(chip->dev, "effect %d has been defined as preloaded\n", | |
- config->preload_effect); | |
- effect->pattern->preload = false; | |
- } else { | |
- config->preload_effect = effect->id; | |
- effect->src = PATTERN2; | |
- } | |
- } | |
- | |
- if (config->is_erm) | |
- effect->pattern->play_rate_us = DEFAULT_ERM_PLAY_RATE_US; | |
- else | |
- effect->pattern->play_rate_us = config->t_lra_us; | |
- | |
- rc = of_property_read_u32(node, "qcom,wf-pattern-period-us", &tmp); | |
+ effect->vmax_mv = config->vmax_mv; | |
+ rc = of_property_read_u32(node, "qcom,wf-vmax-mv", &tmp); | |
if (rc < 0) | |
- dev_dbg(chip->dev, "Read qcom,wf-pattern-period-us failed, rc=%d\n", | |
+ dev_dbg(chip->dev, "Read qcom,wf-vmax-mv failed, rc=%d\n", | |
rc); | |
else | |
- effect->pattern->play_rate_us = tmp; | |
+ effect->vmax_mv = tmp; | |
- if (effect->pattern->play_rate_us > TLRA_MAX_US) { | |
- dev_err(chip->dev, "qcom,wf-pattern-period-us (%d) exceed the max value: %d\n", | |
- effect->pattern->play_rate_us, | |
- TLRA_MAX_US); | |
+ if (effect->vmax_mv > MAX_VMAX_MV) { | |
+ dev_err(chip->dev, "qcom,wf-vmax-mv (%d) exceed the max value: %d\n", | |
+ effect->vmax_mv, MAX_VMAX_MV); | |
return -EINVAL; | |
} | |
- effect->pattern->play_length_us = get_pattern_play_length_us(effect->pattern); | |
- if (effect->pattern->play_length_us == -EINVAL) { | |
- dev_err(chip->dev, "get pattern play length failed\n"); | |
+ effect->t_lra_us = config->t_lra_us; | |
+ tmp = of_property_count_elems_of_size(node, | |
+ "qcom,wf-pattern-data", sizeof(u32)); | |
+ if (tmp > SAMPLES_PER_PATTERN * 3) { | |
+ dev_err(chip->dev, "Pattern src can only play 8 samples at max\n"); | |
return -EINVAL; | |
} | |
- return 0; | |
-} | |
+ if (tmp > 0) { | |
+ effect->pattern = devm_kzalloc(chip->dev, | |
+ sizeof(*effect->pattern), GFP_KERNEL); | |
+ if (!effect->pattern) | |
+ return -ENOMEM; | |
-static int haptics_parse_effect_fifo_data(struct haptics_chip *chip, | |
- struct device_node *node, struct haptics_effect *effect) | |
-{ | |
- struct haptics_hw_config *config = &chip->config; | |
- int rc, tmp; | |
+ rc = of_property_read_u32_array(node, | |
+ "qcom,wf-pattern-data", data, tmp); | |
+ if (rc < 0) { | |
+ dev_err(chip->dev, "Read wf-pattern-data failed, rc=%d\n", | |
+ rc); | |
+ return rc; | |
+ } | |
- if (effect->pattern) { | |
- dev_dbg(chip->dev, "ignore parsing FIFO effect when pattern effect is present\n"); | |
- return 0; | |
+ for (i = 0; i < tmp / 3; i++) { | |
+ if (data[3 * i] > 0x1ff || data[3 * i + 1] > T_LRA_X_8 | |
+ || data[3 * i + 2] > 1) { | |
+ dev_err(chip->dev, "allowed tuples: [amplitude(<= 0x1ff) period(<=6(T_LRA_X_8)) f_lra_x2(0,1)]\n"); | |
+ return -EINVAL; | |
+ } | |
+ | |
+ effect->pattern->samples[i].amplitude = | |
+ (u16)data[3 * i]; | |
+ effect->pattern->samples[i].period = | |
+ (enum s_period)data[3 * i + 1]; | |
+ effect->pattern->samples[i].f_lra_x2 = | |
+ (bool)data[3 * i + 2]; | |
+ } | |
+ | |
+ effect->pattern->preload = of_property_read_bool(node, | |
+ "qcom,wf-pattern-preload"); | |
+ /* | |
+ * Use PATTERN1 src by default, effect with preloaded | |
+ * pattern will use PATTERN2 by default and only the | |
+ * 1st preloaded pattern will be served. | |
+ */ | |
+ effect->src = PATTERN1; | |
+ if (effect->pattern->preload) { | |
+ if (config->preload_effect != -EINVAL) { | |
+ dev_err(chip->dev, "effect %d has been defined as preloaded\n", | |
+ config->preload_effect); | |
+ effect->pattern->preload = false; | |
+ } else { | |
+ config->preload_effect = effect->id; | |
+ effect->src = PATTERN2; | |
+ } | |
+ } | |
} | |
tmp = of_property_count_u8_elems(node, "qcom,wf-fifo-data"); | |
- if (tmp <= 0) { | |
- dev_dbg(chip->dev, "qcom,wf-fifo-data is not defined properly for effect %d\n", | |
+ if (tmp > 0) { | |
+ effect->fifo = devm_kzalloc(chip->dev, | |
+ sizeof(*effect->fifo), GFP_KERNEL); | |
+ if (!effect->fifo) | |
+ return -ENOMEM; | |
+ | |
+ effect->fifo->samples = devm_kcalloc(chip->dev, | |
+ tmp, sizeof(u8), GFP_KERNEL); | |
+ if (!effect->fifo->samples) | |
+ return -ENOMEM; | |
+ | |
+ rc = of_property_read_u8_array(node, "qcom,wf-fifo-data", | |
+ effect->fifo->samples, tmp); | |
+ if (rc < 0) { | |
+ dev_err(chip->dev, "Read wf-fifo-data failed, rc=%d\n", | |
+ rc); | |
+ return rc; | |
+ } | |
+ | |
+ effect->fifo->num_s = tmp; | |
+ } | |
+ | |
+ if (!effect->pattern && !effect->fifo) { | |
+ dev_err(chip->dev, "no pattern specified for effect %d\n", | |
effect->id); | |
- return 0; | |
+ return -EINVAL; | |
} | |
- effect->fifo = devm_kzalloc(chip->dev, | |
- sizeof(*effect->fifo), GFP_KERNEL); | |
- if (!effect->fifo) | |
- return -ENOMEM; | |
+ if (effect->pattern) { | |
+ if (config->is_erm) | |
+ effect->pattern->play_rate_us = | |
+ DEFAULT_ERM_PLAY_RATE_US; | |
+ else | |
+ effect->pattern->play_rate_us = config->t_lra_us; | |
- effect->fifo->samples = devm_kcalloc(chip->dev, | |
- tmp, sizeof(u8), GFP_KERNEL); | |
- if (!effect->fifo->samples) | |
- return -ENOMEM; | |
+ rc = of_property_read_u32(node, "qcom,wf-pattern-period-us", | |
+ &tmp); | |
+ if (rc < 0) | |
+ dev_dbg(chip->dev, "Read qcom,wf-pattern-period-us failed, rc=%d\n", | |
+ rc); | |
+ else | |
+ effect->pattern->play_rate_us = tmp; | |
- rc = of_property_read_u8_array(node, "qcom,wf-fifo-data", | |
- effect->fifo->samples, tmp); | |
- if (rc < 0) { | |
- dev_err(chip->dev, "Read wf-fifo-data failed, rc=%d\n", | |
- rc); | |
- return rc; | |
- } | |
+ if (effect->pattern->play_rate_us > TLRA_MAX_US) { | |
+ dev_err(chip->dev, "qcom,wf-pattern-period-us (%d) exceed the max value: %d\n", | |
+ effect->pattern->play_rate_us, | |
+ TLRA_MAX_US); | |
+ return -EINVAL; | |
+ } | |
- effect->fifo->num_s = tmp; | |
- effect->fifo->period_per_s = T_LRA; | |
- rc = of_property_read_u32(node, "qcom,wf-fifo-period", &tmp); | |
- if (rc < 0) { | |
- dev_err(chip->dev, "Get qcom,wf-fifo-period failed, rc=%d\n", rc); | |
- return rc; | |
- } else if (tmp > F_48KHZ) { | |
- dev_err(chip->dev, "FIFO playing period %d is not supported\n", | |
- tmp); | |
- return -EINVAL; | |
- } | |
+ effect->pattern->play_length_us = | |
+ get_pattern_play_length_us(effect->pattern); | |
+ if (effect->pattern->play_length_us == -EINVAL) { | |
+ dev_err(chip->dev, "get pattern play length failed\n"); | |
+ return -EINVAL; | |
+ } | |
- effect->fifo->period_per_s = tmp; | |
- effect->fifo->play_length_us = | |
- get_fifo_play_length_us(effect->fifo, config->t_lra_us); | |
- if (effect->fifo->play_length_us == -EINVAL) { | |
- dev_err(chip->dev, "get fifo play length failed\n"); | |
- return -EINVAL; | |
- } | |
+ if (effect->fifo) | |
+ dev_dbg(chip->dev, "Ignore FIFO data if pattern is specified!\n"); | |
- effect->src = FIFO; | |
- effect->fifo->preload = of_property_read_bool(node, | |
- "qcom,wf-fifo-preload"); | |
- return 0; | |
-} | |
+ } else if (effect->fifo) { | |
+ effect->fifo->period_per_s = T_LRA; | |
+ rc = of_property_read_u32(node, "qcom,wf-fifo-period", &tmp); | |
+ if (tmp > F_48KHZ) { | |
+ dev_err(chip->dev, "FIFO playing period %d is not supported\n", | |
+ tmp); | |
+ return -EINVAL; | |
+ } else if (!rc) { | |
+ effect->fifo->period_per_s = tmp; | |
+ } | |
-static int haptics_parse_effect_brake_data(struct haptics_chip *chip, | |
- struct device_node *node, struct haptics_effect *effect) | |
-{ | |
- struct haptics_hw_config *config = &chip->config; | |
- int rc, tmp; | |
+ effect->fifo->play_length_us = | |
+ get_fifo_play_length_us(effect->fifo, config->t_lra_us); | |
+ if (effect->fifo->play_length_us == -EINVAL) { | |
+ dev_err(chip->dev, "get fifo play length failed\n"); | |
+ return -EINVAL; | |
+ } | |
+ | |
+ effect->src = FIFO; | |
+ } | |
effect->brake = devm_kzalloc(chip->dev, | |
sizeof(*effect->brake), GFP_KERNEL); | |
@@ -4135,107 +4055,12 @@ static int haptics_parse_effect_brake_data(struct haptics_chip *chip, | |
effect->brake->play_length_us = | |
get_brake_play_length_us(effect->brake, config->t_lra_us); | |
- return 0; | |
-} | |
- | |
-static int haptics_parse_per_effect_dt(struct haptics_chip *chip, | |
- struct device_node *node, struct haptics_effect *effect) | |
-{ | |
- struct haptics_hw_config *config = &chip->config; | |
- int rc, tmp; | |
- | |
- if (!effect) | |
- return -EINVAL; | |
- | |
- effect->vmax_mv = config->vmax_mv; | |
- rc = of_property_read_u32(node, "qcom,wf-vmax-mv", &tmp); | |
- if (rc < 0) | |
- dev_dbg(chip->dev, "read qcom,wf-vmax-mv failed, rc=%d\n", | |
- rc); | |
- else | |
- effect->vmax_mv = tmp; | |
- | |
- if (effect->vmax_mv > MAX_VMAX_MV) { | |
- dev_err(chip->dev, "qcom,wf-vmax-mv (%d) exceed the max value: %d\n", | |
- effect->vmax_mv, MAX_VMAX_MV); | |
- return -EINVAL; | |
- } | |
- | |
- rc = haptics_parse_effect_pattern_data(chip, node, effect); | |
- if (rc < 0) { | |
- dev_err(chip->dev, "parse effect PATTERN data failed, rc=%d\n", rc); | |
- return rc; | |
- } | |
- | |
- rc = haptics_parse_effect_fifo_data(chip, node, effect); | |
- if (rc < 0) { | |
- dev_err(chip->dev, "parse effect FIFO data failed, rc=%d\n", rc); | |
- return rc; | |
- } | |
- | |
- if (!effect->pattern && !effect->fifo) { | |
- dev_err(chip->dev, "no pattern specified for effect %d\n", | |
- effect->id); | |
- return -EINVAL; | |
- } | |
- | |
- rc = haptics_parse_effect_brake_data(chip, node, effect); | |
- if (rc < 0) { | |
- dev_err(chip->dev, "parse effect brake data failed, rc=%d\n", rc); | |
- return rc; | |
- } | |
- | |
- if (!config->is_erm) | |
- effect->auto_res_disable = of_property_read_bool(node, | |
- "qcom,wf-auto-res-disable"); | |
- | |
- return 0; | |
-} | |
- | |
-static int haptics_parse_primitives_dt(struct haptics_chip *chip) | |
-{ | |
- struct device_node *node = chip->dev->of_node; | |
- struct device_node *child; | |
- int rc, i = 0, num = 0; | |
- | |
- for_each_available_child_of_node(node, child) { | |
- if (of_find_property(child, "qcom,primitive-id", NULL)) | |
- num++; | |
- } | |
- if (!num) | |
+ if (config->is_erm) | |
return 0; | |
- chip->primitives = devm_kcalloc(chip->dev, num, | |
- sizeof(*chip->effects), GFP_KERNEL); | |
- if (!chip->primitives) | |
- return -ENOMEM; | |
- | |
- for_each_available_child_of_node(node, child) { | |
- if (!of_find_property(child, "qcom,primitive-id", NULL)) | |
- continue; | |
- | |
- rc = of_property_read_u32(child, "qcom,primitive-id", &(chip->primitives[i].id)); | |
- if (rc < 0) { | |
- dev_err(chip->dev, "Read qcom,primitive-id failed, rc=%d\n", | |
- rc); | |
- of_node_put(child); | |
- return rc; | |
- } | |
- | |
- rc = haptics_parse_per_effect_dt(chip, child, | |
- &chip->primitives[i]); | |
- if (rc < 0) { | |
- dev_err(chip->dev, "parse primitive %d failed, rc=%d\n", | |
- i); | |
- of_node_put(child); | |
- return rc; | |
- } | |
- i++; | |
- } | |
- | |
- chip->primitives_count = i; | |
- dev_dbg(chip->dev, "Dump primitive effect settings as following\n"); | |
- __dump_effects(chip, chip->primitives, chip->primitives_count); | |
+ /* LRA specific per-effect settings are parsed below */ | |
+ effect->auto_res_disable = of_property_read_bool(node, | |
+ "qcom,wf-auto-res-disable"); | |
return 0; | |
} | |
@@ -4262,14 +4087,6 @@ static int haptics_parse_effects_dt(struct haptics_chip *chip) | |
if (!of_find_property(child, "qcom,effect-id", NULL)) | |
continue; | |
- rc = of_property_read_u32(child, "qcom,effect-id", &(chip->effects[i].id)); | |
- if (rc < 0) { | |
- dev_err(chip->dev, "Read qcom,effect-id failed, rc=%d\n", | |
- rc); | |
- of_node_put(child); | |
- return rc; | |
- } | |
- | |
rc = haptics_parse_per_effect_dt(chip, child, | |
&chip->effects[i]); | |
if (rc < 0) { | |
@@ -4282,8 +4099,7 @@ static int haptics_parse_effects_dt(struct haptics_chip *chip) | |
} | |
chip->effects_count = i; | |
- dev_dbg(chip->dev, "Dump predefined effect settings as following\n"); | |
- __dump_effects(chip, chip->effects, chip->effects_count); | |
+ __dump_effects(chip); | |
return 0; | |
} | |
@@ -4335,10 +4151,6 @@ static int haptics_parse_lra_dt(struct haptics_chip *chip) | |
} | |
} | |
- if (chip->hw_type == HAP525_HV) | |
- config->measure_lra_impedance = of_property_read_bool(node, | |
- "qcom,rt-imp-detect"); | |
- | |
return 0; | |
} | |
@@ -4348,48 +4160,25 @@ static int haptics_get_revision(struct haptics_chip *chip) | |
u8 val[2]; | |
rc = haptics_read(chip, chip->cfg_addr_base, | |
- HAP_CFG_REVISION1_REG, val, 2); | |
+ HAP_CFG_REVISION2_REG, val, 1); | |
if (rc < 0) | |
return rc; | |
- chip->cfg_rev1 = val[0]; | |
- chip->cfg_revision = val[1]; | |
+ chip->cfg_revision = val[0]; | |
rc = haptics_read(chip, chip->ptn_addr_base, | |
HAP_PTN_REVISION2_REG, val, 1); | |
if (rc < 0) | |
return rc; | |
chip->ptn_revision = val[0]; | |
+ rc = haptics_read(chip, chip->hbst_addr_base, | |
+ HAP_BOOST_REVISION1, val, 2); | |
+ if (rc < 0) | |
+ return rc; | |
- if (is_haptics_external_powered(chip)) { | |
- dev_info(chip->dev, "haptics revision: HAP_CFG %#x, HAP_PTN %#x\n", | |
- chip->cfg_revision, chip->ptn_revision); | |
- } else { | |
- rc = haptics_read(chip, chip->hbst_addr_base, | |
- HAP_BOOST_REVISION1, val, 2); | |
- if (rc < 0) | |
- return rc; | |
- | |
- chip->hbst_revision = (val[1] << 8) | val[0]; | |
- dev_info(chip->dev, "haptics revision: HAP_CFG %#x, HAP_PTN %#x, HAP_HBST %#x\n", | |
- chip->cfg_revision, chip->ptn_revision, chip->hbst_revision); | |
- | |
- } | |
- | |
- if ((chip->cfg_revision == HAP_CFG_V2) && | |
- (chip->ptn_revision == HAP_PTN_V2)) { | |
- chip->hw_type = HAP520; | |
- } else if ((chip->cfg_revision == HAP_CFG_V3) && | |
- (chip->ptn_revision == HAP_PTN_V3)) { | |
- chip->hw_type = HAP520_MV; | |
- } else if ((chip->cfg_revision == HAP_CFG_V4) && | |
- (chip->ptn_revision == HAP_PTN_V4)) { | |
- chip->hw_type = HAP525_HV; | |
- } else { | |
- dev_err(chip->dev, "haptics revision is not supported\n"); | |
- return -EOPNOTSUPP; | |
- } | |
- | |
+ chip->hbst_revision = (val[1] << 8) | val[0]; | |
+ dev_dbg(chip->dev, "haptics revision: HAP_CFG %#x, HAP_PTN %#x, HAP_HBST %#x\n", | |
+ chip->cfg_revision, chip->ptn_revision, chip->hbst_revision); | |
return 0; | |
} | |
@@ -4487,14 +4276,13 @@ static int haptics_parse_dt(struct haptics_chip *chip) | |
chip->ptn_addr_base = be32_to_cpu(*addr); | |
addr = of_get_address(node, 2, NULL, NULL); | |
- if (!addr && !is_haptics_external_powered(chip)) { | |
+ if (!addr) { | |
dev_err(chip->dev, "Read HAPTICS_HBOOST address failed\n"); | |
rc = -EINVAL; | |
goto free_pbs; | |
- } else if (addr != NULL) { | |
- chip->hbst_addr_base = be32_to_cpu(*addr); | |
} | |
+ chip->hbst_addr_base = be32_to_cpu(*addr); | |
rc = haptics_get_revision(chip); | |
if (rc < 0) { | |
dev_err(chip->dev, "Get revision failed, rc=%d\n", rc); | |
@@ -4517,12 +4305,12 @@ static int haptics_parse_dt(struct haptics_chip *chip) | |
goto free_pbs; | |
} | |
- config->fifo_empty_thresh = get_fifo_empty_threshold(chip); | |
+ config->fifo_empty_thresh = FIFO_EMPTY_THRESHOLD(chip); | |
of_property_read_u32(node, "qcom,fifo-empty-threshold", | |
&config->fifo_empty_thresh); | |
- if (config->fifo_empty_thresh >= get_max_fifo_samples(chip)) { | |
+ if (config->fifo_empty_thresh >= MAX_FIFO_SAMPLES(chip)) { | |
dev_err(chip->dev, "FIFO empty threshold (%d) should be less than %d\n", | |
- config->fifo_empty_thresh, get_max_fifo_samples(chip)); | |
+ config->fifo_empty_thresh, MAX_FIFO_SAMPLES(chip)); | |
rc = -EINVAL; | |
goto free_pbs; | |
} | |
@@ -4577,15 +4365,8 @@ static int haptics_parse_dt(struct haptics_chip *chip) | |
config->preload_effect = -EINVAL; | |
rc = haptics_parse_effects_dt(chip); | |
if (rc < 0) { | |
- dev_err(chip->dev, "Parse device-tree for effects failed, rc=%d\n", | |
- rc); | |
- goto free_pbs; | |
- } | |
- | |
- rc = haptics_parse_primitives_dt(chip); | |
- if (rc < 0) { | |
- dev_err(chip->dev, "Parse device-tree for primitives failed, rc=%d\n", | |
- rc); | |
+ dev_err(chip->dev, "Parse device-tree for effects failed, rc=%d\n", | |
+ rc); | |
goto free_pbs; | |
} | |
@@ -4613,9 +4394,6 @@ static int swr_slave_reg_enable(struct regulator_dev *rdev) | |
return rc; | |
} | |
- if (!(chip->wa_flags & RECOVER_SWR_SLAVE)) | |
- goto done; | |
- | |
/* | |
* If haptics has already been in SWR mode when enabling the SWR | |
* slave, it means that the haptics module was stuck in prevous | |
@@ -4643,7 +4421,7 @@ static int swr_slave_reg_enable(struct regulator_dev *rdev) | |
return rc; | |
} | |
} | |
-done: | |
+ | |
chip->swr_slave_enabled = true; | |
return 0; | |
} | |
@@ -4739,164 +4517,25 @@ static int haptics_pbs_trigger_isc_config(struct haptics_chip *chip) | |
} | |
#define MAX_SWEEP_STEPS 5 | |
+#define MAX_IMPEDANCE_MOHM 40000 | |
+#define MIN_ISC_MA 250 | |
#define MIN_DUTY_MILLI_PCT 0 | |
#define MAX_DUTY_MILLI_PCT 100000 | |
#define LRA_CONFIG_REGS 3 | |
static u32 get_lra_impedance_capable_max(struct haptics_chip *chip) | |
{ | |
- u32 mohms; | |
- u32 max_vmax_mv, min_isc_ma; | |
- | |
- switch (chip->hw_type) { | |
- case HAP520: | |
- min_isc_ma = 250; | |
- if (chip->clamp_at_5v) | |
- max_vmax_mv = 5000; | |
- else | |
- max_vmax_mv = 10000; | |
- break; | |
- case HAP520_MV: | |
- max_vmax_mv = 5000; | |
- min_isc_ma = 140; | |
- break; | |
- case HAP525_HV: | |
- if (chip->clamp_at_5v) { | |
- max_vmax_mv = 5000; | |
- min_isc_ma = 125; | |
- } else { | |
- max_vmax_mv = 10000; | |
- min_isc_ma = 250; | |
- } | |
- break; | |
- default: | |
- return 0; | |
- } | |
+ u32 mohms = MAX_IMPEDANCE_MOHM; | |
- mohms = (max_vmax_mv * 1000) / min_isc_ma; | |
- if (is_haptics_external_powered(chip)) | |
- mohms = (chip->hpwr_voltage_mv * 1000) / min_isc_ma; | |
+ if (chip->clamp_at_5v) | |
+ mohms = MAX_IMPEDANCE_MOHM / 2; | |
+ | |
+ if (chip->hpwr_vreg) | |
+ mohms = (chip->hpwr_voltage_mv * 1000) / MIN_ISC_MA; | |
dev_dbg(chip->dev, "LRA impedance capable max: %u mohms\n", mohms); | |
return mohms; | |
} | |
-#define RT_IMPD_DET_VMAX_DEFAULT_MV 4500 | |
-static int haptics_measure_realtime_lra_impedance(struct haptics_chip *chip) | |
-{ | |
- int rc; | |
- u8 val, current_sel; | |
- u32 vmax_mv, nominal_ohm, current_ma, vmax_margin_mv; | |
- struct pattern_cfg pattern = { | |
- .samples = { | |
- {0xff, T_LRA, false}, | |
- {0, 0, 0}, | |
- {0, 0, 0}, | |
- {0, 0, 0}, | |
- {0, 0, 0}, | |
- {0, 0, 0}, | |
- {0, 0, 0}, | |
- {0, 0, 0}, | |
- }, | |
- .play_rate_us = chip->config.t_lra_us + 2000, /* drive off resonance of the LRA */ | |
- .play_length_us = chip->config.t_lra_us + 2000, /* drive it at least 1 cycle */ | |
- .preload = false, | |
- }; | |
- | |
- /* calculate Vmax according to nominal resistance */ | |
- vmax_mv = RT_IMPD_DET_VMAX_DEFAULT_MV; | |
- current_sel = chip->clamp_at_5v ? CURRENT_SEL_VAL_125MA : CURRENT_SEL_VAL_250MA; | |
- if (chip->hap_cfg_nvmem != NULL) { | |
- rc = nvmem_device_read(chip->hap_cfg_nvmem, | |
- HAP_LRA_NOMINAL_OHM_SDAM_OFFSET, 1, &val); | |
- if (!rc && val) { | |
- nominal_ohm = val; | |
- /* | |
- * use 250mA current_sel when nominal impedance is lower than 15 Ohms | |
- * and use 125mA detection when nominal impedance is higher than 40 Ohms | |
- */ | |
- if (nominal_ohm < 15) | |
- current_sel = CURRENT_SEL_VAL_250MA; | |
- else if (nominal_ohm > 40) | |
- current_sel = CURRENT_SEL_VAL_125MA; | |
- | |
- /* | |
- * give 8 Ohms margin (1000mV / 125mA, or 2000mV / 250mA) for wider | |
- * detectability | |
- */ | |
- if (current_sel == CURRENT_SEL_VAL_125MA) { | |
- current_ma = 125; | |
- vmax_margin_mv = 1000; | |
- } else { | |
- current_ma = 250; | |
- vmax_margin_mv = 2000; | |
- } | |
- | |
- vmax_mv = max(vmax_mv, nominal_ohm * current_ma + vmax_margin_mv); | |
- } | |
- } | |
- | |
- dev_dbg(chip->dev, "Set %u mV Vmax for impedance detection\n", vmax_mv); | |
- rc = haptics_set_vmax_mv(chip, vmax_mv); | |
- if (rc < 0) | |
- return rc; | |
- | |
- /* set current for imp_det comparator and enable it */ | |
- val = LRA_IMPEDANCE_MEAS_EN_BIT | current_sel; | |
- rc = haptics_masked_write(chip, chip->cfg_addr_base, | |
- HAP_CFG_RT_LRA_IMPD_MEAS_CFG_REG, | |
- LRA_IMPEDANCE_MEAS_EN_BIT | | |
- LRA_IMPEDANCE_MEAS_CURRENT_SEL_BIT, val); | |
- if (rc < 0) | |
- return rc; | |
- | |
- /* disconnect imp_det comparator to avoid it impact SC behavior */ | |
- rc = haptics_masked_write(chip, chip->cfg_addr_base, | |
- HAP_CFG_ISC_CFG_REG, EN_IMP_DET_HAP525_HV_BIT, 0); | |
- if (rc < 0) | |
- goto restore; | |
- | |
- /* play 1 drive cycle using PATTERN1 source */ | |
- rc = haptics_set_pattern(chip, &pattern, PATTERN1); | |
- if (rc < 0) | |
- goto restore; | |
- | |
- chip->play.pattern_src = PATTERN1; | |
- rc = haptics_enable_play(chip, true); | |
- if (rc < 0) | |
- goto restore; | |
- | |
- usleep_range(pattern.play_length_us, pattern.play_length_us + 1); | |
- | |
- rc = haptics_enable_play(chip, false); | |
- if (rc < 0) | |
- goto restore; | |
- | |
- /* read the measured LRA impedance */ | |
- rc = haptics_read(chip, chip->cfg_addr_base, | |
- HAP_CFG_REAL_TIME_LRA_IMPEDANCE_REG, &val, 1); | |
- if (rc < 0) | |
- goto restore; | |
- | |
- chip->config.lra_measured_mohms = val * LRA_IMPEDANCE_MOHMS_LSB; | |
- dev_dbg(chip->dev, "measured LRA impedance: %u mohm", | |
- chip->config.lra_measured_mohms); | |
- /* store the detected LRA impedance into SDAM for future usage */ | |
- if (chip->hap_cfg_nvmem != NULL) { | |
- rc = nvmem_device_write(chip->hap_cfg_nvmem, HAP_LRA_DETECTED_OHM_SDAM_OFFSET, 1, | |
- &chip->config.lra_measured_mohms); | |
- if (rc < 0) | |
- dev_err(chip->dev, "write measured impedance value into SDAM failed, rc=%d\n", | |
- rc); | |
- } | |
-restore: | |
- if (rc < 0) | |
- dev_err(chip->dev, "measure LRA impedance failed, rc=%d\n", rc); | |
- | |
- return haptics_masked_write(chip, chip->cfg_addr_base, | |
- HAP_CFG_RT_LRA_IMPD_MEAS_CFG_REG, | |
- LRA_IMPEDANCE_MEAS_EN_BIT, 0); | |
-} | |
- | |
static int haptics_detect_lra_impedance(struct haptics_chip *chip) | |
{ | |
int rc, i; | |
@@ -4906,10 +4545,15 @@ static int haptics_detect_lra_impedance(struct haptics_chip *chip) | |
{ HAP_CFG_VMAX_HDRM_REG, 0x00 }, | |
}; | |
struct haptics_reg_info backup[LRA_CONFIG_REGS]; | |
- u8 val, cfg1, cfg2, reg1, reg2, mask1, mask2, val1, val2; | |
+ u8 val; | |
u32 duty_milli_pct, low_milli_pct, high_milli_pct; | |
u32 amplitude, lra_min_mohms, lra_max_mohms, capability_mohms; | |
+ if (chip->cfg_revision == HAP_CFG_V1) { | |
+ dev_dbg(chip->dev, "HAP_CFG V1.0 doesn't support impedance detection\n"); | |
+ return 0; | |
+ } | |
+ | |
/* Backup default register values */ | |
memcpy(backup, lra_config, sizeof(backup)); | |
for (i = 0; i < LRA_CONFIG_REGS; i++) { | |
@@ -4919,61 +4563,10 @@ static int haptics_detect_lra_impedance(struct haptics_chip *chip) | |
return rc; | |
} | |
- if (chip->hw_type == HAP520) { | |
- /* Trigger PBS to config 250mA ISC setting */ | |
- rc = haptics_pbs_trigger_isc_config(chip); | |
- if (rc < 0) | |
- return rc; | |
- } else { | |
- /* Config ISC_CFG settings for LRA impedance_detection */ | |
- switch (chip->hw_type) { | |
- case HAP520_MV: | |
- reg1 = HAP_CFG_ISC_CFG_REG; | |
- mask1 = ILIM_CC_EN_BIT; | |
- val1 = ILIM_CC_EN_BIT; | |
- reg2 = HAP_CFG_ISC_CFG2_REG; | |
- mask2 = EN_SC_DET_P_HAP520_MV_BIT | | |
- EN_SC_DET_N_HAP520_MV_BIT | | |
- ISC_THRESH_HAP520_MV_MASK; | |
- val2 = EN_SC_DET_P_HAP520_MV_BIT| | |
- EN_SC_DET_N_HAP520_MV_BIT| | |
- ISC_THRESH_HAP520_MV_140MA; | |
- break; | |
- case HAP525_HV: | |
- reg1 = HAP_CFG_ISC_CFG_REG; | |
- mask1 = EN_SC_DET_P_HAP525_HV_BIT | EN_SC_DET_N_HAP525_HV_BIT | | |
- EN_IMP_DET_HAP525_HV_BIT | ILIM_PULSE_DENSITY_MASK; | |
- val1 = EN_IMP_DET_HAP525_HV_BIT | | |
- FIELD_PREP(ILIM_PULSE_DENSITY_MASK, ILIM_DENSITY_8_OVER_64_CYCLES); | |
- reg2 = HAP_CFG_RT_LRA_IMPD_MEAS_CFG_REG; | |
- mask2 = LRA_IMPEDANCE_MEAS_EN_BIT | LRA_IMPEDANCE_MEAS_CURRENT_SEL_BIT; | |
- val2 = chip->clamp_at_5v ? CURRENT_SEL_VAL_125MA : CURRENT_SEL_VAL_250MA; | |
- val2 |= LRA_IMPEDANCE_MEAS_EN_BIT; | |
- break; | |
- default: | |
- dev_err(chip->dev, "unsupported HW type: %d\n", | |
- chip->hw_type); | |
- return -EOPNOTSUPP; | |
- } | |
- | |
- /* save ISC_CFG default settings */ | |
- rc = haptics_read(chip, chip->cfg_addr_base, reg1, &cfg1, 1); | |
- if (rc < 0) | |
- return rc; | |
- | |
- rc = haptics_read(chip, chip->cfg_addr_base, reg2, &cfg2, 1); | |
- if (rc < 0) | |
- return rc; | |
- | |
- /* update ISC_CFG settings for the detection */ | |
- rc = haptics_masked_write(chip, chip->cfg_addr_base, reg1, mask1, val1); | |
- if (rc < 0) | |
- return rc; | |
- | |
- rc = haptics_masked_write(chip, chip->cfg_addr_base, reg2, mask2, val2); | |
- if (rc < 0) | |
- goto restore; | |
- } | |
+ /* Trigger PBS to config 250mA ISC setting */ | |
+ rc = haptics_pbs_trigger_isc_config(chip); | |
+ if (rc < 0) | |
+ return rc; | |
/* Set square drive waveform, 10V Vmax, no HDRM */ | |
for (i = 0; i < LRA_CONFIG_REGS; i++) { | |
@@ -5050,21 +4643,10 @@ static int haptics_detect_lra_impedance(struct haptics_chip *chip) | |
if (rc < 0) | |
return rc; | |
- if (chip->hw_type == HAP520) { | |
- /* Trigger PBS to restore 1500mA ISC setting */ | |
- rc = haptics_pbs_trigger_isc_config(chip); | |
- if (rc < 0) | |
- return rc; | |
- } else { | |
- /* restore ISC_CFG settings to default */ | |
- rc = haptics_write(chip, chip->cfg_addr_base, reg1, &cfg1, 1); | |
- if (rc < 0) | |
- return rc; | |
- | |
- rc = haptics_write(chip, chip->cfg_addr_base, reg2, &cfg2, 1); | |
- if (rc < 0) | |
- return rc; | |
- } | |
+ /* Trigger PBS to restore 1500mA ISC setting */ | |
+ rc = haptics_pbs_trigger_isc_config(chip); | |
+ if (rc < 0) | |
+ return rc; | |
/* Restore driver waveform, Vmax, HDRM settings */ | |
for (i = 0; i < LRA_CONFIG_REGS; i++) { | |
@@ -5113,7 +4695,7 @@ static int haptics_detect_lra_frequency(struct haptics_chip *chip) | |
goto restore; | |
/* Fix Vmax to (hpwr_vreg_mv - hdrm_mv) in non-HBOOST regulator case */ | |
- if (is_haptics_external_powered(chip)) | |
+ if (chip->hpwr_vreg) | |
vmax_mv = chip->hpwr_voltage_mv - LRA_CALIBRATION_VMAX_HDRM_MV; | |
rc = haptics_set_vmax_mv(chip, vmax_mv); | |
@@ -5144,6 +4726,12 @@ static int haptics_detect_lra_frequency(struct haptics_chip *chip) | |
rc = haptics_enable_play(chip, false); | |
if (rc < 0) | |
goto restore; | |
+ | |
+//#ifdef ASUS_DAVINCI_PROJECT | |
+#if 0 | |
+ printk("haptic_d: %s: cl_t_lra_us=%d\n",__func__,chip->config.cl_t_lra_us); | |
+ write_cali_to_file(chip->config.cl_t_lra_us); | |
+#endif | |
haptics_config_openloop_lra_period(chip, chip->config.cl_t_lra_us); | |
@@ -5198,10 +4786,7 @@ static int haptics_start_lra_calibrate(struct haptics_chip *chip) | |
/* Sleep at least 4ms to stabilize the LRA from frequency detection */ | |
usleep_range(4000, 5000); | |
- if (chip->config.measure_lra_impedance) | |
- rc = haptics_measure_realtime_lra_impedance(chip); | |
- else | |
- rc = haptics_detect_lra_impedance(chip); | |
+ rc = haptics_detect_lra_impedance(chip); | |
if (rc < 0) { | |
dev_err(chip->dev, "Detect LRA impedance failed, rc=%d\n", rc); | |
goto unlock; | |
@@ -5239,11 +4824,29 @@ static ssize_t lra_frequency_hz_show(struct class *c, | |
{ | |
struct haptics_chip *chip = container_of(c, | |
struct haptics_chip, hap_class); | |
+//#ifndef ASUS_DAVINCI_PROJECT | |
+#if 1 | |
u32 cl_f_lra; | |
if (chip->config.cl_t_lra_us == 0) | |
return -EINVAL; | |
- | |
+#else | |
+ u32 cl_f_lra; | |
+ u32 cali=0; | |
+ | |
+ if (chip->config.cl_t_lra_us == 0) | |
+ return scnprintf(buf, PAGE_SIZE, "haptic_d: fail. please do calibration to get f0.\n"); | |
+ | |
+ if (get_cali_from_file(&cali) >= 0) | |
+ { | |
+ if (cali == 0xAA55) | |
+ return scnprintf(buf, PAGE_SIZE,"fail. cannot get cali value from saved file.\n"); | |
+ } | |
+ //printk("haptic_d: %s: t_lra_us=%d (%d Hz)\n",__func__, t_lra_us, USEC_PER_SEC/t_lra_us); | |
+ | |
+ if ( cali != chip->config.cl_t_lra_us ) | |
+ return scnprintf(buf, PAGE_SIZE, "haptic_d: fail. saved %d != configured %d \n",cali ,chip->config.cl_t_lra_us ); | |
+#endif | |
cl_f_lra = USEC_PER_SEC / chip->config.cl_t_lra_us; | |
return scnprintf(buf, PAGE_SIZE, "%d Hz\n", cl_f_lra); | |
} | |
@@ -5255,10 +4858,6 @@ static ssize_t lra_impedance_show(struct class *c, | |
struct haptics_chip *chip = container_of(c, | |
struct haptics_chip, hap_class); | |
- if (chip->config.measure_lra_impedance) | |
- return scnprintf(buf, PAGE_SIZE, "measured %u mohms\n", | |
- chip->config.lra_measured_mohms); | |
- | |
if (chip->config.lra_min_mohms == 0 && chip->config.lra_max_mohms == 0) | |
return -EINVAL; | |
else if (chip->config.lra_min_mohms == 0) | |
@@ -5272,48 +4871,50 @@ static ssize_t lra_impedance_show(struct class *c, | |
} | |
static CLASS_ATTR_RO(lra_impedance); | |
-static ssize_t primitive_duration_show(struct class *c, | |
- struct class_attribute *attr, char *buf) | |
-{ | |
- struct haptics_chip *chip = container_of(c, | |
- struct haptics_chip, hap_class); | |
- | |
- return scnprintf(buf, PAGE_SIZE, "%d\n", chip->primitive_duration); | |
-} | |
- | |
-static ssize_t primitive_duration_store(struct class *c, | |
+//#ifdef ASUS_DAVINCI_PROJECT | |
+#if 0 | |
+static ssize_t load_cali_store(struct class *c, | |
struct class_attribute *attr, const char *buf, size_t count) | |
{ | |
struct haptics_chip *chip = container_of(c, | |
struct haptics_chip, hap_class); | |
- u16 primitive_id = 0; | |
- int i = 0; | |
- | |
- if (kstrtou16(buf, 0, &primitive_id)) | |
- return -EINVAL; | |
- | |
- for (i = 0; i < chip->primitives_count; i++) { | |
- if (chip->primitives[i].id == primitive_id) | |
- break; | |
- } | |
- | |
- if (i == chip->primitives_count) { | |
- pr_err("Primitive id specified is incorrect\n"); | |
- return -EINVAL; | |
+ u32 cali=0; | |
+ bool val= 0; | |
+ if (kstrtobool(buf, &val)) | |
+ return -EINVAL; | |
+ | |
+ if(val) | |
+ { | |
+ if (get_cali_from_file(&cali) >= 0) | |
+ { | |
+ if (cali == 0xAA55){ | |
+ printk("haptic_d: fail. cannot get cali value from saved file.\n"); | |
+ return count; | |
+ } | |
+ } | |
+ //200~210 Hz <-> 5000~4761 us | |
+ //197~213 Hz <-> 5076~4694 us | |
+ if ((cali >= 4694) && (cali <= 5076)) | |
+ chip->config.cl_t_lra_us = cali; | |
+ else{ | |
+ printk("haptic_d: fail. saved cali value( %d us => %d Hz ) out of range. Not load cali value.\n", cali, USEC_PER_SEC/cali); | |
+ return count; | |
+ } | |
+ printk("haptic_d: %s: load cali value %d (%d Hz)\n",__func__, chip->config.cl_t_lra_us, USEC_PER_SEC/chip->config.cl_t_lra_us); | |
+ haptics_config_openloop_lra_period(chip, chip->config.cl_t_lra_us); | |
} | |
- | |
- chip->primitive_duration = get_play_length_effect_us(&chip->primitives[i]); | |
- | |
return count; | |
} | |
- | |
-static CLASS_ATTR_RW(primitive_duration); | |
- | |
+static CLASS_ATTR_WO(load_cali); | |
+#endif | |
static struct attribute *hap_class_attrs[] = { | |
&class_attr_lra_calibration.attr, | |
&class_attr_lra_frequency_hz.attr, | |
&class_attr_lra_impedance.attr, | |
- &class_attr_primitive_duration.attr, | |
+//#ifdef ASUS_DAVINCI_PROJECT | |
+#if 0 | |
+ &class_attr_load_cali.attr, | |
+#endif | |
NULL, | |
}; | |
ATTRIBUTE_GROUPS(hap_class); | |
@@ -5333,44 +4934,6 @@ static enum hrtimer_restart haptics_disable_hbst_timer(struct hrtimer *timer) | |
return HRTIMER_NORESTART; | |
} | |
-static bool is_swr_supported(struct haptics_chip *chip) | |
-{ | |
- /* HAP520_MV does not support soundwire */ | |
- if (chip->hw_type == HAP520_MV) | |
- return false; | |
- | |
- return true; | |
-} | |
- | |
-static int haptics_boost_notifier(struct notifier_block *nb, unsigned long event, void *val) | |
-{ | |
- struct haptics_chip *chip = container_of(nb, struct haptics_chip, hboost_nb); | |
- u32 vmax_mv; | |
- int rc; | |
- | |
- switch (event) { | |
- case VMAX_CLAMP: | |
- vmax_mv = *(u32 *)val; | |
- if (vmax_mv > MAX_HV_VMAX_MV) { | |
- dev_err(chip->dev, "voted Vmax (%u mV) is higher than maximum (%u mV)\n", | |
- vmax_mv, MAX_HV_VMAX_MV); | |
- return -EINVAL; | |
- } | |
- | |
- chip->clamped_vmax_mv = vmax_mv; | |
- dev_dbg(chip->dev, "Vmax is clamped at %u mV to support hBoost concurrency\n", | |
- vmax_mv); | |
- rc = haptics_force_vreg_ready(chip, vmax_mv == MAX_HV_VMAX_MV ? false : true); | |
- if (rc < 0) | |
- return rc; | |
- break; | |
- default: | |
- break; | |
- } | |
- | |
- return 0; | |
-} | |
- | |
static int haptics_probe(struct platform_device *pdev) | |
{ | |
struct haptics_chip *chip; | |
@@ -5411,13 +4974,11 @@ static int haptics_probe(struct platform_device *pdev) | |
return rc; | |
} | |
- if (is_swr_supported(chip)) { | |
- rc = haptics_init_swr_slave_regulator(chip); | |
- if (rc < 0) { | |
- dev_err(chip->dev, "Initialize swr slave regulator failed, rc = %d\n", | |
- rc); | |
- return rc; | |
- } | |
+ rc = haptics_init_swr_slave_regulator(chip); | |
+ if (rc < 0) { | |
+ dev_err(chip->dev, "Initialize swr slave regulator failed, rc = %d\n", | |
+ rc); | |
+ return rc; | |
} | |
rc = devm_request_threaded_irq(chip->dev, chip->fifo_empty_irq, | |
@@ -5444,15 +5005,15 @@ static int haptics_probe(struct platform_device *pdev) | |
input_set_capability(input_dev, EV_FF, FF_CONSTANT); | |
input_set_capability(input_dev, EV_FF, FF_GAIN); | |
- if ((chip->effects_count != 0) || (chip->primitives_count != 0)) { | |
+ if (chip->effects_count != 0) { | |
input_set_capability(input_dev, EV_FF, FF_PERIODIC); | |
input_set_capability(input_dev, EV_FF, FF_CUSTOM); | |
} | |
- if (chip->effects_count + chip->primitives_count > MAX_EFFECT_COUNT) | |
- dev_err(chip->dev, "Effects count cannot be more than %d\n", MAX_EFFECT_COUNT); | |
- | |
- count = min_t(u32, chip->effects_count + chip->primitives_count + 1, MAX_EFFECT_COUNT); | |
+ if (chip->effects_count < MAX_EFFECT_COUNT) | |
+ count = chip->effects_count + 1; | |
+ else | |
+ count = MAX_EFFECT_COUNT; | |
rc = input_ff_create(input_dev, count); | |
if (rc < 0) { | |
@@ -5482,13 +5043,14 @@ static int haptics_probe(struct platform_device *pdev) | |
goto destroy_ff; | |
} | |
- chip->hboost_nb.notifier_call = haptics_boost_notifier; | |
- register_hboost_event_notifier(&chip->hboost_nb); | |
#ifdef CONFIG_DEBUG_FS | |
rc = haptics_create_debugfs(chip); | |
if (rc < 0) | |
dev_err(chip->dev, "Creating debugfs failed, rc=%d\n", rc); | |
#endif | |
+ | |
+ printk("haptic_d: probe complete\n"); | |
+ | |
return 0; | |
destroy_ff: | |
input_ff_destroy(chip->input_dev); | |
@@ -5502,7 +5064,6 @@ static int haptics_remove(struct platform_device *pdev) | |
if (chip->pbs_node) | |
of_node_put(chip->pbs_node); | |
- unregister_hboost_event_notifier(&chip->hboost_nb); | |
class_unregister(&chip->hap_class); | |
#ifdef CONFIG_DEBUG_FS | |
debugfs_remove_recursive(chip->debugfs_dir); | |
@@ -5513,49 +5074,16 @@ static int haptics_remove(struct platform_device *pdev) | |
return 0; | |
} | |
-static void haptics_ds_suspend_config(struct device *dev) | |
-{ | |
- struct haptics_chip *chip = dev_get_drvdata(dev); | |
- | |
- if (chip->fifo_empty_irq > 0) | |
- devm_free_irq(dev, chip->fifo_empty_irq, chip); | |
-} | |
- | |
-static int haptics_ds_resume_config(struct device *dev) | |
-{ | |
- struct haptics_chip *chip = dev_get_drvdata(dev); | |
- int rc = 0; | |
- | |
- rc = haptics_hw_init(chip); | |
- if (rc < 0) { | |
- dev_err(chip->dev, "Initialize HW failed, rc = %d\n", rc); | |
- return rc; | |
- } | |
- | |
- if (chip->fifo_empty_irq > 0) { | |
- rc = devm_request_threaded_irq(chip->dev, chip->fifo_empty_irq, | |
- NULL, fifo_empty_irq_handler, | |
- IRQF_ONESHOT, "fifo-empty", chip); | |
- if (rc < 0) { | |
- dev_err(chip->dev, "request fifo-empty IRQ failed, rc=%d\n", | |
- rc); | |
- return rc; | |
- } | |
- | |
- disable_irq_nosync(chip->fifo_empty_irq); | |
- chip->fifo_empty_irq_en = false; | |
- } | |
- | |
- return rc; | |
-} | |
- | |
#ifdef CONFIG_PM_SLEEP | |
-static int haptics_suspend_config(struct device *dev) | |
+static int haptics_suspend(struct device *dev) | |
{ | |
struct haptics_chip *chip = dev_get_drvdata(dev); | |
struct haptics_play_info *play = &chip->play; | |
int rc; | |
+ if (chip->cfg_revision == HAP_CFG_V1) | |
+ return 0; | |
+ | |
mutex_lock(&play->lock); | |
if ((play->pattern_src == FIFO) && | |
atomic_read(&play->fifo_status.is_busy)) { | |
@@ -5583,10 +5111,8 @@ static int haptics_suspend_config(struct device *dev) | |
* Cancel the hBoost turning off timer and disable | |
* hBoost if it's still enabled | |
*/ | |
- if (chip->wa_flags & SW_CTRL_HBST) { | |
- hrtimer_cancel(&chip->hbst_off_timer); | |
- haptics_boost_vreg_enable(chip, false); | |
- } | |
+ hrtimer_cancel(&chip->hbst_off_timer); | |
+ haptics_boost_vreg_enable(chip, false); | |
rc = haptics_enable_hpwr_vreg(chip, false); | |
if (rc < 0) | |
return rc; | |
@@ -5594,95 +5120,24 @@ static int haptics_suspend_config(struct device *dev) | |
return haptics_module_enable(chip, false); | |
} | |
-static int haptics_suspend(struct device *dev) | |
+static int haptics_resume(struct device *dev) | |
{ | |
struct haptics_chip *chip = dev_get_drvdata(dev); | |
- int rc = 0; | |
if (chip->cfg_revision == HAP_CFG_V1) | |
return 0; | |
- rc = haptics_suspend_config(dev); | |
- if (rc < 0) | |
- return rc; | |
- | |
-#ifdef CONFIG_DEEPSLEEP | |
- if (mem_sleep_current == PM_SUSPEND_MEM) | |
- haptics_ds_suspend_config(dev); | |
-#endif | |
- | |
- return 0; | |
-} | |
- | |
-static int haptics_resume(struct device *dev) | |
-{ | |
- struct haptics_chip *chip = dev_get_drvdata(dev); | |
- | |
-#ifdef CONFIG_DEEPSLEEP | |
- if (mem_sleep_current == PM_SUSPEND_MEM) { | |
- int rc = 0; | |
- | |
- rc = haptics_ds_resume_config(dev); | |
- if (rc < 0) | |
- return rc; | |
- } | |
-#endif | |
- | |
return haptics_module_enable(chip, true); | |
} | |
#endif | |
-static int haptics_freeze(struct device *dev) | |
-{ | |
- int rc = 0; | |
- | |
- rc = haptics_suspend_config(dev); | |
- if (rc < 0) | |
- return rc; | |
- | |
- haptics_ds_suspend_config(dev); | |
- | |
- return 0; | |
-} | |
- | |
-static int haptics_restore(struct device *dev) | |
-{ | |
- struct haptics_chip *chip = dev_get_drvdata(dev); | |
- int rc = 0; | |
- | |
- rc = haptics_ds_resume_config(dev); | |
- if (rc < 0) | |
- return rc; | |
- | |
- return haptics_module_enable(chip, true); | |
-} | |
- | |
-static void haptics_shutdown(struct platform_device *pdev) | |
-{ | |
- struct haptics_chip *chip = platform_get_drvdata(pdev); | |
- | |
- haptics_suspend_config(chip->dev); | |
- | |
- haptics_ds_suspend_config(chip->dev); | |
-} | |
- | |
static const struct dev_pm_ops haptics_pm_ops = { | |
- .suspend = haptics_suspend, | |
- .resume = haptics_resume, | |
- .freeze = haptics_freeze, | |
- .restore = haptics_restore, | |
+ SET_SYSTEM_SLEEP_PM_OPS(haptics_suspend, haptics_resume) | |
}; | |
static const struct of_device_id haptics_match_table[] = { | |
- { | |
- .compatible = "qcom,hv-haptics", | |
- }, | |
- { | |
- .compatible = "qcom,pm8350b-haptics", | |
- }, | |
- { | |
- .compatible = "qcom,pm5100-haptics", | |
- }, | |
+ { .compatible = "qcom,hv-haptics" }, | |
+ { .compatible = "qcom,pm8350b-haptics" }, | |
{}, | |
}; | |
@@ -5693,7 +5148,6 @@ static struct platform_driver haptics_driver = { | |
.pm = &haptics_pm_ops, | |
}, | |
.probe = haptics_probe, | |
- .shutdown = haptics_shutdown, | |
.remove = haptics_remove, | |
}; | |
module_platform_driver(haptics_driver); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment