diff options
author | jeongsup.jeong <jeongsup.jeong@samsung.com> | 2019-12-27 15:09:50 +0900 |
---|---|---|
committer | Seung-Woo Kim <sw0312.kim@samsung.com> | 2020-05-11 00:41:22 +0000 |
commit | 3111ced5747423b05e4a2bdfecba8b519bf9f23a (patch) | |
tree | ccf2c0bdfb15e4f9c2c0ad136b7026bff495c690 | |
parent | 58c9cdc9071f28c64e5d2f5122dd0581a2fe052a (diff) | |
download | linux-4.9-exynos9110-3111ced5747423b05e4a2bdfecba8b519bf9f23a.tar.gz linux-4.9-exynos9110-3111ced5747423b05e4a2bdfecba8b519bf9f23a.tar.bz2 linux-4.9-exynos9110-3111ced5747423b05e4a2bdfecba8b519bf9f23a.zip |
Motor: change motor control parameters for new haptic concept
Change the motor control parameters which are used for communicating
between feedbackd in user-space and motor device driver in kernel.
[Detailed motor control parameters]
struct ff_rumble_effect {
__u16 strong_magnitude; // strong_magnitude[15:15] = 0 (Reserved)
// strong_magnitude[14:14]
// = Overdrive : 0 (Off) or 1 (On)
// strong_magnitude[13:0]
// = Intensity Value : 0 (Stop)
// or 1 ~ 10000 (Intensity)
__u16 weak_magnitude; // weak_magnitude[15:13]
// = Intensity Level : 1 ~ 5
// weak_magnitude[12:0]
// = Frequency in 0.1Hz : 0 ~ 8191 (0 ~ 819.1 Hz)
}; */
Change-Id: I3d65855086c2685ddaea3a494d2109f86a29cdbd
Signed-off-by: jeongsup.jeong <jeongsup.jeong@samsung.com>
[cw00.choi: Add commit-msg as the public style]
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
-rw-r--r-- | drivers/motor/ztm620_motor.c | 181 | ||||
-rw-r--r-- | include/linux/ztm620_motor.h | 30 |
2 files changed, 122 insertions, 89 deletions
diff --git a/drivers/motor/ztm620_motor.c b/drivers/motor/ztm620_motor.c index f3f2269f4a50..7f069b479e3c 100644 --- a/drivers/motor/ztm620_motor.c +++ b/drivers/motor/ztm620_motor.c @@ -116,8 +116,32 @@ static int ztm620_motor_run(void) { else pMotorPdata = &pMotorData->msPlatData; - if (!(pMotorData->level)) { - pr_err("[VIB] %s: level 0\n", __func__); + /* intensity level cannot be 0 and also cannot exceed + the number of strength values defined in dts */ + if (pMotorData->intensity_level == 0 + || pMotorData->intensity_level > pMotorPdata->count_strength) { + pr_err("[VIB] %s level error: level %d, str_cnt %d", + __func__, pMotorData->intensity_level, + pMotorPdata->count_strength); + goto out; + } + + /* strength is calculated with the level-mapped value in dt + multiplying intensity value out of 10000 */ + strength = pMotorPdata->strength[pMotorData->intensity_level - 1] + * pMotorData->intensity_value / 10000; + + if (pMotorPdata->count_frequency >= pMotorData->intensity_level) + /* use frequency value in dt if the requested level is mapped */ + freq_hz = pMotorPdata->frequency[pMotorData->intensity_level - 1]; + else if (pMotorData->frequency) + /* use frequency value given from platform if exists */ + freq_hz = pMotorData->frequency; + else { + pr_err("[VIB] %s frequency error: freq_cnt %d, level %d, freq %d", + __func__, pMotorPdata->count_frequency, + pMotorData->intensity_level, + pMotorData->frequency); goto out; } @@ -130,7 +154,7 @@ static int ztm620_motor_run(void) { if (pMotorPdata->soft_en_delay) msleep(pMotorPdata->soft_en_delay); - if (pMotorData->overdrive && pMotorPdata->overdrive_num) { + if (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) @@ -143,11 +167,6 @@ static int ztm620_motor_run(void) { } } - if (pMotorData->level >= MAX_LEVEL) - strength = pMotorPdata->strength_strong; - else - strength = pMotorPdata->strength_weak; - ret = ztm620_motor_reg_write(pMotorData, MOTOR_REG_STRENGTH, strength); if (ret < 0) { pr_err("[VIB] %s STRENGTH 0x%02x write %d fail (%d)\n", @@ -168,22 +187,7 @@ static int ztm620_motor_run(void) { -> DRV_FREQ = Driving Period / (16 Clocks * Clock Period) 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) { - 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; - } + DRV_FREQ_L[7:0] = DRV_FREQ[7:0] */ freq_reg = (MOTOR_CLK * 10) / (freq_hz * 16); ret = ztm620_motor_reg_write(pMotorData, @@ -240,8 +244,10 @@ static int ztm620_motor_run(void) { pMotorData->running = true; } - pr_info("[VIB] Start: str 0x%x(0x%x) freq 0x%x(%d.%d) ovd %d\n", - strength, pMotorData->level, + /* -1 for ovd means overdrive requested to be off by platform */ + pr_info("[VIB] Start: level %d, value 0x%x(%d), freq 0x%x(%d.%d), ovd %d\n", + pMotorData->intensity_level, + strength, pMotorData->intensity_value, freq_reg, freq_hz / 10, freq_hz % 10, pMotorData->overdrive?pMotorPdata->overdrive_num:-1); @@ -265,7 +271,7 @@ static void vibrator_work_routine(struct work_struct *work) mutex_lock(&pMotorData->lock); if (is_suspend) goto out; - if (pMotorData->level) { + if (pMotorData->intensity_value) { err = ztm620_motor_run(); if (err < 0) { pr_err("[VIB] %s motor run fail %d\n", __func__, err); @@ -348,20 +354,31 @@ static int ztm620_motor_haptic_play(struct input_dev *input, void *data, struct ff_effect *effect) { 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; - queue_work(system_highpri_wq, &pMotorData->vibrator_work); - } - else { - pMotorData->level = 0; - queue_work(system_highpri_wq, &pMotorData->vibrator_work); - } + + /* using ff_runble effect */ + /* struct ff_rumble_effect { + __u16 strong_magnitude; // strong_magnitude[15:15] = 0 (Reserved) + // strong_magnitude[14:14] + // = Overdrive : 0 (Off) or 1 (On) + // strong_magnitude[13:0] + // = Intensity Value : 0 (Stop) + // or 1 ~ 10000 (Intensity) + __u16 weak_magnitude; // weak_magnitude[15:13] + // = Intensity Level : 1 ~ 5 + // weak_magnitude[12:0] + // = Frequency in 0.1Hz : 0 ~ 8191 (0 ~ 819.1 Hz) + }; */ + + pr_info("[VIB] %s param 0x%X 0x%X", __func__, + effect->u.rumble.strong_magnitude, + effect->u.rumble.weak_magnitude); + + pMotorData->overdrive = (effect->u.rumble.strong_magnitude & 0x4000) >> 14; + pMotorData->intensity_value = effect->u.rumble.strong_magnitude & 0x3fff; + pMotorData->intensity_level = (effect->u.rumble.weak_magnitude & 0xe000) >> 13; + pMotorData->frequency = effect->u.rumble.weak_magnitude & 0x1fff; + + queue_work(system_highpri_wq, &pMotorData->vibrator_work); return 0; } @@ -477,7 +494,7 @@ static int ztm620_motor_pm_notifier(struct notifier_block *notifier, if (pMotorData->running) pr_warn("[VIB] %s: motor is running", __func__); else if (pm_noti_test) { - pMotorData->level = 0; + pMotorData->intensity_value = 0; pr_info("[VIB] %s: test suspend stop", __func__); } else { @@ -514,10 +531,10 @@ static int ztm620_motor_pm_notifier(struct notifier_block *notifier, mutex_lock(&pMotorData->lock); is_suspend = false; - if (pMotorData->level) + if (pMotorData->intensity_value) pr_warn("[VIB] %s: motor is to run", __func__); else if (pm_noti_test) { - pMotorData->level = MAX_LEVEL; + pMotorData->intensity_value = MAX_INTENSITY_VALUE; pr_info("[VIB] %s test resume run", __func__); } else { @@ -597,6 +614,7 @@ static int of_ztm620_motor_dt(struct i2c_client* client, struct ztm620_motor_pla int ret = 0; const char *motor_type; const char *loop_type; + int i; dev_info(&client->dev, "[VIB] %s: dt parsing start\n", __func__); @@ -698,47 +716,48 @@ static int of_ztm620_motor_dt(struct i2c_client* client, struct ztm620_motor_pla } 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) - 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); - } + /* array elements of strength are assigned for each intensity level + starting from level 1 and increasing */ + pdata->count_strength = of_property_count_u32_elems(client->dev.of_node, + "ztm620_motor,strength"); + pr_info("[VIB] strength count = %d", pdata->count_strength); + if (pdata->count_strength > 0) { + pdata->strength = devm_kzalloc(&client->dev, + sizeof(u32) * pdata->count_strength, GFP_KERNEL); + err = of_property_read_u32_array(client->dev.of_node, + "ztm620_motor,strength", + (u32 *)pdata->strength, pdata->count_strength); + if (err < 0) { + dev_err(&client->dev, "[VIB] %s: strength read fail(%d)\n", + __func__, err); + } - err = of_property_read_u32(client->dev.of_node, - "ztm620_motor,freq-weak", &pdata->freq_weak); - 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); + for (i = 0; i < pdata->count_strength; i++) { + pr_info("[VIB] strength[%d] = %d\n", i, pdata->strength[i]); + } } - 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; - pr_warn("[VIB] %s: strength-strong read fail(%d) :%d\n", - __func__, err, pdata->strength_strong); - } else - pr_info("[VIB] strength-strong = %d\n", pdata->strength_strong); + /* array elements of frequency are assigned for each intensity level + starting from level 1 and increasing */ + pdata->count_frequency = of_property_count_u32_elems(client->dev.of_node, + "ztm620_motor,frequency"); + pr_info("[VIB] frequency count = %d", pdata->count_frequency); + if (pdata->count_frequency > 0) { + pdata->frequency = devm_kzalloc(&client->dev, + sizeof(u32) * pdata->count_frequency, GFP_KERNEL); + err = of_property_read_u32_array(client->dev.of_node, + "ztm620_motor,frequency", + (u32 *)pdata->frequency, pdata->count_frequency); + if (err < 0) { + dev_err(&client->dev, "[VIB] %s: frequency read fail(%d)\n", + __func__, err); + return -ENODEV; + } - 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; - pr_warn("[VIB] %s: strength-weak read fail(%d) :%d\n", - __func__, err, pdata->strength_weak); - } else - pr_info("[VIB] strength-weak = %d\n", pdata->strength_weak); + for (i = 0; i < pdata->count_frequency; i++) { + pr_info("[VIB] frequency[%d] = %d\n", i, pdata->frequency[i]); + } + } err = of_property_read_u32(client->dev.of_node, "ztm620_motor,overdrive-num", &pdata->overdrive_num); diff --git a/include/linux/ztm620_motor.h b/include/linux/ztm620_motor.h index a8e0c458bf84..3e2e0075a339 100644 --- a/include/linux/ztm620_motor.h +++ b/include/linux/ztm620_motor.h @@ -88,7 +88,7 @@ #define OVER_DRV_SHIFT_EN 7 #define OVER_DRV_SHIFT_CNT 0 -#define MAX_LEVEL 0xffff +#define MAX_INTENSITY_VALUE 10000 #define DEFAULT_MOTOR_FREQ 205 #define DEFAULT_MOTOR_STRENGTH 0x56 #define DEFAULT_BRAKE_DELAY 0 @@ -128,10 +128,10 @@ struct ztm620_motor_platform_data { const char *regulator_name; int adc_sampling_time; int soft_en_delay; - int freq_strong; /* in 0.1 hz*/ - int freq_weak; /* in 0.1 hz*/ - int strength_strong; - int strength_weak; + int *frequency; /* in 0.1 hz*/ + int count_frequency; + int *strength; + int count_strength; int overdrive_num; int motor_start_data; int motor_stop_data; @@ -150,10 +150,24 @@ struct ztm620_motor_data { struct work_struct trigger_init; struct timespec last_motor_off; - /* using FF_input_device */ - __u16 level; - __u16 frequency; /* in 0.1 hz*/ + /* using ff_runble effect */ + /* struct ff_rumble_effect { + __u16 strong_magnitude; // strong_magnitude[15:15] = 0 (Reserved) + // strong_magnitude[14:14] + // = Overdrive : 0 (Off) or 1 (On) + // strong_magnitude[13:0] + // = Intensity Value : 0 (Stop) + // or 1 ~ 10000 (Intensity) + __u16 weak_magnitude; // weak_magnitude[15:13] + // = Intensity Level : 1 ~ 5 + // weak_magnitude[12:0] + // = Frequency in 0.1Hz : 0 ~ 8191 (0 ~ 819.1 Hz) + }; */ __u16 overdrive; + __u16 intensity_value; + __u16 intensity_level; + __u16 frequency; + bool running; struct regulator *regulator; int gpio_en; |