summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjeongsup.jeong <jeongsup.jeong@samsung.com>2020-04-24 16:02:43 +0900
committerChanwoo Choi <cw00.choi@samsung.com>2020-04-24 16:02:43 +0900
commitb402b6d9a914d3f6543542ce88eaeed0548da28a (patch)
tree305f1eea86cd20b1adc7b4c24b11f822f001ba6d
parent0dadfbba8f1691ba68610dd0d70a5d401cde3dbd (diff)
downloadlinux-4.9-exynos9110-b402b6d9a914d3f6543542ce88eaeed0548da28a.tar.gz
linux-4.9-exynos9110-b402b6d9a914d3f6543542ce88eaeed0548da28a.tar.bz2
linux-4.9-exynos9110-b402b6d9a914d3f6543542ce88eaeed0548da28a.zip
Motor: add handling freq, overdrive param on ff effect
TODO Signed-off-by: jeongsup.jeong <jeongsup.jeong@samsung.com> [cw00.choi: Apply commit 84d896106285 ("Motor: add handling freq, overdrive param on ff effect") from slp-info.sec.samsung.net with fixing the merge conflit and add commit-msg] Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
-rw-r--r--drivers/motor/ztm620_motor.c146
-rw-r--r--include/linux/ztm620_motor.h12
2 files changed, 102 insertions, 56 deletions
diff --git a/drivers/motor/ztm620_motor.c b/drivers/motor/ztm620_motor.c
index c85f6091db92..4f6e18d5c61a 100644
--- a/drivers/motor/ztm620_motor.c
+++ b/drivers/motor/ztm620_motor.c
@@ -105,31 +105,44 @@ static int ztm620_motor_set_bits(struct ztm620_motor_data *pMotorData,
static int ztm620_motor_run(void) {
int ret = -EINVAL;
unsigned char val, strength;
- int freq;
+ int freq_reg, freq_hz;
struct ztm620_motor_data *pMotorData = g_Ztm620MotorData;
struct ztm620_motor_platform_data *pMotorPdata;
- if (pMotorData == NULL) {
+ if (!pMotorData) {
pr_err("[VIB] %s ztm620_motor_data NULL error\n", __func__);
goto out;
}
else
pMotorPdata = &pMotorData->msPlatData;
- if (pMotorData->level == 0) {
+ if (!(pMotorData->level)) {
pr_err("[VIB] %s: level 0\n", __func__);
goto out;
}
ret = ztm620_motor_reg_write(pMotorData, MOTOR_REG_SOFT_EN, SOFT_ENABLE);
if (ret < 0) {
- pr_err("[VIB] %s SOFT_EN write fail %d\n",
- __func__, ret);
+ pr_err("[VIB] %s SOFT_EN write fail (%d)\n", __func__, ret);
goto out;
}
+
if (pMotorPdata->soft_en_delay)
msleep(pMotorPdata->soft_en_delay);
+ if (pMotorData->overdrive && pMotorPdata->overdrive_num) {
+ val = (pMotorData->overdrive & MOTOR_REG_OVER_DRV_EN_MASK)
+ << OVER_DRV_SHIFT_EN;
+ val |= (pMotorPdata->overdrive_num & MOTOR_REG_OVER_DRV_CNT_MASK)
+ << OVER_DRV_SHIFT_CNT;
+ ret = ztm620_motor_reg_write(pMotorData, MOTOR_REG_OVER_DRV, val);
+ if (ret < 0) {
+ pr_err("[VIB] %s OVER_DRV 0x%02x write fail (%d)\n",
+ __func__, MOTOR_REG_OVER_DRV, ret);
+ goto out;
+ }
+ }
+
if (pMotorData->level >= MAX_LEVEL)
strength = pMotorPdata->strength_strong;
else
@@ -137,17 +150,17 @@ static int ztm620_motor_run(void) {
ret = ztm620_motor_reg_write(pMotorData, MOTOR_REG_STRENGTH, strength);
if (ret < 0) {
- pr_err("[VIB] %s STRENGTH write %d fail %d\n",
- __func__, strength, ret);
+ pr_err("[VIB] %s STRENGTH 0x%02x write %d fail (%d)\n",
+ __func__, MOTOR_REG_STRENGTH, strength, ret);
goto out;
}
- val = (pMotorPdata->meLoop << MODE_01_SHIFT_DRV_MODE );
- ret = ztm620_motor_set_bits(pMotorData,
- MOTOR_REG_MODE_01, (1 << MODE_01_SHIFT_DRV_MODE), val);
+ ret = ztm620_motor_set_bits(pMotorData, MOTOR_REG_MODE_01,
+ 1 << MODE_01_SHIFT_DRV_MODE,
+ pMotorPdata->meLoop << MODE_01_SHIFT_DRV_MODE);
if (ret < 0) {
pr_err("[VIB] %s MODE_01 0x%02x write fail (%d)\n",
- __func__, MOTOR_REG_MODE_01, ret);
+ __func__, MOTOR_REG_MODE_01, ret);
goto out;
}
@@ -156,49 +169,60 @@ static int ztm620_motor_run(void) {
Clock Frequency / (16 Clocks * Driving Frequency)
DRV_FREQ_H[7:0] = DRV_FREQ[15:8]
DRV_FREQ_L[7:0] = DRV_FREQ[7:0] */
- if (pMotorData->level >= MAX_LEVEL)
- freq = MOTOR_CLK / (16 * pMotorPdata->freq_strong);
- else
- freq = MOTOR_CLK / (16 * pMotorPdata->freq_weak);
+ if (pMotorData->level >= MAX_LEVEL) {
+ if (pMotorPdata->freq_strong)
+ freq_hz = pMotorPdata->freq_strong;
+ else if (pMotorData->frequency)
+ freq_hz = pMotorData->frequency;
+ else
+ freq_hz = DEFAULT_MOTOR_FREQ;
+ } else {
+ if (pMotorPdata->freq_weak)
+ freq_hz = pMotorPdata->freq_weak;
+ else if (pMotorData->frequency)
+ freq_hz = pMotorData->frequency;
+ else
+ freq_hz = DEFAULT_MOTOR_FREQ;
+ }
+ freq_reg = (MOTOR_CLK * 10) / (freq_hz * 16);
ret = ztm620_motor_reg_write(pMotorData,
- MOTOR_REG_DRV_FREQ_H, freq / 256);
+ MOTOR_REG_DRV_FREQ_H, freq_reg / 256);
if (ret < 0) {
pr_err("[VIB] %s DRV_FREQ_H 0x%02x write fail (%d)\n",
- __func__, MOTOR_REG_DRV_FREQ_H, ret);
+ __func__, MOTOR_REG_DRV_FREQ_H, ret);
goto out;
}
ret = ztm620_motor_reg_write(pMotorData,
- MOTOR_REG_DRV_FREQ_L, freq % 256);
+ MOTOR_REG_DRV_FREQ_L, freq_reg % 256);
if (ret < 0) {
pr_err("[VIB] %s DRV_FREQ_L 0x%02x write fail (%d)\n",
- __func__, MOTOR_REG_DRV_FREQ_L, ret);
+ __func__, MOTOR_REG_DRV_FREQ_L, ret);
goto out;
}
ret = ztm620_motor_reg_write(pMotorData,
- MOTOR_REG_RESO_FREQ_H, freq / 256);
+ MOTOR_REG_RESO_FREQ_H, freq_reg / 256);
if (ret < 0) {
pr_err("[VIB] %s RESO_FREQ_H 0x%02x write fail (%d)\n",
- __func__, MOTOR_REG_RESO_FREQ_H, ret);
+ __func__, MOTOR_REG_RESO_FREQ_H, ret);
goto out;
}
ret = ztm620_motor_reg_write(pMotorData,
- MOTOR_REG_RESO_FREQ_L, freq % 256);
+ MOTOR_REG_RESO_FREQ_L, freq_reg % 256);
if (ret < 0) {
pr_err("[VIB] %s RESO_FREQ_L 0x%02x write fail (%d)\n",
- __func__, MOTOR_REG_RESO_FREQ_L, ret);
+ __func__, MOTOR_REG_RESO_FREQ_L, ret);
goto out;
}
- val = pMotorPdata->adc_sampling_time;
ret = ztm620_motor_reg_write(pMotorData,
- MOTOR_REG_ADC_SAMPLING_TIME, val);
+ MOTOR_REG_ADC_SAMPLING_TIME, pMotorPdata->adc_sampling_time);
if (ret < 0) {
- pr_err("[VIB] %s ADC_SAMPLING_TIME write fail %d\n",
- __func__, ret);
+ pr_err("[VIB] %s ADC_SAMPLING_TIME 0x%02x write fail (%d)\n",
+ __func__, MOTOR_REG_ADC_SAMPLING_TIME, ret);
goto out;
}
@@ -216,8 +240,11 @@ static int ztm620_motor_run(void) {
}
pMotorData->running = true;
}
- pr_info("[VIB] %s Run: level:0x%x freq:0x%x str:0x%x\n",
- __func__, pMotorData->level, freq, strength);
+
+ pr_info("[VIB] Start: str 0x%x(0x%x) freq 0x%x(%d.%d) ovd %d\n",
+ strength, pMotorData->level,
+ freq_reg, freq_hz / 10, freq_hz % 10,
+ pMotorData->overdrive?pMotorPdata->overdrive_num:-1);
out:
return ret;
@@ -269,7 +296,7 @@ static void vibrator_work_routine(struct work_struct *work)
}
pMotorData->running = false;
pMotorData->last_motor_off = CURRENT_TIME;
- pr_info("[VIB] %s Stop\n", __func__);
+ pr_info("[VIB] Stop\n");
}
out:
@@ -323,6 +350,10 @@ static int ztm620_motor_haptic_play(struct input_dev *input, void *data,
{
struct ztm620_motor_data *pMotorData = input_get_drvdata(input);
__u16 level = effect->u.rumble.strong_magnitude;
+ /* [14:0] */
+ pMotorData->frequency = effect->u.rumble.weak_magnitude & 0x7fff;
+ /* [15:15] */
+ pMotorData->overdrive = !!(effect->u.rumble.weak_magnitude & 0x8000 >> 15);
if (level) {
pMotorData->level = level;
@@ -615,8 +646,7 @@ static int of_ztm620_motor_dt(struct i2c_client* client, struct ztm620_motor_pla
pdata->break_delay = DEFAULT_BRAKE_DELAY;
dev_warn(&client->dev, "[VIB] %s: brake-delay-ms read fail(%d) :%d\n",
__func__, err, pdata->break_delay);
- }
- else
+ } else
pr_info("[VIB] brake-delay-ms = %d\n", pdata->break_delay);
pdata->count_init_regs = of_property_count_u32_elems(client->dev.of_node,
@@ -651,62 +681,70 @@ static int of_ztm620_motor_dt(struct i2c_client* client, struct ztm620_motor_pla
"ztm620_motor,adc-sampling-time", &pdata->adc_sampling_time);
if (err < 0) {
pdata->adc_sampling_time = DEFAULT_ADC_SAMPLING_TIME;
- dev_warn(&client->dev, "[VIB] %s: adc-sampling-time read fail(%d) :%d\n",
+ pr_warn("[VIB] %s: adc-sampling-time read fail(%d) :%d\n",
__func__, err, pdata->adc_sampling_time);
- }
- else
+ } else
pr_info("[VIB] adc-sampling-time = %d\n", pdata->adc_sampling_time);
err = of_property_read_u32(client->dev.of_node,
"ztm620_motor,soft-en-delay-ms", &pdata->soft_en_delay);
if (err < 0) {
pdata->soft_en_delay = DEFAULT_SOFT_EN_DELAY;
- dev_warn(&client->dev, "[VIB] %s: soft-en-delay-ms read fail(%d) :%d\n",
+ pr_warn("[VIB] %s: soft-en-delay-ms read fail(%d) :%d\n",
__func__, err, pdata->soft_en_delay);
- }
- else
+ } else
pr_info("[VIB] soft-en-delay-ms = %d\n", pdata->soft_en_delay);
err = of_property_read_u32(client->dev.of_node,
"ztm620_motor,freq-strong", &pdata->freq_strong);
- if (err < 0) {
- pdata->freq_strong = DEFAULT_MOTOR_FREQ;
- dev_warn(&client->dev, "[VIB] %s: freq-strong read fail(%d) :%d\n",
+ if (err < 0)
+ pr_warn("[VIB] %s: freq-strong read fail(%d) :%d\n",
__func__, err, pdata->freq_strong);
+ else {
+ /* TBD: need to handle float value from dt */
+ pdata->freq_strong *= 10;
+ pr_info("[VIB] freq-strong = %d.%d\n",
+ pdata->freq_strong / 10, pdata->freq_strong % 10);
}
- else
- pr_info("[VIB] freq-strong = %d\n", pdata->freq_strong);
err = of_property_read_u32(client->dev.of_node,
"ztm620_motor,freq-weak", &pdata->freq_weak);
- if (err < 0) {
- pdata->freq_weak = DEFAULT_MOTOR_FREQ;
- dev_warn(&client->dev, "[VIB] %s: freq-weak read fail(%d) :%d\n",
+ if (err < 0)
+ pr_warn("[VIB] %s: freq-weak read fail(%d) :%d\n",
__func__, err, pdata->freq_weak);
+ else {
+ /* TBD: need to handle float value from dt */
+ pdata->freq_weak *= 10;
+ pr_info("[VIB] freq-weak = %d.%d\n",
+ pdata->freq_weak / 10, pdata->freq_weak % 10);
}
- else
- pr_info("[VIB] freq-weak = %d\n", pdata->freq_weak);
err = of_property_read_u32(client->dev.of_node,
"ztm620_motor,strength-strong", &pdata->strength_strong);
if (err < 0) {
pdata->strength_strong = DEFAULT_MOTOR_STRENGTH;
- dev_warn(&client->dev, "[VIB] %s: strength-strong read fail(%d) :%d\n",
+ pr_warn("[VIB] %s: strength-strong read fail(%d) :%d\n",
__func__, err, pdata->strength_strong);
- }
- else
+ } else
pr_info("[VIB] strength-strong = %d\n", pdata->strength_strong);
err = of_property_read_u32(client->dev.of_node,
"ztm620_motor,strength-weak", &pdata->strength_weak);
if (err < 0) {
pdata->strength_weak = DEFAULT_MOTOR_STRENGTH;
- dev_warn(&client->dev, "[VIB] %s: strength-weak read fail(%d) :%d\n",
+ pr_warn("[VIB] %s: strength-weak read fail(%d) :%d\n",
__func__, err, pdata->strength_weak);
- }
- else
+ } else
pr_info("[VIB] strength-weak = %d\n", pdata->strength_weak);
+ err = of_property_read_u32(client->dev.of_node,
+ "ztm620_motor,overdrive-num", &pdata->overdrive_num);
+ if (err < 0) {
+ pr_warn("[VIB] %s: overdrive-num read fail(%d) :%d\n",
+ __func__, err, pdata->overdrive_num);
+ } else
+ pr_info("[VIB] overdrive-num = %d\n", pdata->overdrive_num);
+
dev_info(&client->dev, "[VIB] %s: dt parsing done\n", __func__);
return ret;
diff --git a/include/linux/ztm620_motor.h b/include/linux/ztm620_motor.h
index 9efa64d1c31d..fa33b01a9196 100644
--- a/include/linux/ztm620_motor.h
+++ b/include/linux/ztm620_motor.h
@@ -81,6 +81,11 @@
#define MODE_13_SHIFT_PWR_CAL_EN 0x03
#define MODE_13_SHIFT_ERM_NLRA 0x00
+#define MOTOR_REG_OVER_DRV_EN_MASK 0x01
+#define MOTOR_REG_OVER_DRV_CNT_MASK 0x7F
+#define OVER_DRV_SHIFT_EN 7
+#define OVER_DRV_SHIFT_CNT 0
+
#define MAX_LEVEL 0xffff
#define DEFAULT_MOTOR_FREQ 205
#define DEFAULT_MOTOR_STRENGTH 0x56
@@ -121,10 +126,11 @@ struct ztm620_motor_platform_data {
const char *regulator_name;
int adc_sampling_time;
int soft_en_delay;
- int freq_strong;
- int freq_weak;
+ int freq_strong; /* in 0.1 hz*/
+ int freq_weak; /* in 0.1 hz*/
int strength_strong;
int strength_weak;
+ int overdrive_num;
};
struct ztm620_motor_data {
@@ -142,6 +148,8 @@ struct ztm620_motor_data {
/* using FF_input_device */
__u16 level;
+ __u16 frequency; /* in 0.1 hz*/
+ __u16 overdrive;
bool running;
struct regulator *regulator;
int gpio_en;