summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjeongsup.jeong <jeongsup.jeong@samsung.com>2019-12-27 15:09:50 +0900
committerSeung-Woo Kim <sw0312.kim@samsung.com>2020-05-11 00:41:22 +0000
commit3111ced5747423b05e4a2bdfecba8b519bf9f23a (patch)
treeccf2c0bdfb15e4f9c2c0ad136b7026bff495c690
parent58c9cdc9071f28c64e5d2f5122dd0581a2fe052a (diff)
downloadlinux-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.c181
-rw-r--r--include/linux/ztm620_motor.h30
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;