Motor: change motor control parameters for new haptic concept 96/233196/1
authorjeongsup.jeong <jeongsup.jeong@samsung.com>
Fri, 27 Dec 2019 06:09:50 +0000 (15:09 +0900)
committerChanwoo Choi <cw00.choi@samsung.com>
Thu, 7 May 2020 06:18:20 +0000 (15:18 +0900)
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: I9ec052003b099f4dddeeecaea3ee9517673158a2
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>
drivers/motor/ztm620_motor.c
include/linux/ztm620_motor.h

index f3f2269f4a5074101ee3a02114cd229a06191656..7f069b479e3c49bc63e4b8924eb8c5fe093803d6 100644 (file)
@@ -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);
index a8e0c458bf84dda8bcfc668f7953e0ed435a3318..3e2e0075a339b2db50f13b10d906d5e423f6124f 100644 (file)
@@ -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;