Motor: add handling freq, overdrive param on ff effect 95/233195/1
authorjeongsup.jeong <jeongsup.jeong@samsung.com>
Mon, 22 Jul 2019 09:39:34 +0000 (18:39 +0900)
committerChanwoo Choi <cw00.choi@samsung.com>
Thu, 7 May 2020 06:18:16 +0000 (15:18 +0900)
In order to handle the motor behavior in details,
add new 'frequency' and 'overdrive' parameter for ff (force feedback) effect.

Use the existing 'struct ff_runbm_effect' without any added variable
to pass the user data to input device driver of kernel.

Change-Id: I09a920efe80babaf9e758918ab870dab62c7611b
Signed-off-by: jeongsup.jeong <jeongsup.jeong@samsung.com>
[cw00.choi: Add commit-msg as public style and fix the merge conflict]
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
drivers/motor/ztm620_motor.c
include/linux/ztm620_motor.h

index 0003ec0e98da0d436ea8a332565b50e22ec7bc75..f3f2269f4a5074101ee3a02114cd229a06191656 100644 (file)
@@ -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;
        }
 
@@ -208,16 +232,18 @@ static int ztm620_motor_run(void) {
                }
 
                ret = ztm620_motor_reg_write(pMotorData,
-                                       MOTOR_REG_MODE_00, pMotorPdata->motor_start_data);
+                       MOTOR_REG_MODE_00, pMotorPdata->motor_start_data);
                if (ret < 0) {
-                       pr_err("[VIB] %s MODE_00 write fail %d\n",
-                                                       __func__, ret);
+                       pr_err("[VIB] %s MODE_00 write fail (%d)\n", __func__, ret);
                        goto out;
                }
                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 +295,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 +349,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;
@@ -580,13 +610,11 @@ static int of_ztm620_motor_dt(struct i2c_client* client, struct ztm620_motor_pla
                pdata->motor_type = ACTUATOR_LRA;
                pdata->motor_start_data = MODE_00_I2C_LRA;
                pdata->motor_stop_data = MODE_00_STOP_LRA;
-       }
-       else if (!strcmp(motor_type, "ERM")) {
+       } else if (!strcmp(motor_type, "ERM")) {
                pdata->motor_type = ACTUATOR_ERM;
                pdata->motor_start_data = MODE_00_I2C_ERM;
                pdata->motor_stop_data = MODE_00_STOP_ERM;
-       }
-       else {
+       } else {
                dev_err(&client->dev, "[VIB] %s Wrong motor type: %s\n",
                                __func__, motor_type);
                return -ENODEV;
@@ -621,8 +649,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,
@@ -657,62 +684,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;
index 0111b06e0ed5d619dc51f11bf9669d6081d4cb5e..a8e0c458bf84dda8bcfc668f7953e0ed435a3318 100644 (file)
 #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
@@ -123,10 +128,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;
        int motor_start_data;
        int motor_stop_data;
 };
@@ -146,6 +152,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;