diff --git a/Documentation/devicetree/bindings/haptic/ti-drv2605.txt b/Documentation/devicetree/bindings/haptic/ti-drv2605.txt index 358bf403de2905ac153334bac8b46c44529b1624..ad592b9a06944211d3703c79f3412946d8bc7274 100644 --- a/Documentation/devicetree/bindings/haptic/ti-drv2605.txt +++ b/Documentation/devicetree/bindings/haptic/ti-drv2605.txt @@ -22,10 +22,13 @@ Required properties: rated voltage for the motor - overdrive_voltage: overdrive voltage for the motor +Optional: - disable_calibration: disable boot-up calibration.The calibration data should be store in OTP memory on factory. If OTP memory is not programmed the driver will ignore this option. + - calibration-data: + Default calibration data. Example: i2c@1a200000 { diff --git a/drivers/misc/drv2605.c b/drivers/misc/drv2605.c index 98332263fa5f85d71e0a0b85109541d9c8d8b45e..1d620c6cecbeb74936b01f5ed508158c667e82d0 100755 --- a/drivers/misc/drv2605.c +++ b/drivers/misc/drv2605.c @@ -178,6 +178,8 @@ static struct drv260x { unsigned char rated_voltage; unsigned char overdrive_voltage; struct regulator *vibrator_vdd; + int use_default_calibration; + unsigned char default_calibration[5]; } *drv260x; static struct vibrator { @@ -299,6 +301,8 @@ static struct drv260x_platform_data *drv260x_of_init(struct i2c_client *client) { struct drv260x_platform_data *pdata; struct device_node *np = client->dev.of_node; + const u32 *regs_arr; + int regs_len , i; pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); @@ -320,6 +324,21 @@ static struct drv260x_platform_data *drv260x_of_init(struct i2c_client *client) pdata->vibrator_vdd = devm_regulator_get(&client->dev, "vibrator_vdd"); pdata->static_vdd = devm_regulator_get(&client->dev, "static-vdd"); + regs_arr = of_get_property(np, "calibration-data", + ®s_len); + regs_len /= sizeof(u32); + + if (!regs_arr || (regs_len != 5)) { + pr_warn("drv2605: No default calibration data\n"); + regs_len = 0; + } else { + pdata->calibration_data = devm_kzalloc(&client->dev, + sizeof(unsigned char) * regs_len, + GFP_KERNEL); + for (i = 0; i < regs_len; i++) + pdata->calibration_data[i] = be32_to_cpu(regs_arr[i]); + } + return pdata; } #else @@ -743,6 +762,12 @@ static int drv260x_probe(struct i2c_client *client, if ((pdata->effects_library >= LIBRARY_A) && (pdata->effects_library <= LIBRARY_F)) g_effect_bank = pdata->effects_library; + if (pdata->calibration_data) { + drv260x->use_default_calibration = 1; + memcpy(&drv260x->default_calibration, + pdata->calibration_data, + sizeof(drv260x->default_calibration)); + } INIT_WORK(&vibdata.work_probe, probe_work); schedule_work(&vibdata.work_probe); @@ -851,6 +876,14 @@ static void probe_work(struct work_struct *work) /* Read calibration results */ drv260x_read_reg_val(reinit_sequence, sizeof(reinit_sequence)); + if (drv260x->use_default_calibration) { + reinit_sequence[3] = drv260x->default_calibration[0]; + reinit_sequence[5] = drv260x->default_calibration[1]; + reinit_sequence[7] = drv260x->default_calibration[2]; + reinit_sequence[9] = drv260x->default_calibration[3]; + reinit_sequence[11] = drv260x->default_calibration[4]; + } + /* Read device ID */ device_id = (status & DEV_ID_MASK); switch (device_id) { diff --git a/include/linux/drv2605.h b/include/linux/drv2605.h index 7ccf76b4c0cf2d993f5a9eadfb3b2d1b148f6f9d..490f5da690fecb2c72b962a1940ad5d6214e3a1d 100755 --- a/include/linux/drv2605.h +++ b/include/linux/drv2605.h @@ -344,5 +344,6 @@ struct drv260x_platform_data { int disable_calibration; struct regulator *vibrator_vdd; struct regulator *static_vdd; + unsigned char *calibration_data; }; #endif /* __KERNEL__ */