From 9c27847dda9cfae7c273cde62becf364f9fa9ea3 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 27 May 2015 11:09:38 +0930 Subject: kernel/params: constify struct kernel_param_ops uses Most code already uses consts for the struct kernel_param_ops, sweep the kernel for the last offending stragglers. Other than include/linux/moduleparam.h and kernel/params.c all other changes were generated with the following Coccinelle SmPL patch. Merge conflicts between trees can be handled with Coccinelle. In the future git could get Coccinelle merge support to deal with patch --> fail --> grammar --> Coccinelle --> new patch conflicts automatically for us on patches where the grammar is available and the patch is of high confidence. Consider this a feature request. Test compiled on x86_64 against: * allnoconfig * allmodconfig * allyesconfig @ const_found @ identifier ops; @@ const struct kernel_param_ops ops = { }; @ const_not_found depends on !const_found @ identifier ops; @@ -struct kernel_param_ops ops = { +const struct kernel_param_ops ops = { }; Generated-by: Coccinelle SmPL Cc: Rusty Russell Cc: Junio C Hamano Cc: Andrew Morton Cc: Kees Cook Cc: Tejun Heo Cc: Ingo Molnar Cc: cocci@systeme.lip6.fr Cc: linux-kernel@vger.kernel.org Signed-off-by: Luis R. Rodriguez Signed-off-by: Rusty Russell --- drivers/input/mouse/psmouse-base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input/mouse') diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 5bb1658f60c7..f8286b625ec4 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -47,7 +47,7 @@ MODULE_LICENSE("GPL"); static unsigned int psmouse_max_proto = PSMOUSE_AUTO; static int psmouse_set_maxproto(const char *val, const struct kernel_param *); static int psmouse_get_maxproto(char *buffer, const struct kernel_param *kp); -static struct kernel_param_ops param_ops_proto_abbrev = { +static const struct kernel_param_ops param_ops_proto_abbrev = { .set = psmouse_set_maxproto, .get = psmouse_get_maxproto, }; -- cgit v1.2.3 From 800e3b9a68011c4124f380d50e2117523c41a843 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 17 Jul 2015 16:44:05 -0700 Subject: Input: drop owner assignment from i2c_driver i2c_driver does not need to set an owner because i2c_register_driver() will set it. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/adp5589-keys.c | 1 - drivers/input/keyboard/cap11xx.c | 1 - drivers/input/keyboard/lm8333.c | 1 - drivers/input/keyboard/mcs_touchkey.c | 1 - drivers/input/keyboard/mpr121_touchkey.c | 1 - drivers/input/keyboard/qt1070.c | 1 - drivers/input/keyboard/qt2160.c | 1 - drivers/input/keyboard/tca8418_keypad.c | 1 - drivers/input/misc/adxl34x-i2c.c | 1 - drivers/input/misc/bma150.c | 1 - drivers/input/misc/cma3000_d0x_i2c.c | 1 - drivers/input/misc/drv260x.c | 1 - drivers/input/misc/drv2665.c | 1 - drivers/input/misc/drv2667.c | 1 - drivers/input/misc/gp2ap002a00f.c | 1 - drivers/input/misc/kxtj9.c | 1 - drivers/input/misc/mpu3050.c | 1 - drivers/input/misc/pcf8574_keypad.c | 1 - drivers/input/mouse/cyapa.c | 1 - drivers/input/mouse/elan_i2c_core.c | 1 - drivers/input/mouse/synaptics_i2c.c | 1 - drivers/input/touchscreen/ad7879-i2c.c | 1 - drivers/input/touchscreen/ar1021_i2c.c | 1 - drivers/input/touchscreen/atmel_mxt_ts.c | 1 - drivers/input/touchscreen/auo-pixcir-ts.c | 1 - drivers/input/touchscreen/bu21013_ts.c | 1 - drivers/input/touchscreen/chipone_icn8318.c | 1 - drivers/input/touchscreen/cy8ctmg110_ts.c | 1 - drivers/input/touchscreen/cyttsp4_i2c.c | 1 - drivers/input/touchscreen/cyttsp_i2c.c | 1 - drivers/input/touchscreen/edt-ft5x06.c | 1 - drivers/input/touchscreen/egalax_ts.c | 1 - drivers/input/touchscreen/elants_i2c.c | 1 - drivers/input/touchscreen/goodix.c | 1 - drivers/input/touchscreen/ili210x.c | 1 - drivers/input/touchscreen/max11801_ts.c | 1 - drivers/input/touchscreen/mms114.c | 1 - drivers/input/touchscreen/pixcir_i2c_ts.c | 1 - drivers/input/touchscreen/st1232.c | 1 - drivers/input/touchscreen/tsc2007.c | 1 - drivers/input/touchscreen/wacom_i2c.c | 1 - drivers/input/touchscreen/zforce_ts.c | 1 - 42 files changed, 42 deletions(-) (limited to 'drivers/input/mouse') diff --git a/drivers/input/keyboard/adp5589-keys.c b/drivers/input/keyboard/adp5589-keys.c index 6ed83cf8b74e..4d446d5085aa 100644 --- a/drivers/input/keyboard/adp5589-keys.c +++ b/drivers/input/keyboard/adp5589-keys.c @@ -1097,7 +1097,6 @@ MODULE_DEVICE_TABLE(i2c, adp5589_id); static struct i2c_driver adp5589_driver = { .driver = { .name = KBUILD_MODNAME, - .owner = THIS_MODULE, .pm = &adp5589_dev_pm_ops, }, .probe = adp5589_probe, diff --git a/drivers/input/keyboard/cap11xx.c b/drivers/input/keyboard/cap11xx.c index f07461a64d85..b58fd9d72d92 100644 --- a/drivers/input/keyboard/cap11xx.c +++ b/drivers/input/keyboard/cap11xx.c @@ -361,7 +361,6 @@ MODULE_DEVICE_TABLE(i2c, cap11xx_i2c_ids); static struct i2c_driver cap11xx_i2c_driver = { .driver = { .name = "cap11xx", - .owner = THIS_MODULE, .of_match_table = cap11xx_dt_ids, }, .id_table = cap11xx_i2c_ids, diff --git a/drivers/input/keyboard/lm8333.c b/drivers/input/keyboard/lm8333.c index 0ad422b8a260..c717e8f3c964 100644 --- a/drivers/input/keyboard/lm8333.c +++ b/drivers/input/keyboard/lm8333.c @@ -223,7 +223,6 @@ MODULE_DEVICE_TABLE(i2c, lm8333_id); static struct i2c_driver lm8333_driver = { .driver = { .name = "lm8333", - .owner = THIS_MODULE, }, .probe = lm8333_probe, .remove = lm8333_remove, diff --git a/drivers/input/keyboard/mcs_touchkey.c b/drivers/input/keyboard/mcs_touchkey.c index 375b05ca8e2a..31090d71a685 100644 --- a/drivers/input/keyboard/mcs_touchkey.c +++ b/drivers/input/keyboard/mcs_touchkey.c @@ -265,7 +265,6 @@ MODULE_DEVICE_TABLE(i2c, mcs_touchkey_id); static struct i2c_driver mcs_touchkey_driver = { .driver = { .name = "mcs_touchkey", - .owner = THIS_MODULE, .pm = &mcs_touchkey_pm_ops, }, .probe = mcs_touchkey_probe, diff --git a/drivers/input/keyboard/mpr121_touchkey.c b/drivers/input/keyboard/mpr121_touchkey.c index 3aa2ec45bcab..0fd612dd76ed 100644 --- a/drivers/input/keyboard/mpr121_touchkey.c +++ b/drivers/input/keyboard/mpr121_touchkey.c @@ -305,7 +305,6 @@ MODULE_DEVICE_TABLE(i2c, mpr121_id); static struct i2c_driver mpr_touchkey_driver = { .driver = { .name = "mpr121", - .owner = THIS_MODULE, .pm = &mpr121_touchkey_pm_ops, }, .id_table = mpr121_id, diff --git a/drivers/input/keyboard/qt1070.c b/drivers/input/keyboard/qt1070.c index 52cd6e88acd7..5a5778729e37 100644 --- a/drivers/input/keyboard/qt1070.c +++ b/drivers/input/keyboard/qt1070.c @@ -277,7 +277,6 @@ MODULE_DEVICE_TABLE(i2c, qt1070_id); static struct i2c_driver qt1070_driver = { .driver = { .name = "qt1070", - .owner = THIS_MODULE, .pm = &qt1070_pm_ops, }, .id_table = qt1070_id, diff --git a/drivers/input/keyboard/qt2160.c b/drivers/input/keyboard/qt2160.c index 819b22897c13..43b86482dda0 100644 --- a/drivers/input/keyboard/qt2160.c +++ b/drivers/input/keyboard/qt2160.c @@ -497,7 +497,6 @@ MODULE_DEVICE_TABLE(i2c, qt2160_idtable); static struct i2c_driver qt2160_driver = { .driver = { .name = "qt2160", - .owner = THIS_MODULE, }, .id_table = qt2160_idtable, diff --git a/drivers/input/keyboard/tca8418_keypad.c b/drivers/input/keyboard/tca8418_keypad.c index 4e491c1762cf..9002298698fc 100644 --- a/drivers/input/keyboard/tca8418_keypad.c +++ b/drivers/input/keyboard/tca8418_keypad.c @@ -404,7 +404,6 @@ MODULE_ALIAS("i2c:tca8418"); static struct i2c_driver tca8418_keypad_driver = { .driver = { .name = TCA8418_NAME, - .owner = THIS_MODULE, .of_match_table = of_match_ptr(tca8418_dt_ids), }, .probe = tca8418_keypad_probe, diff --git a/drivers/input/misc/adxl34x-i2c.c b/drivers/input/misc/adxl34x-i2c.c index bdb5d03b296e..a8b0a2eec344 100644 --- a/drivers/input/misc/adxl34x-i2c.c +++ b/drivers/input/misc/adxl34x-i2c.c @@ -158,7 +158,6 @@ MODULE_DEVICE_TABLE(of, adxl34x_of_id); static struct i2c_driver adxl34x_driver = { .driver = { .name = "adxl34x", - .owner = THIS_MODULE, .pm = &adxl34x_i2c_pm, .of_match_table = of_match_ptr(adxl34x_of_id), }, diff --git a/drivers/input/misc/bma150.c b/drivers/input/misc/bma150.c index c2780493b0ed..1d0e61d7c131 100644 --- a/drivers/input/misc/bma150.c +++ b/drivers/input/misc/bma150.c @@ -653,7 +653,6 @@ MODULE_DEVICE_TABLE(i2c, bma150_id); static struct i2c_driver bma150_driver = { .driver = { - .owner = THIS_MODULE, .name = BMA150_DRIVER, .pm = &bma150_pm, }, diff --git a/drivers/input/misc/cma3000_d0x_i2c.c b/drivers/input/misc/cma3000_d0x_i2c.c index 4fdef98ceb56..c7021916b64b 100644 --- a/drivers/input/misc/cma3000_d0x_i2c.c +++ b/drivers/input/misc/cma3000_d0x_i2c.c @@ -118,7 +118,6 @@ static struct i2c_driver cma3000_i2c_driver = { .id_table = cma3000_i2c_id, .driver = { .name = "cma3000_i2c_accl", - .owner = THIS_MODULE, #ifdef CONFIG_PM .pm = &cma3000_i2c_pm_ops, #endif diff --git a/drivers/input/misc/drv260x.c b/drivers/input/misc/drv260x.c index 0e3af55d9e25..e65496e6463d 100644 --- a/drivers/input/misc/drv260x.c +++ b/drivers/input/misc/drv260x.c @@ -720,7 +720,6 @@ static struct i2c_driver drv260x_driver = { .probe = drv260x_probe, .driver = { .name = "drv260x-haptics", - .owner = THIS_MODULE, .of_match_table = of_match_ptr(drv260x_of_match), .pm = &drv260x_pm_ops, }, diff --git a/drivers/input/misc/drv2665.c b/drivers/input/misc/drv2665.c index e9501fdca5ef..327a63c2f07d 100644 --- a/drivers/input/misc/drv2665.c +++ b/drivers/input/misc/drv2665.c @@ -309,7 +309,6 @@ static struct i2c_driver drv2665_driver = { .probe = drv2665_probe, .driver = { .name = "drv2665-haptics", - .owner = THIS_MODULE, .of_match_table = of_match_ptr(drv2665_of_match), .pm = &drv2665_pm_ops, }, diff --git a/drivers/input/misc/drv2667.c b/drivers/input/misc/drv2667.c index a231342207f9..46a4be4e9dc3 100644 --- a/drivers/input/misc/drv2667.c +++ b/drivers/input/misc/drv2667.c @@ -484,7 +484,6 @@ static struct i2c_driver drv2667_driver = { .probe = drv2667_probe, .driver = { .name = "drv2667-haptics", - .owner = THIS_MODULE, .of_match_table = of_match_ptr(drv2667_of_match), .pm = &drv2667_pm_ops, }, diff --git a/drivers/input/misc/gp2ap002a00f.c b/drivers/input/misc/gp2ap002a00f.c index 0ac176d66a6f..ba301af91b95 100644 --- a/drivers/input/misc/gp2ap002a00f.c +++ b/drivers/input/misc/gp2ap002a00f.c @@ -271,7 +271,6 @@ static const struct i2c_device_id gp2a_i2c_id[] = { static struct i2c_driver gp2a_i2c_driver = { .driver = { .name = GP2A_I2C_NAME, - .owner = THIS_MODULE, .pm = &gp2a_pm, }, .probe = gp2a_probe, diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c index 6e29349da537..e058d711256a 100644 --- a/drivers/input/misc/kxtj9.c +++ b/drivers/input/misc/kxtj9.c @@ -658,7 +658,6 @@ MODULE_DEVICE_TABLE(i2c, kxtj9_id); static struct i2c_driver kxtj9_driver = { .driver = { .name = NAME, - .owner = THIS_MODULE, .pm = &kxtj9_pm_ops, }, .probe = kxtj9_probe, diff --git a/drivers/input/misc/mpu3050.c b/drivers/input/misc/mpu3050.c index 5e5051351c3a..f088db31cfc7 100644 --- a/drivers/input/misc/mpu3050.c +++ b/drivers/input/misc/mpu3050.c @@ -466,7 +466,6 @@ MODULE_DEVICE_TABLE(of, mpu3050_of_match); static struct i2c_driver mpu3050_i2c_driver = { .driver = { .name = "mpu3050", - .owner = THIS_MODULE, .pm = &mpu3050_pm, .of_match_table = mpu3050_of_match, }, diff --git a/drivers/input/misc/pcf8574_keypad.c b/drivers/input/misc/pcf8574_keypad.c index 97f711a7bd20..4abdf1efb3e0 100644 --- a/drivers/input/misc/pcf8574_keypad.c +++ b/drivers/input/misc/pcf8574_keypad.c @@ -208,7 +208,6 @@ MODULE_DEVICE_TABLE(i2c, pcf8574_kp_id); static struct i2c_driver pcf8574_kp_driver = { .driver = { .name = DRV_NAME, - .owner = THIS_MODULE, #ifdef CONFIG_PM .pm = &pcf8574_kp_pm_ops, #endif diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index efe148474e7f..dfbfd494bb1f 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -1382,7 +1382,6 @@ MODULE_DEVICE_TABLE(acpi, cyapa_acpi_id); static struct i2c_driver cyapa_driver = { .driver = { .name = "cyapa", - .owner = THIS_MODULE, .pm = &cyapa_pm_ops, .acpi_match_table = ACPI_PTR(cyapa_acpi_id), }, diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index 62641f2adaf7..e7ef4ab1b37d 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -1183,7 +1183,6 @@ MODULE_DEVICE_TABLE(of, elan_of_match); static struct i2c_driver elan_driver = { .driver = { .name = DRIVER_NAME, - .owner = THIS_MODULE, .pm = &elan_pm_ops, .acpi_match_table = ACPI_PTR(elan_acpi_id), .of_match_table = of_match_ptr(elan_of_match), diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c index ffceedcaf3c8..aa7c5da60800 100644 --- a/drivers/input/mouse/synaptics_i2c.c +++ b/drivers/input/mouse/synaptics_i2c.c @@ -655,7 +655,6 @@ MODULE_DEVICE_TABLE(i2c, synaptics_i2c_id_table); static struct i2c_driver synaptics_i2c_driver = { .driver = { .name = DRIVER_NAME, - .owner = THIS_MODULE, .pm = &synaptics_i2c_pm, }, diff --git a/drivers/input/touchscreen/ad7879-i2c.c b/drivers/input/touchscreen/ad7879-i2c.c index dcf390771549..d66962c5b1c2 100644 --- a/drivers/input/touchscreen/ad7879-i2c.c +++ b/drivers/input/touchscreen/ad7879-i2c.c @@ -94,7 +94,6 @@ MODULE_DEVICE_TABLE(i2c, ad7879_id); static struct i2c_driver ad7879_i2c_driver = { .driver = { .name = "ad7879", - .owner = THIS_MODULE, .pm = &ad7879_pm_ops, }, .probe = ad7879_i2c_probe, diff --git a/drivers/input/touchscreen/ar1021_i2c.c b/drivers/input/touchscreen/ar1021_i2c.c index f0b954d46a25..71b5a634cf6d 100644 --- a/drivers/input/touchscreen/ar1021_i2c.c +++ b/drivers/input/touchscreen/ar1021_i2c.c @@ -166,7 +166,6 @@ MODULE_DEVICE_TABLE(of, ar1021_i2c_of_match); static struct i2c_driver ar1021_i2c_driver = { .driver = { .name = "ar1021_i2c", - .owner = THIS_MODULE, .pm = &ar1021_i2c_pm, .of_match_table = ar1021_i2c_of_match, }, diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index dfc7309e3d38..8efe7a002f1e 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -2666,7 +2666,6 @@ MODULE_DEVICE_TABLE(i2c, mxt_id); static struct i2c_driver mxt_driver = { .driver = { .name = "atmel_mxt_ts", - .owner = THIS_MODULE, .of_match_table = of_match_ptr(mxt_of_match), .acpi_match_table = ACPI_PTR(mxt_acpi_id), .pm = &mxt_pm_ops, diff --git a/drivers/input/touchscreen/auo-pixcir-ts.c b/drivers/input/touchscreen/auo-pixcir-ts.c index 40e02dd5b2f9..38c06f754acd 100644 --- a/drivers/input/touchscreen/auo-pixcir-ts.c +++ b/drivers/input/touchscreen/auo-pixcir-ts.c @@ -686,7 +686,6 @@ MODULE_DEVICE_TABLE(of, auo_pixcir_ts_dt_idtable); static struct i2c_driver auo_pixcir_driver = { .driver = { - .owner = THIS_MODULE, .name = "auo_pixcir_ts", .pm = &auo_pixcir_pm_ops, .of_match_table = of_match_ptr(auo_pixcir_ts_dt_idtable), diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c index b9b5ddad6658..931417eb4f5a 100644 --- a/drivers/input/touchscreen/bu21013_ts.c +++ b/drivers/input/touchscreen/bu21013_ts.c @@ -716,7 +716,6 @@ MODULE_DEVICE_TABLE(i2c, bu21013_id); static struct i2c_driver bu21013_driver = { .driver = { .name = DRIVER_TP, - .owner = THIS_MODULE, #ifdef CONFIG_PM .pm = &bu21013_dev_pm_ops, #endif diff --git a/drivers/input/touchscreen/chipone_icn8318.c b/drivers/input/touchscreen/chipone_icn8318.c index 32e9db0e04bf..22a6fead8cfb 100644 --- a/drivers/input/touchscreen/chipone_icn8318.c +++ b/drivers/input/touchscreen/chipone_icn8318.c @@ -300,7 +300,6 @@ MODULE_DEVICE_TABLE(i2c, icn8318_i2c_id); static struct i2c_driver icn8318_driver = { .driver = { - .owner = THIS_MODULE, .name = "chipone_icn8318", .pm = &icn8318_pm_ops, .of_match_table = icn8318_of_match, diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c index f2119ee0e21b..cc1d1350074e 100644 --- a/drivers/input/touchscreen/cy8ctmg110_ts.c +++ b/drivers/input/touchscreen/cy8ctmg110_ts.c @@ -347,7 +347,6 @@ MODULE_DEVICE_TABLE(i2c, cy8ctmg110_idtable); static struct i2c_driver cy8ctmg110_driver = { .driver = { - .owner = THIS_MODULE, .name = CY8CTMG110_DRIVER_NAME, .pm = &cy8ctmg110_pm, }, diff --git a/drivers/input/touchscreen/cyttsp4_i2c.c b/drivers/input/touchscreen/cyttsp4_i2c.c index 8e2012c79058..9a323dd915de 100644 --- a/drivers/input/touchscreen/cyttsp4_i2c.c +++ b/drivers/input/touchscreen/cyttsp4_i2c.c @@ -74,7 +74,6 @@ MODULE_DEVICE_TABLE(i2c, cyttsp4_i2c_id); static struct i2c_driver cyttsp4_i2c_driver = { .driver = { .name = CYTTSP4_I2C_NAME, - .owner = THIS_MODULE, .pm = &cyttsp4_pm_ops, }, .probe = cyttsp4_i2c_probe, diff --git a/drivers/input/touchscreen/cyttsp_i2c.c b/drivers/input/touchscreen/cyttsp_i2c.c index 63104a86a9bd..519e2de2f8df 100644 --- a/drivers/input/touchscreen/cyttsp_i2c.c +++ b/drivers/input/touchscreen/cyttsp_i2c.c @@ -74,7 +74,6 @@ MODULE_DEVICE_TABLE(i2c, cyttsp_i2c_id); static struct i2c_driver cyttsp_i2c_driver = { .driver = { .name = CY_I2C_NAME, - .owner = THIS_MODULE, .pm = &cyttsp_pm_ops, }, .probe = cyttsp_i2c_probe, diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index 8f8f3199be39..48de1e8b3c93 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -1134,7 +1134,6 @@ MODULE_DEVICE_TABLE(of, edt_ft5x06_of_match); static struct i2c_driver edt_ft5x06_ts_driver = { .driver = { - .owner = THIS_MODULE, .name = "edt_ft5x06", .of_match_table = of_match_ptr(edt_ft5x06_of_match), .pm = &edt_ft5x06_ts_pm_ops, diff --git a/drivers/input/touchscreen/egalax_ts.c b/drivers/input/touchscreen/egalax_ts.c index 4c56299284ef..7bce2d90ec74 100644 --- a/drivers/input/touchscreen/egalax_ts.c +++ b/drivers/input/touchscreen/egalax_ts.c @@ -268,7 +268,6 @@ static const struct of_device_id egalax_ts_dt_ids[] = { static struct i2c_driver egalax_ts_driver = { .driver = { .name = "egalax_ts", - .owner = THIS_MODULE, .pm = &egalax_ts_pm_ops, .of_match_table = egalax_ts_dt_ids, }, diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c index 0efd766a545b..746137694137 100644 --- a/drivers/input/touchscreen/elants_i2c.c +++ b/drivers/input/touchscreen/elants_i2c.c @@ -1261,7 +1261,6 @@ static struct i2c_driver elants_i2c_driver = { .id_table = elants_i2c_id, .driver = { .name = DEVICE_NAME, - .owner = THIS_MODULE, .pm = &elants_i2c_pm_ops, .acpi_match_table = ACPI_PTR(elants_acpi_id), .of_match_table = of_match_ptr(elants_of_match), diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c index b4d12e29abff..ccd9dca61195 100644 --- a/drivers/input/touchscreen/goodix.c +++ b/drivers/input/touchscreen/goodix.c @@ -412,7 +412,6 @@ static struct i2c_driver goodix_ts_driver = { .id_table = goodix_ts_id, .driver = { .name = "Goodix-TS", - .owner = THIS_MODULE, .acpi_match_table = ACPI_PTR(goodix_acpi_match), .of_match_table = of_match_ptr(goodix_of_match), }, diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c index da6dc819c846..cf0dc2f0b1be 100644 --- a/drivers/input/touchscreen/ili210x.c +++ b/drivers/input/touchscreen/ili210x.c @@ -343,7 +343,6 @@ MODULE_DEVICE_TABLE(i2c, ili210x_i2c_id); static struct i2c_driver ili210x_ts_driver = { .driver = { .name = "ili210x_i2c", - .owner = THIS_MODULE, .pm = &ili210x_i2c_pm, }, .id_table = ili210x_i2c_id, diff --git a/drivers/input/touchscreen/max11801_ts.c b/drivers/input/touchscreen/max11801_ts.c index a68ec142ee9a..82079cde849c 100644 --- a/drivers/input/touchscreen/max11801_ts.c +++ b/drivers/input/touchscreen/max11801_ts.c @@ -229,7 +229,6 @@ MODULE_DEVICE_TABLE(i2c, max11801_ts_id); static struct i2c_driver max11801_ts_driver = { .driver = { .name = "max11801_ts", - .owner = THIS_MODULE, }, .id_table = max11801_ts_id, .probe = max11801_ts_probe, diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c index 67c0d31613d8..6b69f461733c 100644 --- a/drivers/input/touchscreen/mms114.c +++ b/drivers/input/touchscreen/mms114.c @@ -577,7 +577,6 @@ static const struct of_device_id mms114_dt_match[] = { static struct i2c_driver mms114_driver = { .driver = { .name = "mms114", - .owner = THIS_MODULE, .pm = &mms114_pm_ops, .of_match_table = of_match_ptr(mms114_dt_match), }, diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c index 68d0d549797c..4c71d631cbae 100644 --- a/drivers/input/touchscreen/pixcir_i2c_ts.c +++ b/drivers/input/touchscreen/pixcir_i2c_ts.c @@ -604,7 +604,6 @@ MODULE_DEVICE_TABLE(of, pixcir_of_match); static struct i2c_driver pixcir_i2c_ts_driver = { .driver = { - .owner = THIS_MODULE, .name = "pixcir_ts", .pm = &pixcir_dev_pm_ops, .of_match_table = of_match_ptr(pixcir_of_match), diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c index 697e26e52d54..e943678ce54c 100644 --- a/drivers/input/touchscreen/st1232.c +++ b/drivers/input/touchscreen/st1232.c @@ -296,7 +296,6 @@ static struct i2c_driver st1232_ts_driver = { .id_table = st1232_ts_id, .driver = { .name = ST1232_TS_NAME, - .owner = THIS_MODULE, .of_match_table = of_match_ptr(st1232_ts_dt_ids), .pm = &st1232_ts_pm_ops, }, diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c index ccc8aa615709..5d0cd51c6f41 100644 --- a/drivers/input/touchscreen/tsc2007.c +++ b/drivers/input/touchscreen/tsc2007.c @@ -482,7 +482,6 @@ MODULE_DEVICE_TABLE(of, tsc2007_of_match); static struct i2c_driver tsc2007_driver = { .driver = { - .owner = THIS_MODULE, .name = "tsc2007", .of_match_table = of_match_ptr(tsc2007_of_match), }, diff --git a/drivers/input/touchscreen/wacom_i2c.c b/drivers/input/touchscreen/wacom_i2c.c index 32f8ac003936..8d7a2852caef 100644 --- a/drivers/input/touchscreen/wacom_i2c.c +++ b/drivers/input/touchscreen/wacom_i2c.c @@ -271,7 +271,6 @@ MODULE_DEVICE_TABLE(i2c, wacom_i2c_id); static struct i2c_driver wacom_i2c_driver = { .driver = { .name = "wacom_i2c", - .owner = THIS_MODULE, .pm = &wacom_i2c_pm, }, diff --git a/drivers/input/touchscreen/zforce_ts.c b/drivers/input/touchscreen/zforce_ts.c index c4cffcfb03d3..d00e1e33b657 100644 --- a/drivers/input/touchscreen/zforce_ts.c +++ b/drivers/input/touchscreen/zforce_ts.c @@ -919,7 +919,6 @@ MODULE_DEVICE_TABLE(of, zforce_dt_idtable); static struct i2c_driver zforce_driver = { .driver = { - .owner = THIS_MODULE, .name = "zforce-ts", .pm = &zforce_pm_ops, .of_match_table = of_match_ptr(zforce_dt_idtable), -- cgit v1.2.3 From 6ccfe64c770139675a080ee5029ded7d89d9ea0d Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Mon, 20 Jul 2015 09:56:18 -0700 Subject: Input: elan_i2c - enable ELAN0600 acpi panels ELAN0600 seems to work just fine in mouse emulation mode through i2c-hid, but to have full raw touch support we need to register it in elan_i2c.ko Reported-and-tested-by: Alessio Treglia Signed-off-by: Benjamin Tissoires Acked-by: Jiri Kosina Signed-off-by: Dmitry Torokhov --- drivers/hid/hid-core.c | 1 + drivers/input/mouse/elan_i2c_core.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers/input/mouse') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 56ce8c2b5530..f3133e49ba0c 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -2238,6 +2238,7 @@ static const struct hid_device_id hid_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) }, { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, 0x0004) }, { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, 0x000a) }, + { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, 0x0400) }, { HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) }, { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) }, { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) }, diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index e7ef4ab1b37d..4a5d6ee5caaf 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -1167,6 +1167,7 @@ MODULE_DEVICE_TABLE(i2c, elan_id); #ifdef CONFIG_ACPI static const struct acpi_device_id elan_acpi_id[] = { { "ELAN0000", 0 }, + { "ELAN0600", 0 }, { } }; MODULE_DEVICE_TABLE(acpi, elan_acpi_id); -- cgit v1.2.3 From 94897619bf24aca6b37cfa847399a56cf40eab66 Mon Sep 17 00:00:00 2001 From: Dudley Du Date: Mon, 20 Jul 2015 16:49:06 -0700 Subject: Input: cyapa - rename 'gen5' to 'pip' for chared code Change 'gen5' to 'pip' for all macros, variables and functions that are shared between gen5 and gen6 modules to make naming more clear and readable. Also fix a few spelling errors. Signed-off-by: Dudley Du Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/cyapa.c | 34 +- drivers/input/mouse/cyapa.h | 136 ++++- drivers/input/mouse/cyapa_gen3.c | 4 +- drivers/input/mouse/cyapa_gen5.c | 1103 ++++++++++++++++++-------------------- 4 files changed, 673 insertions(+), 604 deletions(-) (limited to 'drivers/input/mouse') diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index dfbfd494bb1f..4c4429598adb 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -6,7 +6,7 @@ * Daniel Kurtz * Benson Leung * - * Copyright (C) 2011-2014 Cypress Semiconductor, Inc. + * Copyright (C) 2011-2015 Cypress Semiconductor, Inc. * Copyright (C) 2011-2012 Google, Inc. * * This file is subject to the terms and conditions of the GNU General Public @@ -39,11 +39,27 @@ const char product_id[] = "CYTRA"; static int cyapa_reinitialize(struct cyapa *cyapa); -static inline bool cyapa_is_bootloader_mode(struct cyapa *cyapa) +bool cyapa_is_pip_bl_mode(struct cyapa *cyapa) { if (cyapa->gen == CYAPA_GEN5 && cyapa->state == CYAPA_STATE_GEN5_BL) return true; + return false; +} + +bool cyapa_is_pip_app_mode(struct cyapa *cyapa) +{ + if (cyapa->gen == CYAPA_GEN5 && cyapa->state == CYAPA_STATE_GEN5_APP) + return true; + + return false; +} + +static bool cyapa_is_bootloader_mode(struct cyapa *cyapa) +{ + if (cyapa_is_pip_bl_mode(cyapa)) + return true; + if (cyapa->gen == CYAPA_GEN3 && cyapa->state >= CYAPA_STATE_BL_BUSY && cyapa->state <= CYAPA_STATE_BL_ACTIVE) @@ -54,7 +70,7 @@ static inline bool cyapa_is_bootloader_mode(struct cyapa *cyapa) static inline bool cyapa_is_operational_mode(struct cyapa *cyapa) { - if (cyapa->gen == CYAPA_GEN5 && cyapa->state == CYAPA_STATE_GEN5_APP) + if (cyapa_is_pip_app_mode(cyapa)) return true; if (cyapa->gen == CYAPA_GEN3 && cyapa->state == CYAPA_STATE_OP) @@ -306,7 +322,7 @@ static int cyapa_check_is_operational(struct cyapa *cyapa) /* * Returns 0 on device detected, negative errno on no device detected. - * And when the device is detected and opertaional, it will be reset to + * And when the device is detected and operational, it will be reset to * full power active mode automatically. */ static int cyapa_detect(struct cyapa *cyapa) @@ -629,15 +645,15 @@ static irqreturn_t cyapa_irq(int irq, void *dev_id) if (device_may_wakeup(dev)) pm_wakeup_event(dev, 0); - /* Interrupt event maybe cuased by host command to trackpad device. */ + /* Interrupt event can be caused by host command to trackpad device. */ if (cyapa->ops->irq_cmd_handler(cyapa)) { /* * Interrupt event maybe from trackpad device input reporting. */ if (!cyapa->input) { /* - * Still in probling or in firware image - * udpating or reading. + * Still in probing or in firmware image + * updating or reading. */ cyapa->ops->sort_empty_output_data(cyapa, NULL, NULL, NULL); @@ -1051,12 +1067,12 @@ static ssize_t cyapa_update_fw_store(struct device *dev, dev_dbg(dev, "firmware update successfully done.\n"); /* - * Redetect trackpad device states because firmware update process + * Re-detect trackpad device states because firmware update process * will reset trackpad device into bootloader mode. */ ret = cyapa_reinitialize(cyapa); if (ret) { - dev_err(dev, "failed to redetect after updated: %d\n", ret); + dev_err(dev, "failed to re-detect after updated: %d\n", ret); error = error ? error : ret; } diff --git a/drivers/input/mouse/cyapa.h b/drivers/input/mouse/cyapa.h index adc9ed5dcb0e..d019d1d2d1e4 100644 --- a/drivers/input/mouse/cyapa.h +++ b/drivers/input/mouse/cyapa.h @@ -3,7 +3,7 @@ * * Author: Dudley Du * - * Copyright (C) 2014 Cypress Semiconductor, Inc. + * Copyright (C) 2014-2015 Cypress Semiconductor, Inc. * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive for @@ -25,7 +25,7 @@ /* * Macros for SMBus communication */ -#define SMBUS_READ 0x01 +#define SMBUS_READ 0x01 #define SMBUS_WRITE 0x00 #define SMBUS_ENCODE_IDX(cmd, idx) ((cmd) | (((idx) & 0x03) << 1)) #define SMBUS_ENCODE_RW(cmd, rw) ((cmd) | ((rw) & 0x01)) @@ -159,12 +159,86 @@ #define AUTOSUSPEND_DELAY 2000 /* unit : ms */ -#define UNINIT_SLEEP_TIME 0xFFFF -#define UNINIT_PWR_MODE 0xFF - #define BTN_ONLY_MODE_NAME "buttononly" #define OFF_MODE_NAME "off" +/* Common macros for PIP interface. */ +#define PIP_HID_DESCRIPTOR_ADDR 0x0001 +#define PIP_REPORT_DESCRIPTOR_ADDR 0x0002 +#define PIP_INPUT_REPORT_ADDR 0x0003 +#define PIP_OUTPUT_REPORT_ADDR 0x0004 +#define PIP_CMD_DATA_ADDR 0x0006 + +#define PIP_RETRIEVE_DATA_STRUCTURE 0x24 +#define PIP_CMD_CALIBRATE 0x28 +#define PIP_BL_CMD_VERIFY_APP_INTEGRITY 0x31 +#define PIP_BL_CMD_GET_BL_INFO 0x38 +#define PIP_BL_CMD_PROGRAM_VERIFY_ROW 0x39 +#define PIP_BL_CMD_LAUNCH_APP 0x3b +#define PIP_BL_CMD_INITIATE_BL 0x48 +#define PIP_INVALID_CMD 0xff + +#define PIP_HID_DESCRIPTOR_SIZE 32 +#define PIP_HID_APP_REPORT_ID 0xf7 +#define PIP_HID_BL_REPORT_ID 0xff + +#define PIP_BL_CMD_REPORT_ID 0x40 +#define PIP_BL_RESP_REPORT_ID 0x30 +#define PIP_APP_CMD_REPORT_ID 0x2f +#define PIP_APP_RESP_REPORT_ID 0x1f + +#define PIP_READ_SYS_INFO_CMD_LENGTH 7 +#define PIP_BL_READ_APP_INFO_CMD_LENGTH 13 +#define PIP_MIN_BL_CMD_LENGTH 13 +#define PIP_MIN_BL_RESP_LENGTH 11 +#define PIP_MIN_APP_CMD_LENGTH 7 +#define PIP_MIN_APP_RESP_LENGTH 5 +#define PIP_UNSUPPORTED_CMD_RESP_LENGTH 6 +#define PIP_READ_SYS_INFO_RESP_LENGTH 71 +#define PIP_BL_APP_INFO_RESP_LENGTH 30 +#define PIP_BL_GET_INFO_RESP_LENGTH 19 + +#define PIP_PRODUCT_FAMILY_MASK 0xf000 +#define PIP_PRODUCT_FAMILY_TRACKPAD 0x1000 + +#define PIP_DEEP_SLEEP_STATE_ON 0x00 +#define PIP_DEEP_SLEEP_STATE_OFF 0x01 +#define PIP_DEEP_SLEEP_STATE_MASK 0x03 +#define PIP_APP_DEEP_SLEEP_REPORT_ID 0xf0 +#define PIP_DEEP_SLEEP_RESP_LENGTH 5 +#define PIP_DEEP_SLEEP_OPCODE 0x08 +#define PIP_DEEP_SLEEP_OPCODE_MASK 0x0f + +#define PIP_RESP_LENGTH_OFFSET 0 +#define PIP_RESP_LENGTH_SIZE 2 +#define PIP_RESP_REPORT_ID_OFFSET 2 +#define PIP_RESP_RSVD_OFFSET 3 +#define PIP_RESP_RSVD_KEY 0x00 +#define PIP_RESP_BL_SOP_OFFSET 4 +#define PIP_SOP_KEY 0x01 /* Start of Packet */ +#define PIP_EOP_KEY 0x17 /* End of Packet */ +#define PIP_RESP_APP_CMD_OFFSET 4 +#define GET_PIP_CMD_CODE(reg) ((reg) & 0x7f) +#define PIP_RESP_STATUS_OFFSET 5 + +#define VALID_CMD_RESP_HEADER(resp, cmd) \ + (((resp)[PIP_RESP_REPORT_ID_OFFSET] == PIP_APP_RESP_REPORT_ID) && \ + ((resp)[PIP_RESP_RSVD_OFFSET] == PIP_RESP_RSVD_KEY) && \ + (GET_PIP_CMD_CODE((resp)[PIP_RESP_APP_CMD_OFFSET]) == (cmd))) + +#define PIP_CMD_COMPLETE_SUCCESS(resp_data) \ + ((resp_data)[PIP_RESP_STATUS_OFFSET] == 0x00) + +/* Variables to record latest gen5 trackpad power states. */ +#define UNINIT_SLEEP_TIME 0xffff +#define UNINIT_PWR_MODE 0xff +#define PIP_DEV_SET_PWR_STATE(cyapa, s) ((cyapa)->dev_pwr_mode = (s)) +#define PIP_DEV_GET_PWR_STATE(cyapa) ((cyapa)->dev_pwr_mode) +#define PIP_DEV_SET_SLEEP_TIME(cyapa, t) ((cyapa)->dev_sleep_time = (t)) +#define PIP_DEV_GET_SLEEP_TIME(cyapa) ((cyapa)->dev_sleep_time) +#define PIP_DEV_UNINIT_SLEEP_TIME(cyapa) \ + (((cyapa)->dev_sleep_time) == UNINIT_SLEEP_TIME) + /* The touch.id is used as the MT slot id, thus max MT slot is 15 */ #define CYAPA_MAX_MT_SLOTS 15 @@ -198,7 +272,7 @@ struct cyapa_dev_ops { int (*set_power_mode)(struct cyapa *, u8, u16); }; -struct cyapa_gen5_cmd_states { +struct cyapa_pip_cmd_states { struct mutex cmd_lock; struct completion cmd_ready; atomic_t cmd_issued; @@ -214,7 +288,7 @@ struct cyapa_gen5_cmd_states { }; union cyapa_cmd_states { - struct cyapa_gen5_cmd_states gen5; + struct cyapa_pip_cmd_states pip; }; enum cyapa_state { @@ -259,7 +333,7 @@ struct cyapa { int physical_size_y; /* Used in ttsp and truetouch based trackpad devices. */ - u8 x_origin; /* X Axis Origin: 0 = left side; 1 = rigth side. */ + u8 x_origin; /* X Axis Origin: 0 = left side; 1 = right side. */ u8 y_origin; /* Y Axis Origin: 0 = top; 1 = bottom. */ int electrodes_x; /* Number of electrodes on the X Axis*/ int electrodes_y; /* Number of electrodes on the Y Axis*/ @@ -282,9 +356,9 @@ struct cyapa { ssize_t cyapa_i2c_reg_read_block(struct cyapa *cyapa, u8 reg, size_t len, - u8 *values); + u8 *values); ssize_t cyapa_smbus_read_block(struct cyapa *cyapa, u8 cmd, size_t len, - u8 *values); + u8 *values); ssize_t cyapa_read_block(struct cyapa *cyapa, u8 cmd_idx, u8 *values); @@ -293,7 +367,47 @@ int cyapa_poll_state(struct cyapa *cyapa, unsigned int timeout); u8 cyapa_sleep_time_to_pwr_cmd(u16 sleep_time); u16 cyapa_pwr_cmd_to_sleep_time(u8 pwr_mode); - +ssize_t cyapa_i2c_pip_read(struct cyapa *cyapa, u8 *buf, size_t size); +ssize_t cyapa_i2c_pip_write(struct cyapa *cyapa, u8 *buf, size_t size); +int cyapa_empty_pip_output_data(struct cyapa *cyapa, + u8 *buf, int *len, cb_sort func); +int cyapa_i2c_pip_cmd_irq_sync(struct cyapa *cyapa, + u8 *cmd, int cmd_len, + u8 *resp_data, int *resp_len, + unsigned long timeout, + cb_sort func, + bool irq_mode); +int cyapa_pip_state_parse(struct cyapa *cyapa, u8 *reg_data, int len); +bool cyapa_pip_sort_system_info_data(struct cyapa *cyapa, u8 *buf, int len); +bool cyapa_sort_tsg_pip_bl_resp_data(struct cyapa *cyapa, u8 *data, int len); +int cyapa_pip_deep_sleep(struct cyapa *cyapa, u8 state); +bool cyapa_sort_tsg_pip_app_resp_data(struct cyapa *cyapa, u8 *data, int len); +int cyapa_pip_bl_exit(struct cyapa *cyapa); +int cyapa_pip_bl_enter(struct cyapa *cyapa); + + +bool cyapa_is_pip_bl_mode(struct cyapa *cyapa); +bool cyapa_is_pip_app_mode(struct cyapa *cyapa); +int cyapa_pip_cmd_state_initialize(struct cyapa *cyapa); + +int cyapa_pip_resume_scanning(struct cyapa *cyapa); +int cyapa_pip_suspend_scanning(struct cyapa *cyapa); + +int cyapa_pip_check_fw(struct cyapa *cyapa, const struct firmware *fw); +int cyapa_pip_bl_initiate(struct cyapa *cyapa, const struct firmware *fw); +int cyapa_pip_do_fw_update(struct cyapa *cyapa, const struct firmware *fw); +int cyapa_pip_bl_activate(struct cyapa *cyapa); +int cyapa_pip_bl_deactivate(struct cyapa *cyapa); +ssize_t cyapa_pip_do_calibrate(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count); + +bool cyapa_pip_irq_cmd_handler(struct cyapa *cyapa); +int cyapa_pip_irq_handler(struct cyapa *cyapa); + + +extern u8 pip_read_sys_info[]; +extern u8 pip_bl_read_app_info[]; extern const char product_id[]; extern const struct cyapa_dev_ops cyapa_gen3_ops; extern const struct cyapa_dev_ops cyapa_gen5_ops; diff --git a/drivers/input/mouse/cyapa_gen3.c b/drivers/input/mouse/cyapa_gen3.c index 3faf01c1b191..3884311410f7 100644 --- a/drivers/input/mouse/cyapa_gen3.c +++ b/drivers/input/mouse/cyapa_gen3.c @@ -6,7 +6,7 @@ * Daniel Kurtz * Benson Leung * - * Copyright (C) 2011-2014 Cypress Semiconductor, Inc. + * Copyright (C) 2011-2015 Cypress Semiconductor, Inc. * Copyright (C) 2011-2012 Google, Inc. * * This file is subject to the terms and conditions of the GNU General Public @@ -1156,7 +1156,7 @@ static bool cyapa_gen3_irq_cmd_handler(struct cyapa *cyapa) * so, stop cyapa_gen3_irq_handler to continue process to * avoid unwanted to error detecting and processing. * - * And also, avoid the periodicly accerted interrupts to be processed + * And also, avoid the periodically asserted interrupts to be processed * as touch inputs when gen3 failed to launch into application mode, * which will cause gen3 stays in bootloader mode. */ diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c index afc39e799da2..9d75c6f9f307 100644 --- a/drivers/input/mouse/cyapa_gen5.c +++ b/drivers/input/mouse/cyapa_gen5.c @@ -3,7 +3,7 @@ * * Author: Dudley Du * - * Copyright (C) 2014 Cypress Semiconductor, Inc. + * Copyright (C) 2014-2015 Cypress Semiconductor, Inc. * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive for @@ -22,12 +22,7 @@ #include "cyapa.h" -/* Macro of Gen5 */ -#define RECORD_EVENT_NONE 0 -#define RECORD_EVENT_TOUCHDOWN 1 -#define RECORD_EVENT_DISPLACE 2 -#define RECORD_EVENT_LIFTOFF 3 - +/* Macro of TSG firmware image */ #define CYAPA_TSG_FLASH_MAP_BLOCK_SIZE 0x80 #define CYAPA_TSG_IMG_FW_HDR_SIZE 13 #define CYAPA_TSG_FW_ROW_SIZE (CYAPA_TSG_FLASH_MAP_BLOCK_SIZE) @@ -44,43 +39,48 @@ #define CYAPA_TSG_MAX_CMD_SIZE 256 -#define GEN5_BL_CMD_VERIFY_APP_INTEGRITY 0x31 -#define GEN5_BL_CMD_GET_BL_INFO 0x38 -#define GEN5_BL_CMD_PROGRAM_VERIFY_ROW 0x39 -#define GEN5_BL_CMD_LAUNCH_APP 0x3b -#define GEN5_BL_CMD_INITIATE_BL 0x48 - -#define GEN5_HID_DESCRIPTOR_ADDR 0x0001 -#define GEN5_REPORT_DESCRIPTOR_ADDR 0x0002 -#define GEN5_INPUT_REPORT_ADDR 0x0003 -#define GEN5_OUTPUT_REPORT_ADDR 0x0004 -#define GEN5_CMD_DATA_ADDR 0x0006 - -#define GEN5_TOUCH_REPORT_HEAD_SIZE 7 -#define GEN5_TOUCH_REPORT_MAX_SIZE 127 -#define GEN5_BTN_REPORT_HEAD_SIZE 6 -#define GEN5_BTN_REPORT_MAX_SIZE 14 -#define GEN5_WAKEUP_EVENT_SIZE 4 -#define GEN5_RAW_DATA_HEAD_SIZE 24 - -#define GEN5_BL_CMD_REPORT_ID 0x40 -#define GEN5_BL_RESP_REPORT_ID 0x30 -#define GEN5_APP_CMD_REPORT_ID 0x2f -#define GEN5_APP_RESP_REPORT_ID 0x1f - -#define GEN5_APP_DEEP_SLEEP_REPORT_ID 0xf0 -#define GEN5_DEEP_SLEEP_RESP_LENGTH 5 +/* Macro of PIP interface */ +#define PIP_BL_INITIATE_RESP_LEN 11 +#define PIP_BL_FAIL_EXIT_RESP_LEN 11 +#define PIP_BL_FAIL_EXIT_STATUS_CODE 0x0c +#define PIP_BL_VERIFY_INTEGRITY_RESP_LEN 12 +#define PIP_BL_INTEGRITY_CHEKC_PASS 0x00 +#define PIP_BL_BLOCK_WRITE_RESP_LEN 11 + +#define PIP_TOUCH_REPORT_ID 0x01 +#define PIP_BTN_REPORT_ID 0x03 +#define PIP_WAKEUP_EVENT_REPORT_ID 0x04 +#define PIP_PUSH_BTN_REPORT_ID 0x06 +#define GEN5_OLD_PUSH_BTN_REPORT_ID 0x05 /* Special for old Gen5 TP. */ + +#define PIP_TOUCH_REPORT_HEAD_SIZE 7 +#define PIP_TOUCH_REPORT_MAX_SIZE 127 +#define PIP_BTN_REPORT_HEAD_SIZE 6 +#define PIP_BTN_REPORT_MAX_SIZE 14 +#define PIP_WAKEUP_EVENT_SIZE 4 + +#define PIP_NUMBER_OF_TOUCH_OFFSET 5 +#define PIP_NUMBER_OF_TOUCH_MASK 0x1f +#define PIP_BUTTONS_OFFSET 5 +#define PIP_BUTTONS_MASK 0x0f +#define PIP_GET_EVENT_ID(reg) (((reg) >> 5) & 0x03) +#define PIP_GET_TOUCH_ID(reg) ((reg) & 0x1f) +#define PIP_TOUCH_TYPE_FINGER 0x00 +#define PIP_TOUCH_TYPE_PROXIMITY 0x01 +#define PIP_TOUCH_TYPE_HOVER 0x02 +#define PIP_GET_TOUCH_TYPE(reg) ((reg) & 0x07) -#define GEN5_CMD_GET_PARAMETER 0x05 -#define GEN5_CMD_SET_PARAMETER 0x06 -#define GEN5_PARAMETER_ACT_INTERVL_ID 0x4d -#define GEN5_PARAMETER_ACT_INTERVL_SIZE 1 -#define GEN5_PARAMETER_ACT_LFT_INTERVL_ID 0x4f -#define GEN5_PARAMETER_ACT_LFT_INTERVL_SIZE 2 -#define GEN5_PARAMETER_LP_INTRVL_ID 0x4c -#define GEN5_PARAMETER_LP_INTRVL_SIZE 2 +#define RECORD_EVENT_NONE 0 +#define RECORD_EVENT_TOUCHDOWN 1 +#define RECORD_EVENT_DISPLACE 2 +#define RECORD_EVENT_LIFTOFF 3 -#define GEN5_PARAMETER_DISABLE_PIP_REPORT 0x08 +#define PIP_SENSING_MODE_MUTUAL_CAP_FINE 0x00 +#define PIP_SENSING_MODE_SELF_CAP 0x02 + +/* Macro of Gen5 */ +#define GEN5_BL_MAX_OUTPUT_LENGTH 0x0100 +#define GEN5_APP_MAX_OUTPUT_LENGTH 0x00fe #define GEN5_POWER_STATE_ACTIVE 0x01 #define GEN5_POWER_STATE_LOOK_FOR_TOUCH 0x02 @@ -89,46 +89,19 @@ #define GEN5_POWER_STATE_BTN_ONLY 0x05 #define GEN5_POWER_STATE_OFF 0x06 -#define GEN5_DEEP_SLEEP_STATE_MASK 0x03 -#define GEN5_DEEP_SLEEP_STATE_ON 0x00 -#define GEN5_DEEP_SLEEP_STATE_OFF 0x01 - -#define GEN5_DEEP_SLEEP_OPCODE 0x08 -#define GEN5_DEEP_SLEEP_OPCODE_MASK 0x0f - #define GEN5_POWER_READY_MAX_INTRVL_TIME 50 /* Unit: ms */ #define GEN5_POWER_IDLE_MAX_INTRVL_TIME 250 /* Unit: ms */ -#define GEN5_CMD_REPORT_ID_OFFSET 4 - -#define GEN5_RESP_REPORT_ID_OFFSET 2 -#define GEN5_RESP_RSVD_OFFSET 3 -#define GEN5_RESP_RSVD_KEY 0x00 -#define GEN5_RESP_BL_SOP_OFFSET 4 -#define GEN5_SOP_KEY 0x01 /* Start of Packet */ -#define GEN5_EOP_KEY 0x17 /* End of Packet */ -#define GEN5_RESP_APP_CMD_OFFSET 4 -#define GET_GEN5_CMD_CODE(reg) ((reg) & 0x7f) - -#define VALID_CMD_RESP_HEADER(resp, cmd) \ - (((resp)[GEN5_RESP_REPORT_ID_OFFSET] == GEN5_APP_RESP_REPORT_ID) && \ - ((resp)[GEN5_RESP_RSVD_OFFSET] == GEN5_RESP_RSVD_KEY) && \ - (GET_GEN5_CMD_CODE((resp)[GEN5_RESP_APP_CMD_OFFSET]) == (cmd))) - -#define GEN5_MIN_BL_CMD_LENGTH 13 -#define GEN5_MIN_BL_RESP_LENGTH 11 -#define GEN5_MIN_APP_CMD_LENGTH 7 -#define GEN5_MIN_APP_RESP_LENGTH 5 -#define GEN5_UNSUPPORTED_CMD_RESP_LENGTH 6 - -#define GEN5_RESP_LENGTH_OFFSET 0x00 -#define GEN5_RESP_LENGTH_SIZE 2 - -#define GEN5_HID_DESCRIPTOR_SIZE 32 -#define GEN5_BL_HID_REPORT_ID 0xff -#define GEN5_APP_HID_REPORT_ID 0xf7 -#define GEN5_BL_MAX_OUTPUT_LENGTH 0x0100 -#define GEN5_APP_MAX_OUTPUT_LENGTH 0x00fe +#define GEN5_CMD_GET_PARAMETER 0x05 +#define GEN5_CMD_SET_PARAMETER 0x06 +#define GEN5_PARAMETER_ACT_INTERVL_ID 0x4d +#define GEN5_PARAMETER_ACT_INTERVL_SIZE 1 +#define GEN5_PARAMETER_ACT_LFT_INTERVL_ID 0x4f +#define GEN5_PARAMETER_ACT_LFT_INTERVL_SIZE 2 +#define GEN5_PARAMETER_LP_INTRVL_ID 0x4c +#define GEN5_PARAMETER_LP_INTRVL_SIZE 2 + +#define GEN5_PARAMETER_DISABLE_PIP_REPORT 0x08 #define GEN5_BL_REPORT_DESCRIPTOR_SIZE 0x1d #define GEN5_BL_REPORT_DESCRIPTOR_ID 0xfe @@ -136,26 +109,6 @@ #define GEN5_APP_CONTRACT_REPORT_DESCRIPTOR_SIZE 0xfa #define GEN5_APP_REPORT_DESCRIPTOR_ID 0xf6 -#define GEN5_TOUCH_REPORT_ID 0x01 -#define GEN5_BTN_REPORT_ID 0x03 -#define GEN5_WAKEUP_EVENT_REPORT_ID 0x04 -#define GEN5_OLD_PUSH_BTN_REPORT_ID 0x05 -#define GEN5_PUSH_BTN_REPORT_ID 0x06 - -#define GEN5_CMD_COMPLETE_SUCCESS(status) ((status) == 0x00) - -#define GEN5_BL_INITIATE_RESP_LEN 11 -#define GEN5_BL_FAIL_EXIT_RESP_LEN 11 -#define GEN5_BL_FAIL_EXIT_STATUS_CODE 0x0c -#define GEN5_BL_VERIFY_INTEGRITY_RESP_LEN 12 -#define GEN5_BL_INTEGRITY_CHEKC_PASS 0x00 -#define GEN5_BL_BLOCK_WRITE_RESP_LEN 11 -#define GEN5_BL_READ_APP_INFO_RESP_LEN 31 -#define GEN5_CMD_CALIBRATE 0x28 -#define CYAPA_SENSING_MODE_MUTUAL_CAP_FINE 0x00 -#define CYAPA_SENSING_MODE_SELF_CAP 0x02 - -#define GEN5_CMD_RETRIEVE_DATA_STRUCTURE 0x24 #define GEN5_RETRIEVE_MUTUAL_PWC_DATA 0x00 #define GEN5_RETRIEVE_SELF_CAP_PWC_DATA 0x01 @@ -170,23 +123,12 @@ #define GEN5_PANEL_SCAN_SELF_BASELINE 0x04 #define GEN5_PANEL_SCAN_SELF_DIFFCOUNT 0x05 -/* The offset only valid for reterive PWC and panel scan commands */ +/* The offset only valid for retrieve PWC and panel scan commands */ #define GEN5_RESP_DATA_STRUCTURE_OFFSET 10 #define GEN5_PWC_DATA_ELEMENT_SIZE_MASK 0x07 -#define GEN5_NUMBER_OF_TOUCH_OFFSET 5 -#define GEN5_NUMBER_OF_TOUCH_MASK 0x1f -#define GEN5_BUTTONS_OFFSET 5 -#define GEN5_BUTTONS_MASK 0x0f -#define GEN5_GET_EVENT_ID(reg) (((reg) >> 5) & 0x03) -#define GEN5_GET_TOUCH_ID(reg) ((reg) & 0x1f) - -#define GEN5_PRODUCT_FAMILY_MASK 0xf000 -#define GEN5_PRODUCT_FAMILY_TRACKPAD 0x1000 - -#define TSG_INVALID_CMD 0xff -struct cyapa_gen5_touch_record { +struct cyapa_pip_touch_record { /* * Bit 7 - 3: reserved * Bit 2 - 0: touch type; @@ -221,7 +163,11 @@ struct cyapa_gen5_touch_record { /* Bit 15 - 8 of Y-axis coordinate of the touch in pixel. */ u8 y_hi; - /* Touch intensity in counts, pressure value. */ + /* + * The meaning of this value is different when touch_type is different. + * For standard finger type: + * Touch intensity in counts, pressure value. + **/ u8 z; /* @@ -260,9 +206,9 @@ struct cyapa_gen5_touch_record { u8 orientation; } __packed; -struct cyapa_gen5_report_data { - u8 report_head[GEN5_TOUCH_REPORT_HEAD_SIZE]; - struct cyapa_gen5_touch_record touch_records[10]; +struct cyapa_pip_report_data { + u8 report_head[PIP_TOUCH_REPORT_HEAD_SIZE]; + struct cyapa_pip_touch_record touch_records[10]; } __packed; struct cyapa_tsg_bin_image_head { @@ -288,36 +234,36 @@ struct cyapa_tsg_bin_image { struct cyapa_tsg_bin_image_data_record records[0]; } __packed; -struct gen5_bl_packet_start { +struct pip_bl_packet_start { u8 sop; /* Start of packet, must be 01h */ u8 cmd_code; __le16 data_length; /* Size of data parameter start from data[0] */ } __packed; -struct gen5_bl_packet_end { +struct pip_bl_packet_end { __le16 crc; u8 eop; /* End of packet, must be 17h */ } __packed; -struct gen5_bl_cmd_head { +struct pip_bl_cmd_head { __le16 addr; /* Output report register address, must be 0004h */ /* Size of packet not including output report register address */ __le16 length; u8 report_id; /* Bootloader output report id, must be 40h */ u8 rsvd; /* Reserved, must be 0 */ - struct gen5_bl_packet_start packet_start; + struct pip_bl_packet_start packet_start; u8 data[0]; /* Command data variable based on commands */ } __packed; /* Initiate bootload command data structure. */ -struct gen5_bl_initiate_cmd_data { +struct pip_bl_initiate_cmd_data { /* Key must be "A5h 01h 02h 03h FFh FEh FDh 5Ah" */ u8 key[CYAPA_TSG_BL_KEY_SIZE]; u8 metadata_raw_parameter[CYAPA_TSG_FLASH_MAP_METADATA_SIZE]; __le16 metadata_crc; } __packed; -struct gen5_bl_metadata_row_params { +struct tsg_bl_metadata_row_params { __le16 size; __le16 maximum_size; __le32 app_start; @@ -332,13 +278,13 @@ struct gen5_bl_metadata_row_params { } __packed; /* Bootload program and verify row command data structure */ -struct gen5_bl_flash_row_head { +struct tsg_bl_flash_row_head { u8 flash_array_id; __le16 flash_row_id; u8 flash_data[0]; } __packed; -struct gen5_app_cmd_head { +struct pip_app_cmd_head { __le16 addr; /* Output report register address, must be 0004h */ /* Size of packet not including output report register address */ __le16 length; @@ -369,30 +315,26 @@ struct gen5_retrieve_panel_scan_data { u8 data_id; } __packed; -/* Variables to record latest gen5 trackpad power states. */ -#define GEN5_DEV_SET_PWR_STATE(cyapa, s) ((cyapa)->dev_pwr_mode = (s)) -#define GEN5_DEV_GET_PWR_STATE(cyapa) ((cyapa)->dev_pwr_mode) -#define GEN5_DEV_SET_SLEEP_TIME(cyapa, t) ((cyapa)->dev_sleep_time = (t)) -#define GEN5_DEV_GET_SLEEP_TIME(cyapa) ((cyapa)->dev_sleep_time) -#define GEN5_DEV_UNINIT_SLEEP_TIME(cyapa) \ - (((cyapa)->dev_sleep_time) == UNINIT_SLEEP_TIME) - +u8 pip_read_sys_info[] = { 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x02 }; +u8 pip_bl_read_app_info[] = { 0x04, 0x00, 0x0b, 0x00, 0x40, 0x00, + 0x01, 0x3c, 0x00, 0x00, 0xb0, 0x42, 0x17 + }; -static u8 cyapa_gen5_bl_cmd_key[] = { 0xa5, 0x01, 0x02, 0x03, +static u8 cyapa_pip_bl_cmd_key[] = { 0xa5, 0x01, 0x02, 0x03, 0xff, 0xfe, 0xfd, 0x5a }; -static int cyapa_gen5_initialize(struct cyapa *cyapa) +int cyapa_pip_cmd_state_initialize(struct cyapa *cyapa) { - struct cyapa_gen5_cmd_states *gen5_pip = &cyapa->cmd_states.gen5; + struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip; - init_completion(&gen5_pip->cmd_ready); - atomic_set(&gen5_pip->cmd_issued, 0); - mutex_init(&gen5_pip->cmd_lock); + init_completion(&pip->cmd_ready); + atomic_set(&pip->cmd_issued, 0); + mutex_init(&pip->cmd_lock); - gen5_pip->resp_sort_func = NULL; - gen5_pip->in_progress_cmd = TSG_INVALID_CMD; - gen5_pip->resp_data = NULL; - gen5_pip->resp_len = NULL; + pip->resp_sort_func = NULL; + pip->in_progress_cmd = PIP_INVALID_CMD; + pip->resp_data = NULL; + pip->resp_len = NULL; cyapa->dev_pwr_mode = UNINIT_PWR_MODE; cyapa->dev_sleep_time = UNINIT_SLEEP_TIME; @@ -401,7 +343,7 @@ static int cyapa_gen5_initialize(struct cyapa *cyapa) } /* Return negative errno, or else the number of bytes read. */ -static ssize_t cyapa_i2c_pip_read(struct cyapa *cyapa, u8 *buf, size_t size) +ssize_t cyapa_i2c_pip_read(struct cyapa *cyapa, u8 *buf, size_t size) { int ret; @@ -415,14 +357,13 @@ static ssize_t cyapa_i2c_pip_read(struct cyapa *cyapa, u8 *buf, size_t size) if (ret != size) return (ret < 0) ? ret : -EIO; - return size; } /** * Return a negative errno code else zero on success. */ -static ssize_t cyapa_i2c_pip_write(struct cyapa *cyapa, u8 *buf, size_t size) +ssize_t cyapa_i2c_pip_write(struct cyapa *cyapa, u8 *buf, size_t size) { int ret; @@ -441,10 +382,10 @@ static ssize_t cyapa_i2c_pip_write(struct cyapa *cyapa, u8 *buf, size_t size) * This function is aimed to dump all not read data in Gen5 trackpad * before send any command, otherwise, the interrupt line will be blocked. */ -static int cyapa_empty_pip_output_data(struct cyapa *cyapa, +int cyapa_empty_pip_output_data(struct cyapa *cyapa, u8 *buf, int *len, cb_sort func) { - struct cyapa_gen5_cmd_states *gen5_pip = &cyapa->cmd_states.gen5; + struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip; int length; int report_count; int empty_count; @@ -476,13 +417,13 @@ static int cyapa_empty_pip_output_data(struct cyapa *cyapa, if (empty_count > 5) return 0; - error = cyapa_i2c_pip_read(cyapa, gen5_pip->empty_buf, - GEN5_RESP_LENGTH_SIZE); + error = cyapa_i2c_pip_read(cyapa, pip->empty_buf, + PIP_RESP_LENGTH_SIZE); if (error < 0) return error; - length = get_unaligned_le16(gen5_pip->empty_buf); - if (length == GEN5_RESP_LENGTH_SIZE) { + length = get_unaligned_le16(pip->empty_buf); + if (length == PIP_RESP_LENGTH_SIZE) { empty_count++; continue; } else if (length > CYAPA_REG_MAP_SIZE) { @@ -490,11 +431,11 @@ static int cyapa_empty_pip_output_data(struct cyapa *cyapa, return -EINVAL; } else if (length == 0) { /* Application or bootloader launch data polled out. */ - length = GEN5_RESP_LENGTH_SIZE; + length = PIP_RESP_LENGTH_SIZE; if (buf && buf_len && func && - func(cyapa, gen5_pip->empty_buf, length)) { + func(cyapa, pip->empty_buf, length)) { length = min(buf_len, length); - memcpy(buf, gen5_pip->empty_buf, length); + memcpy(buf, pip->empty_buf, length); *len = length; /* Response found, success. */ return 0; @@ -502,19 +443,19 @@ static int cyapa_empty_pip_output_data(struct cyapa *cyapa, continue; } - error = cyapa_i2c_pip_read(cyapa, gen5_pip->empty_buf, length); + error = cyapa_i2c_pip_read(cyapa, pip->empty_buf, length); if (error < 0) return error; report_count--; empty_count = 0; - length = get_unaligned_le16(gen5_pip->empty_buf); - if (length <= GEN5_RESP_LENGTH_SIZE) { + length = get_unaligned_le16(pip->empty_buf); + if (length <= PIP_RESP_LENGTH_SIZE) { empty_count++; } else if (buf && buf_len && func && - func(cyapa, gen5_pip->empty_buf, length)) { + func(cyapa, pip->empty_buf, length)) { length = min(buf_len, length); - memcpy(buf, gen5_pip->empty_buf, length); + memcpy(buf, pip->empty_buf, length); *len = length; /* Response found, success. */ return 0; @@ -531,24 +472,24 @@ static int cyapa_do_i2c_pip_cmd_irq_sync( u8 *cmd, size_t cmd_len, unsigned long timeout) { - struct cyapa_gen5_cmd_states *gen5_pip = &cyapa->cmd_states.gen5; + struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip; int error; /* Wait for interrupt to set ready completion */ - init_completion(&gen5_pip->cmd_ready); + init_completion(&pip->cmd_ready); - atomic_inc(&gen5_pip->cmd_issued); + atomic_inc(&pip->cmd_issued); error = cyapa_i2c_pip_write(cyapa, cmd, cmd_len); if (error) { - atomic_dec(&gen5_pip->cmd_issued); + atomic_dec(&pip->cmd_issued); return (error < 0) ? error : -EIO; } /* Wait for interrupt to indicate command is completed. */ - timeout = wait_for_completion_timeout(&gen5_pip->cmd_ready, + timeout = wait_for_completion_timeout(&pip->cmd_ready, msecs_to_jiffies(timeout)); if (timeout == 0) { - atomic_dec(&gen5_pip->cmd_issued); + atomic_dec(&pip->cmd_issued); return -ETIMEDOUT; } @@ -562,15 +503,15 @@ static int cyapa_do_i2c_pip_cmd_polling( unsigned long timeout, cb_sort func) { - struct cyapa_gen5_cmd_states *gen5_pip = &cyapa->cmd_states.gen5; + struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip; int tries; int length; int error; - atomic_inc(&gen5_pip->cmd_issued); + atomic_inc(&pip->cmd_issued); error = cyapa_i2c_pip_write(cyapa, cmd, cmd_len); if (error) { - atomic_dec(&gen5_pip->cmd_issued); + atomic_dec(&pip->cmd_issued); return error < 0 ? error : -EIO; } @@ -591,11 +532,11 @@ static int cyapa_do_i2c_pip_cmd_polling( error = error ? error : -ETIMEDOUT; } - atomic_dec(&gen5_pip->cmd_issued); + atomic_dec(&pip->cmd_issued); return error; } -static int cyapa_i2c_pip_cmd_irq_sync( +int cyapa_i2c_pip_cmd_irq_sync( struct cyapa *cyapa, u8 *cmd, int cmd_len, u8 *resp_data, int *resp_len, @@ -603,34 +544,34 @@ static int cyapa_i2c_pip_cmd_irq_sync( cb_sort func, bool irq_mode) { - struct cyapa_gen5_cmd_states *gen5_pip = &cyapa->cmd_states.gen5; + struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip; int error; if (!cmd || !cmd_len) return -EINVAL; /* Commands must be serialized. */ - error = mutex_lock_interruptible(&gen5_pip->cmd_lock); + error = mutex_lock_interruptible(&pip->cmd_lock); if (error) return error; - gen5_pip->resp_sort_func = func; - gen5_pip->resp_data = resp_data; - gen5_pip->resp_len = resp_len; + pip->resp_sort_func = func; + pip->resp_data = resp_data; + pip->resp_len = resp_len; - if (cmd_len >= GEN5_MIN_APP_CMD_LENGTH && - cmd[4] == GEN5_APP_CMD_REPORT_ID) { + if (cmd_len >= PIP_MIN_APP_CMD_LENGTH && + cmd[4] == PIP_APP_CMD_REPORT_ID) { /* Application command */ - gen5_pip->in_progress_cmd = cmd[6] & 0x7f; - } else if (cmd_len >= GEN5_MIN_BL_CMD_LENGTH && - cmd[4] == GEN5_BL_CMD_REPORT_ID) { + pip->in_progress_cmd = cmd[6] & 0x7f; + } else if (cmd_len >= PIP_MIN_BL_CMD_LENGTH && + cmd[4] == PIP_BL_CMD_REPORT_ID) { /* Bootloader command */ - gen5_pip->in_progress_cmd = cmd[7]; + pip->in_progress_cmd = cmd[7]; } /* Send command data, wait and read output response data's length. */ if (irq_mode) { - gen5_pip->is_irq_mode = true; + pip->is_irq_mode = true; error = cyapa_do_i2c_pip_cmd_irq_sync(cyapa, cmd, cmd_len, timeout); if (error == -ETIMEDOUT && resp_data && @@ -646,54 +587,54 @@ static int cyapa_i2c_pip_cmd_irq_sync( error = error ? error : -ETIMEDOUT; } } else { - gen5_pip->is_irq_mode = false; + pip->is_irq_mode = false; error = cyapa_do_i2c_pip_cmd_polling(cyapa, cmd, cmd_len, resp_data, resp_len, timeout, func); } - gen5_pip->resp_sort_func = NULL; - gen5_pip->resp_data = NULL; - gen5_pip->resp_len = NULL; - gen5_pip->in_progress_cmd = TSG_INVALID_CMD; + pip->resp_sort_func = NULL; + pip->resp_data = NULL; + pip->resp_len = NULL; + pip->in_progress_cmd = PIP_INVALID_CMD; - mutex_unlock(&gen5_pip->cmd_lock); + mutex_unlock(&pip->cmd_lock); return error; } -static bool cyapa_gen5_sort_tsg_pip_bl_resp_data(struct cyapa *cyapa, +bool cyapa_sort_tsg_pip_bl_resp_data(struct cyapa *cyapa, u8 *data, int len) { - if (!data || len < GEN5_MIN_BL_RESP_LENGTH) + if (!data || len < PIP_MIN_BL_RESP_LENGTH) return false; /* Bootloader input report id 30h */ - if (data[GEN5_RESP_REPORT_ID_OFFSET] == GEN5_BL_RESP_REPORT_ID && - data[GEN5_RESP_RSVD_OFFSET] == GEN5_RESP_RSVD_KEY && - data[GEN5_RESP_BL_SOP_OFFSET] == GEN5_SOP_KEY) + if (data[PIP_RESP_REPORT_ID_OFFSET] == PIP_BL_RESP_REPORT_ID && + data[PIP_RESP_RSVD_OFFSET] == PIP_RESP_RSVD_KEY && + data[PIP_RESP_BL_SOP_OFFSET] == PIP_SOP_KEY) return true; return false; } -static bool cyapa_gen5_sort_tsg_pip_app_resp_data(struct cyapa *cyapa, +bool cyapa_sort_tsg_pip_app_resp_data(struct cyapa *cyapa, u8 *data, int len) { - struct cyapa_gen5_cmd_states *gen5_pip = &cyapa->cmd_states.gen5; + struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip; int resp_len; - if (!data || len < GEN5_MIN_APP_RESP_LENGTH) + if (!data || len < PIP_MIN_APP_RESP_LENGTH) return false; - if (data[GEN5_RESP_REPORT_ID_OFFSET] == GEN5_APP_RESP_REPORT_ID && - data[GEN5_RESP_RSVD_OFFSET] == GEN5_RESP_RSVD_KEY) { - resp_len = get_unaligned_le16(&data[GEN5_RESP_LENGTH_OFFSET]); - if (GET_GEN5_CMD_CODE(data[GEN5_RESP_APP_CMD_OFFSET]) == 0x00 && - resp_len == GEN5_UNSUPPORTED_CMD_RESP_LENGTH && - data[5] == gen5_pip->in_progress_cmd) { + if (data[PIP_RESP_REPORT_ID_OFFSET] == PIP_APP_RESP_REPORT_ID && + data[PIP_RESP_RSVD_OFFSET] == PIP_RESP_RSVD_KEY) { + resp_len = get_unaligned_le16(&data[PIP_RESP_LENGTH_OFFSET]); + if (GET_PIP_CMD_CODE(data[PIP_RESP_APP_CMD_OFFSET]) == 0x00 && + resp_len == PIP_UNSUPPORTED_CMD_RESP_LENGTH && + data[5] == pip->in_progress_cmd) { /* Unsupported command code */ return false; - } else if (GET_GEN5_CMD_CODE(data[GEN5_RESP_APP_CMD_OFFSET]) == - gen5_pip->in_progress_cmd) { + } else if (GET_PIP_CMD_CODE(data[PIP_RESP_APP_CMD_OFFSET]) == + pip->in_progress_cmd) { /* Correct command response received */ return true; } @@ -702,10 +643,10 @@ static bool cyapa_gen5_sort_tsg_pip_app_resp_data(struct cyapa *cyapa, return false; } -static bool cyapa_gen5_sort_application_launch_data(struct cyapa *cyapa, +static bool cyapa_sort_pip_application_launch_data(struct cyapa *cyapa, u8 *buf, int len) { - if (buf == NULL || len < GEN5_RESP_LENGTH_SIZE) + if (buf == NULL || len < PIP_RESP_LENGTH_SIZE) return false; /* @@ -718,25 +659,25 @@ static bool cyapa_gen5_sort_application_launch_data(struct cyapa *cyapa, return false; } -static bool cyapa_gen5_sort_hid_descriptor_data(struct cyapa *cyapa, +static bool cyapa_sort_gen5_hid_descriptor_data(struct cyapa *cyapa, u8 *buf, int len) { int resp_len; int max_output_len; /* Check hid descriptor. */ - if (len != GEN5_HID_DESCRIPTOR_SIZE) + if (len != PIP_HID_DESCRIPTOR_SIZE) return false; - resp_len = get_unaligned_le16(&buf[GEN5_RESP_LENGTH_OFFSET]); + resp_len = get_unaligned_le16(&buf[PIP_RESP_LENGTH_OFFSET]); max_output_len = get_unaligned_le16(&buf[16]); - if (resp_len == GEN5_HID_DESCRIPTOR_SIZE) { - if (buf[GEN5_RESP_REPORT_ID_OFFSET] == GEN5_BL_HID_REPORT_ID && + if (resp_len == PIP_HID_DESCRIPTOR_SIZE) { + if (buf[PIP_RESP_REPORT_ID_OFFSET] == PIP_HID_BL_REPORT_ID && max_output_len == GEN5_BL_MAX_OUTPUT_LENGTH) { /* BL mode HID Descriptor */ return true; - } else if ((buf[GEN5_RESP_REPORT_ID_OFFSET] == - GEN5_APP_HID_REPORT_ID) && + } else if ((buf[PIP_RESP_REPORT_ID_OFFSET] == + PIP_HID_APP_REPORT_ID) && max_output_len == GEN5_APP_MAX_OUTPUT_LENGTH) { /* APP mode HID Descriptor */ return true; @@ -746,21 +687,21 @@ static bool cyapa_gen5_sort_hid_descriptor_data(struct cyapa *cyapa, return false; } -static bool cyapa_gen5_sort_deep_sleep_data(struct cyapa *cyapa, +static bool cyapa_sort_pip_deep_sleep_data(struct cyapa *cyapa, u8 *buf, int len) { - if (len == GEN5_DEEP_SLEEP_RESP_LENGTH && - buf[GEN5_RESP_REPORT_ID_OFFSET] == - GEN5_APP_DEEP_SLEEP_REPORT_ID && - (buf[4] & GEN5_DEEP_SLEEP_OPCODE_MASK) == - GEN5_DEEP_SLEEP_OPCODE) + if (len == PIP_DEEP_SLEEP_RESP_LENGTH && + buf[PIP_RESP_REPORT_ID_OFFSET] == + PIP_APP_DEEP_SLEEP_REPORT_ID && + (buf[4] & PIP_DEEP_SLEEP_OPCODE_MASK) == + PIP_DEEP_SLEEP_OPCODE) return true; return false; } static int gen5_idle_state_parse(struct cyapa *cyapa) { - u8 resp_data[GEN5_HID_DESCRIPTOR_SIZE]; + u8 resp_data[PIP_HID_DESCRIPTOR_SIZE]; int max_output_len; int length; u8 cmd[2]; @@ -778,9 +719,9 @@ static int gen5_idle_state_parse(struct cyapa *cyapa) if (ret != 3) return ret < 0 ? ret : -EIO; - length = get_unaligned_le16(&resp_data[GEN5_RESP_LENGTH_OFFSET]); - if (length == GEN5_RESP_LENGTH_SIZE) { - /* Normal state of Gen5 with no data to respose */ + length = get_unaligned_le16(&resp_data[PIP_RESP_LENGTH_OFFSET]); + if (length == PIP_RESP_LENGTH_SIZE) { + /* Normal state of Gen5 with no data to response */ cyapa->gen = CYAPA_GEN5; cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); @@ -788,30 +729,30 @@ static int gen5_idle_state_parse(struct cyapa *cyapa) /* Read description from trackpad device */ cmd[0] = 0x01; cmd[1] = 0x00; - length = GEN5_HID_DESCRIPTOR_SIZE; + length = PIP_HID_DESCRIPTOR_SIZE; error = cyapa_i2c_pip_cmd_irq_sync(cyapa, - cmd, GEN5_RESP_LENGTH_SIZE, + cmd, PIP_RESP_LENGTH_SIZE, resp_data, &length, 300, - cyapa_gen5_sort_hid_descriptor_data, + cyapa_sort_gen5_hid_descriptor_data, false); if (error) return error; length = get_unaligned_le16( - &resp_data[GEN5_RESP_LENGTH_OFFSET]); + &resp_data[PIP_RESP_LENGTH_OFFSET]); max_output_len = get_unaligned_le16(&resp_data[16]); - if ((length == GEN5_HID_DESCRIPTOR_SIZE || - length == GEN5_RESP_LENGTH_SIZE) && - (resp_data[GEN5_RESP_REPORT_ID_OFFSET] == - GEN5_BL_HID_REPORT_ID) && + if ((length == PIP_HID_DESCRIPTOR_SIZE || + length == PIP_RESP_LENGTH_SIZE) && + (resp_data[PIP_RESP_REPORT_ID_OFFSET] == + PIP_HID_BL_REPORT_ID) && max_output_len == GEN5_BL_MAX_OUTPUT_LENGTH) { /* BL mode HID Description read */ cyapa->state = CYAPA_STATE_GEN5_BL; - } else if ((length == GEN5_HID_DESCRIPTOR_SIZE || - length == GEN5_RESP_LENGTH_SIZE) && - (resp_data[GEN5_RESP_REPORT_ID_OFFSET] == - GEN5_APP_HID_REPORT_ID) && + } else if ((length == PIP_HID_DESCRIPTOR_SIZE || + length == PIP_RESP_LENGTH_SIZE) && + (resp_data[PIP_RESP_REPORT_ID_OFFSET] == + PIP_HID_APP_REPORT_ID) && max_output_len == GEN5_APP_MAX_OUTPUT_LENGTH) { /* APP mode HID Description read */ cyapa->state = CYAPA_STATE_GEN5_APP; @@ -839,14 +780,14 @@ static int gen5_hid_description_header_parse(struct cyapa *cyapa, u8 *reg_data) * or report any touch or button data. */ ret = cyapa_i2c_pip_read(cyapa, resp_data, - GEN5_HID_DESCRIPTOR_SIZE); - if (ret != GEN5_HID_DESCRIPTOR_SIZE) + PIP_HID_DESCRIPTOR_SIZE); + if (ret != PIP_HID_DESCRIPTOR_SIZE) return ret < 0 ? ret : -EIO; - length = get_unaligned_le16(&resp_data[GEN5_RESP_LENGTH_OFFSET]); + length = get_unaligned_le16(&resp_data[PIP_RESP_LENGTH_OFFSET]); max_output_len = get_unaligned_le16(&resp_data[16]); - if (length == GEN5_RESP_LENGTH_SIZE) { - if (reg_data[GEN5_RESP_REPORT_ID_OFFSET] == - GEN5_BL_HID_REPORT_ID) { + if (length == PIP_RESP_LENGTH_SIZE) { + if (reg_data[PIP_RESP_REPORT_ID_OFFSET] == + PIP_HID_BL_REPORT_ID) { /* * BL mode HID Description has been previously * read out. @@ -861,15 +802,15 @@ static int gen5_hid_description_header_parse(struct cyapa *cyapa, u8 *reg_data) cyapa->gen = CYAPA_GEN5; cyapa->state = CYAPA_STATE_GEN5_APP; } - } else if (length == GEN5_HID_DESCRIPTOR_SIZE && - resp_data[2] == GEN5_BL_HID_REPORT_ID && + } else if (length == PIP_HID_DESCRIPTOR_SIZE && + resp_data[2] == PIP_HID_BL_REPORT_ID && max_output_len == GEN5_BL_MAX_OUTPUT_LENGTH) { /* BL mode HID Description read. */ cyapa->gen = CYAPA_GEN5; cyapa->state = CYAPA_STATE_GEN5_BL; - } else if (length == GEN5_HID_DESCRIPTOR_SIZE && - (resp_data[GEN5_RESP_REPORT_ID_OFFSET] == - GEN5_APP_HID_REPORT_ID) && + } else if (length == PIP_HID_DESCRIPTOR_SIZE && + (resp_data[PIP_RESP_REPORT_ID_OFFSET] == + PIP_HID_APP_REPORT_ID) && max_output_len == GEN5_APP_MAX_OUTPUT_LENGTH) { /* APP mode HID Description read. */ cyapa->gen = CYAPA_GEN5; @@ -886,22 +827,22 @@ static int gen5_report_data_header_parse(struct cyapa *cyapa, u8 *reg_data) { int length; - length = get_unaligned_le16(®_data[GEN5_RESP_LENGTH_OFFSET]); - switch (reg_data[GEN5_RESP_REPORT_ID_OFFSET]) { - case GEN5_TOUCH_REPORT_ID: - if (length < GEN5_TOUCH_REPORT_HEAD_SIZE || - length > GEN5_TOUCH_REPORT_MAX_SIZE) + length = get_unaligned_le16(®_data[PIP_RESP_LENGTH_OFFSET]); + switch (reg_data[PIP_RESP_REPORT_ID_OFFSET]) { + case PIP_TOUCH_REPORT_ID: + if (length < PIP_TOUCH_REPORT_HEAD_SIZE || + length > PIP_TOUCH_REPORT_MAX_SIZE) return -EINVAL; break; - case GEN5_BTN_REPORT_ID: + case PIP_BTN_REPORT_ID: case GEN5_OLD_PUSH_BTN_REPORT_ID: - case GEN5_PUSH_BTN_REPORT_ID: - if (length < GEN5_BTN_REPORT_HEAD_SIZE || - length > GEN5_BTN_REPORT_MAX_SIZE) + case PIP_PUSH_BTN_REPORT_ID: + if (length < PIP_BTN_REPORT_HEAD_SIZE || + length > PIP_BTN_REPORT_MAX_SIZE) return -EINVAL; break; - case GEN5_WAKEUP_EVENT_REPORT_ID: - if (length != GEN5_WAKEUP_EVENT_SIZE) + case PIP_WAKEUP_EVENT_REPORT_ID: + if (length != PIP_WAKEUP_EVENT_SIZE) return -EINVAL; break; default: @@ -915,7 +856,7 @@ static int gen5_report_data_header_parse(struct cyapa *cyapa, u8 *reg_data) static int gen5_cmd_resp_header_parse(struct cyapa *cyapa, u8 *reg_data) { - struct cyapa_gen5_cmd_states *gen5_pip = &cyapa->cmd_states.gen5; + struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip; int length; int ret; @@ -924,15 +865,15 @@ static int gen5_cmd_resp_header_parse(struct cyapa *cyapa, u8 *reg_data) * otherwise Gen5 trackpad cannot response next command * or report any touch or button data. */ - length = get_unaligned_le16(®_data[GEN5_RESP_LENGTH_OFFSET]); - ret = cyapa_i2c_pip_read(cyapa, gen5_pip->empty_buf, length); + length = get_unaligned_le16(®_data[PIP_RESP_LENGTH_OFFSET]); + ret = cyapa_i2c_pip_read(cyapa, pip->empty_buf, length); if (ret != length) return ret < 0 ? ret : -EIO; - if (length == GEN5_RESP_LENGTH_SIZE) { + if (length == PIP_RESP_LENGTH_SIZE) { /* Previous command has read the data through out. */ - if (reg_data[GEN5_RESP_REPORT_ID_OFFSET] == - GEN5_BL_RESP_REPORT_ID) { + if (reg_data[PIP_RESP_REPORT_ID_OFFSET] == + PIP_BL_RESP_REPORT_ID) { /* Gen5 BL command response data detected */ cyapa->gen = CYAPA_GEN5; cyapa->state = CYAPA_STATE_GEN5_BL; @@ -941,21 +882,21 @@ static int gen5_cmd_resp_header_parse(struct cyapa *cyapa, u8 *reg_data) cyapa->gen = CYAPA_GEN5; cyapa->state = CYAPA_STATE_GEN5_APP; } - } else if ((gen5_pip->empty_buf[GEN5_RESP_REPORT_ID_OFFSET] == - GEN5_BL_RESP_REPORT_ID) && - (gen5_pip->empty_buf[GEN5_RESP_RSVD_OFFSET] == - GEN5_RESP_RSVD_KEY) && - (gen5_pip->empty_buf[GEN5_RESP_BL_SOP_OFFSET] == - GEN5_SOP_KEY) && - (gen5_pip->empty_buf[length - 1] == - GEN5_EOP_KEY)) { + } else if ((pip->empty_buf[PIP_RESP_REPORT_ID_OFFSET] == + PIP_BL_RESP_REPORT_ID) && + (pip->empty_buf[PIP_RESP_RSVD_OFFSET] == + PIP_RESP_RSVD_KEY) && + (pip->empty_buf[PIP_RESP_BL_SOP_OFFSET] == + PIP_SOP_KEY) && + (pip->empty_buf[length - 1] == + PIP_EOP_KEY)) { /* Gen5 BL command response data detected */ cyapa->gen = CYAPA_GEN5; cyapa->state = CYAPA_STATE_GEN5_BL; - } else if (gen5_pip->empty_buf[GEN5_RESP_REPORT_ID_OFFSET] == - GEN5_APP_RESP_REPORT_ID && - gen5_pip->empty_buf[GEN5_RESP_RSVD_OFFSET] == - GEN5_RESP_RSVD_KEY) { + } else if (pip->empty_buf[PIP_RESP_REPORT_ID_OFFSET] == + PIP_APP_RESP_REPORT_ID && + pip->empty_buf[PIP_RESP_RSVD_OFFSET] == + PIP_RESP_RSVD_KEY) { /* Gen5 APP command response data detected */ cyapa->gen = CYAPA_GEN5; cyapa->state = CYAPA_STATE_GEN5_APP; @@ -977,12 +918,12 @@ static int cyapa_gen5_state_parse(struct cyapa *cyapa, u8 *reg_data, int len) cyapa->state = CYAPA_STATE_NO_DEVICE; /* Parse based on Gen5 characteristic registers and bits */ - length = get_unaligned_le16(®_data[GEN5_RESP_LENGTH_OFFSET]); - if (length == 0 || length == GEN5_RESP_LENGTH_SIZE) { + length = get_unaligned_le16(®_data[PIP_RESP_LENGTH_OFFSET]); + if (length == 0 || length == PIP_RESP_LENGTH_SIZE) { gen5_idle_state_parse(cyapa); - } else if (length == GEN5_HID_DESCRIPTOR_SIZE && - (reg_data[2] == GEN5_BL_HID_REPORT_ID || - reg_data[2] == GEN5_APP_HID_REPORT_ID)) { + } else if (length == PIP_HID_DESCRIPTOR_SIZE && + (reg_data[2] == PIP_HID_BL_REPORT_ID || + reg_data[2] == PIP_HID_APP_REPORT_ID)) { gen5_hid_description_header_parse(cyapa, reg_data); } else if ((length == GEN5_APP_REPORT_DESCRIPTOR_SIZE || length == GEN5_APP_CONTRACT_REPORT_DESCRIPTOR_SIZE) && @@ -992,17 +933,17 @@ static int cyapa_gen5_state_parse(struct cyapa *cyapa, u8 *reg_data, int len) cyapa->state = CYAPA_STATE_GEN5_APP; } else if (length == GEN5_BL_REPORT_DESCRIPTOR_SIZE && reg_data[2] == GEN5_BL_REPORT_DESCRIPTOR_ID) { - /* 0x1D 0x00 0xFE is Gen5 BL report descriptior header. */ + /* 0x1D 0x00 0xFE is Gen5 BL report descriptor header. */ cyapa->gen = CYAPA_GEN5; cyapa->state = CYAPA_STATE_GEN5_BL; - } else if (reg_data[2] == GEN5_TOUCH_REPORT_ID || - reg_data[2] == GEN5_BTN_REPORT_ID || + } else if (reg_data[2] == PIP_TOUCH_REPORT_ID || + reg_data[2] == PIP_BTN_REPORT_ID || reg_data[2] == GEN5_OLD_PUSH_BTN_REPORT_ID || - reg_data[2] == GEN5_PUSH_BTN_REPORT_ID || - reg_data[2] == GEN5_WAKEUP_EVENT_REPORT_ID) { + reg_data[2] == PIP_PUSH_BTN_REPORT_ID || + reg_data[2] == PIP_WAKEUP_EVENT_REPORT_ID) { gen5_report_data_header_parse(cyapa, reg_data); - } else if (reg_data[2] == GEN5_BL_RESP_REPORT_ID || - reg_data[2] == GEN5_APP_RESP_REPORT_ID) { + } else if (reg_data[2] == PIP_BL_RESP_REPORT_ID || + reg_data[2] == PIP_APP_RESP_REPORT_ID) { gen5_cmd_resp_header_parse(cyapa, reg_data); } @@ -1023,14 +964,25 @@ static int cyapa_gen5_state_parse(struct cyapa *cyapa, u8 *reg_data, int len) return -EAGAIN; } -static int cyapa_gen5_bl_initiate(struct cyapa *cyapa, - const struct firmware *fw) +static struct cyapa_tsg_bin_image_data_record * +cyapa_get_image_record_data_num(const struct firmware *fw, + int *record_num) +{ + int head_size; + + head_size = fw->data[0] + 1; + *record_num = (fw->size - head_size) / + sizeof(struct cyapa_tsg_bin_image_data_record); + return (struct cyapa_tsg_bin_image_data_record *)&fw->data[head_size]; +} + +int cyapa_pip_bl_initiate(struct cyapa *cyapa, const struct firmware *fw) { - struct cyapa_tsg_bin_image *image; - struct gen5_bl_cmd_head *bl_cmd_head; - struct gen5_bl_packet_start *bl_packet_start; - struct gen5_bl_initiate_cmd_data *cmd_data; - struct gen5_bl_packet_end *bl_packet_end; + struct cyapa_tsg_bin_image_data_record *image_records; + struct pip_bl_cmd_head *bl_cmd_head; + struct pip_bl_packet_start *bl_packet_start; + struct pip_bl_initiate_cmd_data *cmd_data; + struct pip_bl_packet_end *bl_packet_end; u8 cmd[CYAPA_TSG_MAX_CMD_SIZE]; int cmd_len; u16 cmd_data_len; @@ -1046,30 +998,28 @@ static int cyapa_gen5_bl_initiate(struct cyapa *cyapa, cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); memset(cmd, 0, CYAPA_TSG_MAX_CMD_SIZE); - bl_cmd_head = (struct gen5_bl_cmd_head *)cmd; + bl_cmd_head = (struct pip_bl_cmd_head *)cmd; cmd_data_len = CYAPA_TSG_BL_KEY_SIZE + CYAPA_TSG_FLASH_MAP_BLOCK_SIZE; - cmd_len = sizeof(struct gen5_bl_cmd_head) + cmd_data_len + - sizeof(struct gen5_bl_packet_end); + cmd_len = sizeof(struct pip_bl_cmd_head) + cmd_data_len + + sizeof(struct pip_bl_packet_end); - put_unaligned_le16(GEN5_OUTPUT_REPORT_ADDR, &bl_cmd_head->addr); + put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR, &bl_cmd_head->addr); put_unaligned_le16(cmd_len - 2, &bl_cmd_head->length); - bl_cmd_head->report_id = GEN5_BL_CMD_REPORT_ID; + bl_cmd_head->report_id = PIP_BL_CMD_REPORT_ID; bl_packet_start = &bl_cmd_head->packet_start; - bl_packet_start->sop = GEN5_SOP_KEY; - bl_packet_start->cmd_code = GEN5_BL_CMD_INITIATE_BL; + bl_packet_start->sop = PIP_SOP_KEY; + bl_packet_start->cmd_code = PIP_BL_CMD_INITIATE_BL; /* 8 key bytes and 128 bytes block size */ put_unaligned_le16(cmd_data_len, &bl_packet_start->data_length); - cmd_data = (struct gen5_bl_initiate_cmd_data *)bl_cmd_head->data; - memcpy(cmd_data->key, cyapa_gen5_bl_cmd_key, CYAPA_TSG_BL_KEY_SIZE); + cmd_data = (struct pip_bl_initiate_cmd_data *)bl_cmd_head->data; + memcpy(cmd_data->key, cyapa_pip_bl_cmd_key, CYAPA_TSG_BL_KEY_SIZE); + + image_records = cyapa_get_image_record_data_num(fw, &records_num); - /* Copy 60 bytes Meta Data Row Parameters */ - image = (struct cyapa_tsg_bin_image *)fw->data; - records_num = (fw->size - sizeof(struct cyapa_tsg_bin_image_head)) / - sizeof(struct cyapa_tsg_bin_image_data_record); /* APP_INTEGRITY row is always the last row block */ - data = image->records[records_num - 1].record_data; + data = image_records[records_num - 1].record_data; memcpy(cmd_data->metadata_raw_parameter, data, CYAPA_TSG_FLASH_MAP_METADATA_SIZE); @@ -1077,47 +1027,47 @@ static int cyapa_gen5_bl_initiate(struct cyapa *cyapa, CYAPA_TSG_FLASH_MAP_METADATA_SIZE); put_unaligned_le16(meta_data_crc, &cmd_data->metadata_crc); - bl_packet_end = (struct gen5_bl_packet_end *)(bl_cmd_head->data + + bl_packet_end = (struct pip_bl_packet_end *)(bl_cmd_head->data + cmd_data_len); cmd_crc = crc_itu_t(0xffff, (u8 *)bl_packet_start, - sizeof(struct gen5_bl_packet_start) + cmd_data_len); + sizeof(struct pip_bl_packet_start) + cmd_data_len); put_unaligned_le16(cmd_crc, &bl_packet_end->crc); - bl_packet_end->eop = GEN5_EOP_KEY; + bl_packet_end->eop = PIP_EOP_KEY; resp_len = sizeof(resp_data); error = cyapa_i2c_pip_cmd_irq_sync(cyapa, cmd, cmd_len, resp_data, &resp_len, 12000, - cyapa_gen5_sort_tsg_pip_bl_resp_data, true); - if (error || resp_len != GEN5_BL_INITIATE_RESP_LEN || - resp_data[2] != GEN5_BL_RESP_REPORT_ID || - !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5])) + cyapa_sort_tsg_pip_bl_resp_data, true); + if (error || resp_len != PIP_BL_INITIATE_RESP_LEN || + resp_data[2] != PIP_BL_RESP_REPORT_ID || + !PIP_CMD_COMPLETE_SUCCESS(resp_data)) return error ? error : -EAGAIN; return 0; } -static bool cyapa_gen5_sort_bl_exit_data(struct cyapa *cyapa, u8 *buf, int len) +static bool cyapa_sort_pip_bl_exit_data(struct cyapa *cyapa, u8 *buf, int len) { - if (buf == NULL || len < GEN5_RESP_LENGTH_SIZE) + if (buf == NULL || len < PIP_RESP_LENGTH_SIZE) return false; if (buf[0] == 0 && buf[1] == 0) return true; /* Exit bootloader failed for some reason. */ - if (len == GEN5_BL_FAIL_EXIT_RESP_LEN && - buf[GEN5_RESP_REPORT_ID_OFFSET] == - GEN5_BL_RESP_REPORT_ID && - buf[GEN5_RESP_RSVD_OFFSET] == GEN5_RESP_RSVD_KEY && - buf[GEN5_RESP_BL_SOP_OFFSET] == GEN5_SOP_KEY && - buf[10] == GEN5_EOP_KEY) + if (len == PIP_BL_FAIL_EXIT_RESP_LEN && + buf[PIP_RESP_REPORT_ID_OFFSET] == + PIP_BL_RESP_REPORT_ID && + buf[PIP_RESP_RSVD_OFFSET] == PIP_RESP_RSVD_KEY && + buf[PIP_RESP_BL_SOP_OFFSET] == PIP_SOP_KEY && + buf[10] == PIP_EOP_KEY) return true; return false; } -static int cyapa_gen5_bl_exit(struct cyapa *cyapa) +int cyapa_pip_bl_exit(struct cyapa *cyapa) { u8 bl_gen5_bl_exit[] = { 0x04, 0x00, @@ -1132,13 +1082,13 @@ static int cyapa_gen5_bl_exit(struct cyapa *cyapa) error = cyapa_i2c_pip_cmd_irq_sync(cyapa, bl_gen5_bl_exit, sizeof(bl_gen5_bl_exit), resp_data, &resp_len, - 5000, cyapa_gen5_sort_bl_exit_data, false); + 5000, cyapa_sort_pip_bl_exit_data, false); if (error) return error; - if (resp_len == GEN5_BL_FAIL_EXIT_RESP_LEN || - resp_data[GEN5_RESP_REPORT_ID_OFFSET] == - GEN5_BL_RESP_REPORT_ID) + if (resp_len == PIP_BL_FAIL_EXIT_RESP_LEN || + resp_data[PIP_RESP_REPORT_ID_OFFSET] == + PIP_BL_RESP_REPORT_ID) return -EAGAIN; if (resp_data[0] == 0x00 && resp_data[1] == 0x00) @@ -1147,7 +1097,7 @@ static int cyapa_gen5_bl_exit(struct cyapa *cyapa) return -ENODEV; } -static int cyapa_gen5_bl_enter(struct cyapa *cyapa) +int cyapa_pip_bl_enter(struct cyapa *cyapa) { u8 cmd[] = { 0x04, 0x00, 0x05, 0x00, 0x2F, 0x00, 0x01 }; u8 resp_data[2]; @@ -1157,15 +1107,12 @@ static int cyapa_gen5_bl_enter(struct cyapa *cyapa) error = cyapa_poll_state(cyapa, 500); if (error < 0) return error; - if (cyapa->gen != CYAPA_GEN5) - return -EINVAL; - /* Already in Gen5 BL. Skipping exit. */ - if (cyapa->state == CYAPA_STATE_GEN5_BL) + /* Already in bootloader mode, Skipping exit. */ + if (cyapa_is_pip_bl_mode(cyapa)) return 0; - - if (cyapa->state != CYAPA_STATE_GEN5_APP) - return -EAGAIN; + else if (!cyapa_is_pip_app_mode(cyapa)) + return -EINVAL; /* Try to dump all buffered report data before any send command. */ cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); @@ -1179,39 +1126,38 @@ static int cyapa_gen5_bl_enter(struct cyapa *cyapa) error = cyapa_i2c_pip_cmd_irq_sync(cyapa, cmd, sizeof(cmd), resp_data, &resp_len, - 5000, cyapa_gen5_sort_application_launch_data, + 5000, cyapa_sort_pip_application_launch_data, true); if (error || resp_data[0] != 0x00 || resp_data[1] != 0x00) return error < 0 ? error : -EAGAIN; cyapa->operational = false; - cyapa->state = CYAPA_STATE_GEN5_BL; + if (cyapa->gen == CYAPA_GEN5) + cyapa->state = CYAPA_STATE_GEN5_BL; return 0; } -static int cyapa_gen5_check_fw(struct cyapa *cyapa, const struct firmware *fw) +int cyapa_pip_check_fw(struct cyapa *cyapa, const struct firmware *fw) { struct device *dev = &cyapa->client->dev; - const struct cyapa_tsg_bin_image *image = (const void *)fw->data; + struct cyapa_tsg_bin_image_data_record *image_records; const struct cyapa_tsg_bin_image_data_record *app_integrity; - const struct gen5_bl_metadata_row_params *metadata; - size_t flash_records_count; + const struct tsg_bl_metadata_row_params *metadata; + int flash_records_count; u32 fw_app_start, fw_upgrade_start; u16 fw_app_len, fw_upgrade_len; u16 app_crc; u16 app_integrity_crc; - int record_index; int i; - flash_records_count = (fw->size - - sizeof(struct cyapa_tsg_bin_image_head)) / - sizeof(struct cyapa_tsg_bin_image_data_record); + image_records = + cyapa_get_image_record_data_num(fw, &flash_records_count); /* * APP_INTEGRITY row is always the last row block, * and the row id must be 0x01ff. */ - app_integrity = &image->records[flash_records_count - 1]; + app_integrity = &image_records[flash_records_count - 1]; if (app_integrity->flash_array_id != 0x00 || get_unaligned_be16(&app_integrity->row_number) != 0x01ff) { @@ -1242,14 +1188,11 @@ static int cyapa_gen5_check_fw(struct cyapa *cyapa, const struct firmware *fw) return -EINVAL; } - /* - * Verify application image CRC - */ - record_index = fw_app_start / CYAPA_TSG_FW_ROW_SIZE - - CYAPA_TSG_IMG_START_ROW_NUM; + /* Verify application image CRC. */ app_crc = 0xffffU; for (i = 0; i < fw_app_len / CYAPA_TSG_FW_ROW_SIZE; i++) { - const u8 *data = image->records[record_index + i].record_data; + const u8 *data = image_records[i].record_data; + app_crc = crc_itu_t(app_crc, data, CYAPA_TSG_FW_ROW_SIZE); } @@ -1261,13 +1204,13 @@ static int cyapa_gen5_check_fw(struct cyapa *cyapa, const struct firmware *fw) return 0; } -static int cyapa_gen5_write_fw_block(struct cyapa *cyapa, +static int cyapa_pip_write_fw_block(struct cyapa *cyapa, struct cyapa_tsg_bin_image_data_record *flash_record) { - struct gen5_bl_cmd_head *bl_cmd_head; - struct gen5_bl_packet_start *bl_packet_start; - struct gen5_bl_flash_row_head *flash_row_head; - struct gen5_bl_packet_end *bl_packet_end; + struct pip_bl_cmd_head *bl_cmd_head; + struct pip_bl_packet_start *bl_packet_start; + struct tsg_bl_flash_row_head *flash_row_head; + struct pip_bl_packet_end *bl_packet_end; u8 cmd[CYAPA_TSG_MAX_CMD_SIZE]; u16 cmd_len; u8 flash_array_id; @@ -1286,71 +1229,68 @@ static int cyapa_gen5_write_fw_block(struct cyapa *cyapa, record_data = flash_record->record_data; memset(cmd, 0, CYAPA_TSG_MAX_CMD_SIZE); - bl_cmd_head = (struct gen5_bl_cmd_head *)cmd; + bl_cmd_head = (struct pip_bl_cmd_head *)cmd; bl_packet_start = &bl_cmd_head->packet_start; - cmd_len = sizeof(struct gen5_bl_cmd_head) + - sizeof(struct gen5_bl_flash_row_head) + + cmd_len = sizeof(struct pip_bl_cmd_head) + + sizeof(struct tsg_bl_flash_row_head) + CYAPA_TSG_FLASH_MAP_BLOCK_SIZE + - sizeof(struct gen5_bl_packet_end); + sizeof(struct pip_bl_packet_end); - put_unaligned_le16(GEN5_OUTPUT_REPORT_ADDR, &bl_cmd_head->addr); + put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR, &bl_cmd_head->addr); /* Don't include 2 bytes register address */ put_unaligned_le16(cmd_len - 2, &bl_cmd_head->length); - bl_cmd_head->report_id = GEN5_BL_CMD_REPORT_ID; - bl_packet_start->sop = GEN5_SOP_KEY; - bl_packet_start->cmd_code = GEN5_BL_CMD_PROGRAM_VERIFY_ROW; + bl_cmd_head->report_id = PIP_BL_CMD_REPORT_ID; + bl_packet_start->sop = PIP_SOP_KEY; + bl_packet_start->cmd_code = PIP_BL_CMD_PROGRAM_VERIFY_ROW; /* 1 (Flash Array ID) + 2 (Flash Row ID) + 128 (flash data) */ - data_len = sizeof(struct gen5_bl_flash_row_head) + record_len; + data_len = sizeof(struct tsg_bl_flash_row_head) + record_len; put_unaligned_le16(data_len, &bl_packet_start->data_length); - flash_row_head = (struct gen5_bl_flash_row_head *)bl_cmd_head->data; + flash_row_head = (struct tsg_bl_flash_row_head *)bl_cmd_head->data; flash_row_head->flash_array_id = flash_array_id; put_unaligned_le16(flash_row_id, &flash_row_head->flash_row_id); memcpy(flash_row_head->flash_data, record_data, record_len); - bl_packet_end = (struct gen5_bl_packet_end *)(bl_cmd_head->data + + bl_packet_end = (struct pip_bl_packet_end *)(bl_cmd_head->data + data_len); crc = crc_itu_t(0xffff, (u8 *)bl_packet_start, - sizeof(struct gen5_bl_packet_start) + data_len); + sizeof(struct pip_bl_packet_start) + data_len); put_unaligned_le16(crc, &bl_packet_end->crc); - bl_packet_end->eop = GEN5_EOP_KEY; + bl_packet_end->eop = PIP_EOP_KEY; resp_len = sizeof(resp_data); error = cyapa_i2c_pip_cmd_irq_sync(cyapa, cmd, cmd_len, resp_data, &resp_len, - 500, cyapa_gen5_sort_tsg_pip_bl_resp_data, true); - if (error || resp_len != GEN5_BL_BLOCK_WRITE_RESP_LEN || - resp_data[2] != GEN5_BL_RESP_REPORT_ID || - !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5])) + 500, cyapa_sort_tsg_pip_bl_resp_data, true); + if (error || resp_len != PIP_BL_BLOCK_WRITE_RESP_LEN || + resp_data[2] != PIP_BL_RESP_REPORT_ID || + !PIP_CMD_COMPLETE_SUCCESS(resp_data)) return error < 0 ? error : -EAGAIN; return 0; } -static int cyapa_gen5_do_fw_update(struct cyapa *cyapa, +int cyapa_pip_do_fw_update(struct cyapa *cyapa, const struct firmware *fw) { struct device *dev = &cyapa->client->dev; - struct cyapa_tsg_bin_image_data_record *flash_record; - struct cyapa_tsg_bin_image *image = - (struct cyapa_tsg_bin_image *)fw->data; + struct cyapa_tsg_bin_image_data_record *image_records; int flash_records_count; int i; int error; cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); - flash_records_count = - (fw->size - sizeof(struct cyapa_tsg_bin_image_head)) / - sizeof(struct cyapa_tsg_bin_image_data_record); + image_records = + cyapa_get_image_record_data_num(fw, &flash_records_count); + /* * The last flash row 0x01ff has been written through bl_initiate * command, so DO NOT write flash 0x01ff to trackpad device. */ for (i = 0; i < (flash_records_count - 1); i++) { - flash_record = &image->records[i]; - error = cyapa_gen5_write_fw_block(cyapa, flash_record); + error = cyapa_pip_write_fw_block(cyapa, &image_records[i]); if (error) { dev_err(dev, "%s: Gen5 FW update aborted: %d\n", __func__, error); @@ -1372,9 +1312,9 @@ static int cyapa_gen5_change_power_state(struct cyapa *cyapa, u8 power_state) resp_len = sizeof(resp_data); error = cyapa_i2c_pip_cmd_irq_sync(cyapa, cmd, sizeof(cmd), resp_data, &resp_len, - 500, cyapa_gen5_sort_tsg_pip_app_resp_data, false); + 500, cyapa_sort_tsg_pip_app_resp_data, false); if (error || !VALID_CMD_RESP_HEADER(resp_data, 0x08) || - !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5])) + !PIP_CMD_COMPLETE_SUCCESS(resp_data)) return error < 0 ? error : -EINVAL; return 0; @@ -1383,7 +1323,7 @@ static int cyapa_gen5_change_power_state(struct cyapa *cyapa, u8 power_state) static int cyapa_gen5_set_interval_time(struct cyapa *cyapa, u8 parameter_id, u16 interval_time) { - struct gen5_app_cmd_head *app_cmd_head; + struct pip_app_cmd_head *app_cmd_head; struct gen5_app_set_parameter_data *parameter_data; u8 cmd[CYAPA_TSG_MAX_CMD_SIZE]; int cmd_len; @@ -1393,10 +1333,10 @@ static int cyapa_gen5_set_interval_time(struct cyapa *cyapa, int error; memset(cmd, 0, CYAPA_TSG_MAX_CMD_SIZE); - app_cmd_head = (struct gen5_app_cmd_head *)cmd; + app_cmd_head = (struct pip_app_cmd_head *)cmd; parameter_data = (struct gen5_app_set_parameter_data *) app_cmd_head->parameter_data; - cmd_len = sizeof(struct gen5_app_cmd_head) + + cmd_len = sizeof(struct pip_app_cmd_head) + sizeof(struct gen5_app_set_parameter_data); switch (parameter_id) { @@ -1413,14 +1353,14 @@ static int cyapa_gen5_set_interval_time(struct cyapa *cyapa, return -EINVAL; } - put_unaligned_le16(GEN5_OUTPUT_REPORT_ADDR, &app_cmd_head->addr); + put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR, &app_cmd_head->addr); /* * Don't include unused parameter value bytes and * 2 bytes register address. */ put_unaligned_le16(cmd_len - (4 - parameter_size) - 2, &app_cmd_head->length); - app_cmd_head->report_id = GEN5_APP_CMD_REPORT_ID; + app_cmd_head->report_id = PIP_APP_CMD_REPORT_ID; app_cmd_head->cmd_code = GEN5_CMD_SET_PARAMETER; parameter_data->parameter_id = parameter_id; parameter_data->parameter_size = parameter_size; @@ -1428,7 +1368,7 @@ static int cyapa_gen5_set_interval_time(struct cyapa *cyapa, resp_len = sizeof(resp_data); error = cyapa_i2c_pip_cmd_irq_sync(cyapa, cmd, cmd_len, resp_data, &resp_len, - 500, cyapa_gen5_sort_tsg_pip_app_resp_data, false); + 500, cyapa_sort_tsg_pip_app_resp_data, false); if (error || resp_data[5] != parameter_id || resp_data[6] != parameter_size || !VALID_CMD_RESP_HEADER(resp_data, GEN5_CMD_SET_PARAMETER)) @@ -1440,7 +1380,7 @@ static int cyapa_gen5_set_interval_time(struct cyapa *cyapa, static int cyapa_gen5_get_interval_time(struct cyapa *cyapa, u8 parameter_id, u16 *interval_time) { - struct gen5_app_cmd_head *app_cmd_head; + struct pip_app_cmd_head *app_cmd_head; struct gen5_app_get_parameter_data *parameter_data; u8 cmd[CYAPA_TSG_MAX_CMD_SIZE]; int cmd_len; @@ -1451,10 +1391,10 @@ static int cyapa_gen5_get_interval_time(struct cyapa *cyapa, int error; memset(cmd, 0, CYAPA_TSG_MAX_CMD_SIZE); - app_cmd_head = (struct gen5_app_cmd_head *)cmd; + app_cmd_head = (struct pip_app_cmd_head *)cmd; parameter_data = (struct gen5_app_get_parameter_data *) app_cmd_head->parameter_data; - cmd_len = sizeof(struct gen5_app_cmd_head) + + cmd_len = sizeof(struct pip_app_cmd_head) + sizeof(struct gen5_app_get_parameter_data); *interval_time = 0; @@ -1472,17 +1412,17 @@ static int cyapa_gen5_get_interval_time(struct cyapa *cyapa, return -EINVAL; } - put_unaligned_le16(GEN5_HID_DESCRIPTOR_ADDR, &app_cmd_head->addr); + put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR, &app_cmd_head->addr); /* Don't include 2 bytes register address */ put_unaligned_le16(cmd_len - 2, &app_cmd_head->length); - app_cmd_head->report_id = GEN5_APP_CMD_REPORT_ID; + app_cmd_head->report_id = PIP_APP_CMD_REPORT_ID; app_cmd_head->cmd_code = GEN5_CMD_GET_PARAMETER; parameter_data->parameter_id = parameter_id; resp_len = sizeof(resp_data); error = cyapa_i2c_pip_cmd_irq_sync(cyapa, cmd, cmd_len, resp_data, &resp_len, - 500, cyapa_gen5_sort_tsg_pip_app_resp_data, false); + 500, cyapa_sort_tsg_pip_app_resp_data, false); if (error || resp_data[5] != parameter_id || resp_data[6] == 0 || !VALID_CMD_RESP_HEADER(resp_data, GEN5_CMD_GET_PARAMETER)) return error < 0 ? error : -EINVAL; @@ -1497,18 +1437,18 @@ static int cyapa_gen5_get_interval_time(struct cyapa *cyapa, static int cyapa_gen5_disable_pip_report(struct cyapa *cyapa) { - struct gen5_app_cmd_head *app_cmd_head; + struct pip_app_cmd_head *app_cmd_head; u8 cmd[10]; u8 resp_data[7]; int resp_len; int error; memset(cmd, 0, sizeof(cmd)); - app_cmd_head = (struct gen5_app_cmd_head *)cmd; + app_cmd_head = (struct pip_app_cmd_head *)cmd; - put_unaligned_le16(GEN5_HID_DESCRIPTOR_ADDR, &app_cmd_head->addr); + put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR, &app_cmd_head->addr); put_unaligned_le16(sizeof(cmd) - 2, &app_cmd_head->length); - app_cmd_head->report_id = GEN5_APP_CMD_REPORT_ID; + app_cmd_head->report_id = PIP_APP_CMD_REPORT_ID; app_cmd_head->cmd_code = GEN5_CMD_SET_PARAMETER; app_cmd_head->parameter_data[0] = GEN5_PARAMETER_DISABLE_PIP_REPORT; app_cmd_head->parameter_data[1] = 0x01; @@ -1516,7 +1456,7 @@ static int cyapa_gen5_disable_pip_report(struct cyapa *cyapa) resp_len = sizeof(resp_data); error = cyapa_i2c_pip_cmd_irq_sync(cyapa, cmd, sizeof(cmd), resp_data, &resp_len, - 500, cyapa_gen5_sort_tsg_pip_app_resp_data, false); + 500, cyapa_sort_tsg_pip_app_resp_data, false); if (error || resp_data[5] != GEN5_PARAMETER_DISABLE_PIP_REPORT || !VALID_CMD_RESP_HEADER(resp_data, GEN5_CMD_SET_PARAMETER) || resp_data[6] != 0x01) @@ -1525,19 +1465,19 @@ static int cyapa_gen5_disable_pip_report(struct cyapa *cyapa) return 0; } -static int cyapa_gen5_deep_sleep(struct cyapa *cyapa, u8 state) +int cyapa_pip_deep_sleep(struct cyapa *cyapa, u8 state) { u8 cmd[] = { 0x05, 0x00, 0x00, 0x08}; u8 resp_data[5]; int resp_len; int error; - cmd[2] = state & GEN5_DEEP_SLEEP_STATE_MASK; + cmd[2] = state & PIP_DEEP_SLEEP_STATE_MASK; resp_len = sizeof(resp_data); error = cyapa_i2c_pip_cmd_irq_sync(cyapa, cmd, sizeof(cmd), resp_data, &resp_len, - 500, cyapa_gen5_sort_deep_sleep_data, false); - if (error || ((resp_data[3] & GEN5_DEEP_SLEEP_STATE_MASK) != state)) + 500, cyapa_sort_pip_deep_sleep_data, false); + if (error || ((resp_data[3] & PIP_DEEP_SLEEP_STATE_MASK) != state)) return -EINVAL; return 0; @@ -1556,40 +1496,40 @@ static int cyapa_gen5_set_power_mode(struct cyapa *cyapa, /* Dump all the report data before do power mode commmands. */ cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); - if (GEN5_DEV_GET_PWR_STATE(cyapa) == UNINIT_PWR_MODE) { + if (PIP_DEV_GET_PWR_STATE(cyapa) == UNINIT_PWR_MODE) { /* * Assume TP in deep sleep mode when driver is loaded, * avoid driver unload and reload command IO issue caused by TP * has been set into deep sleep mode when unloading. */ - GEN5_DEV_SET_PWR_STATE(cyapa, PWR_MODE_OFF); + PIP_DEV_SET_PWR_STATE(cyapa, PWR_MODE_OFF); } - if (GEN5_DEV_UNINIT_SLEEP_TIME(cyapa) && - GEN5_DEV_GET_PWR_STATE(cyapa) != PWR_MODE_OFF) + if (PIP_DEV_UNINIT_SLEEP_TIME(cyapa) && + PIP_DEV_GET_PWR_STATE(cyapa) != PWR_MODE_OFF) if (cyapa_gen5_get_interval_time(cyapa, GEN5_PARAMETER_LP_INTRVL_ID, &cyapa->dev_sleep_time) != 0) - GEN5_DEV_SET_SLEEP_TIME(cyapa, UNINIT_SLEEP_TIME); + PIP_DEV_SET_SLEEP_TIME(cyapa, UNINIT_SLEEP_TIME); - if (GEN5_DEV_GET_PWR_STATE(cyapa) == power_mode) { + if (PIP_DEV_GET_PWR_STATE(cyapa) == power_mode) { if (power_mode == PWR_MODE_OFF || power_mode == PWR_MODE_FULL_ACTIVE || power_mode == PWR_MODE_BTN_ONLY || - GEN5_DEV_GET_SLEEP_TIME(cyapa) == sleep_time) { + PIP_DEV_GET_SLEEP_TIME(cyapa) == sleep_time) { /* Has in correct power mode state, early return. */ return 0; } } if (power_mode == PWR_MODE_OFF) { - error = cyapa_gen5_deep_sleep(cyapa, GEN5_DEEP_SLEEP_STATE_OFF); + error = cyapa_pip_deep_sleep(cyapa, PIP_DEEP_SLEEP_STATE_OFF); if (error) { dev_err(dev, "enter deep sleep fail: %d\n", error); return error; } - GEN5_DEV_SET_PWR_STATE(cyapa, PWR_MODE_OFF); + PIP_DEV_SET_PWR_STATE(cyapa, PWR_MODE_OFF); return 0; } @@ -1598,8 +1538,8 @@ static int cyapa_gen5_set_power_mode(struct cyapa *cyapa, * state directly, must be wake up from sleep firstly, then * continue to do next power sate change. */ - if (GEN5_DEV_GET_PWR_STATE(cyapa) == PWR_MODE_OFF) { - error = cyapa_gen5_deep_sleep(cyapa, GEN5_DEEP_SLEEP_STATE_ON); + if (PIP_DEV_GET_PWR_STATE(cyapa) == PWR_MODE_OFF) { + error = cyapa_pip_deep_sleep(cyapa, PIP_DEEP_SLEEP_STATE_ON); if (error) { dev_err(dev, "deep sleep wake fail: %d\n", error); return error; @@ -1614,7 +1554,7 @@ static int cyapa_gen5_set_power_mode(struct cyapa *cyapa, return error; } - GEN5_DEV_SET_PWR_STATE(cyapa, PWR_MODE_FULL_ACTIVE); + PIP_DEV_SET_PWR_STATE(cyapa, PWR_MODE_FULL_ACTIVE); } else if (power_mode == PWR_MODE_BTN_ONLY) { error = cyapa_gen5_change_power_state(cyapa, GEN5_POWER_STATE_BTN_ONLY); @@ -1623,19 +1563,19 @@ static int cyapa_gen5_set_power_mode(struct cyapa *cyapa, return error; } - GEN5_DEV_SET_PWR_STATE(cyapa, PWR_MODE_BTN_ONLY); + PIP_DEV_SET_PWR_STATE(cyapa, PWR_MODE_BTN_ONLY); } else { /* * Continue to change power mode even failed to set * interval time, it won't affect the power mode change. * except the sleep interval time is not correct. */ - if (GEN5_DEV_UNINIT_SLEEP_TIME(cyapa) || - sleep_time != GEN5_DEV_GET_SLEEP_TIME(cyapa)) + if (PIP_DEV_UNINIT_SLEEP_TIME(cyapa) || + sleep_time != PIP_DEV_GET_SLEEP_TIME(cyapa)) if (cyapa_gen5_set_interval_time(cyapa, GEN5_PARAMETER_LP_INTRVL_ID, sleep_time) == 0) - GEN5_DEV_SET_SLEEP_TIME(cyapa, sleep_time); + PIP_DEV_SET_SLEEP_TIME(cyapa, sleep_time); if (sleep_time <= GEN5_POWER_READY_MAX_INTRVL_TIME) power_state = GEN5_POWER_STATE_READY; @@ -1661,14 +1601,14 @@ static int cyapa_gen5_set_power_mode(struct cyapa *cyapa, cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); cyapa_gen5_disable_pip_report(cyapa); - GEN5_DEV_SET_PWR_STATE(cyapa, + PIP_DEV_SET_PWR_STATE(cyapa, cyapa_sleep_time_to_pwr_cmd(sleep_time)); } return 0; } -static int cyapa_gen5_resume_scanning(struct cyapa *cyapa) +int cyapa_pip_resume_scanning(struct cyapa *cyapa) { u8 cmd[] = { 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x04 }; u8 resp_data[6]; @@ -1682,7 +1622,7 @@ static int cyapa_gen5_resume_scanning(struct cyapa *cyapa) error = cyapa_i2c_pip_cmd_irq_sync(cyapa, cmd, sizeof(cmd), resp_data, &resp_len, - 500, cyapa_gen5_sort_tsg_pip_app_resp_data, true); + 500, cyapa_sort_tsg_pip_app_resp_data, true); if (error || !VALID_CMD_RESP_HEADER(resp_data, 0x04)) return -EINVAL; @@ -1692,7 +1632,7 @@ static int cyapa_gen5_resume_scanning(struct cyapa *cyapa) return 0; } -static int cyapa_gen5_suspend_scanning(struct cyapa *cyapa) +int cyapa_pip_suspend_scanning(struct cyapa *cyapa) { u8 cmd[] = { 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x03 }; u8 resp_data[6]; @@ -1706,7 +1646,7 @@ static int cyapa_gen5_suspend_scanning(struct cyapa *cyapa) error = cyapa_i2c_pip_cmd_irq_sync(cyapa, cmd, sizeof(cmd), resp_data, &resp_len, - 500, cyapa_gen5_sort_tsg_pip_app_resp_data, true); + 500, cyapa_sort_tsg_pip_app_resp_data, true); if (error || !VALID_CMD_RESP_HEADER(resp_data, 0x03)) return -EINVAL; @@ -1716,10 +1656,10 @@ static int cyapa_gen5_suspend_scanning(struct cyapa *cyapa) return 0; } -static int cyapa_gen5_calibrate_pwcs(struct cyapa *cyapa, +static int cyapa_pip_calibrate_pwcs(struct cyapa *cyapa, u8 calibrate_sensing_mode_type) { - struct gen5_app_cmd_head *app_cmd_head; + struct pip_app_cmd_head *app_cmd_head; u8 cmd[8]; u8 resp_data[6]; int resp_len; @@ -1729,25 +1669,25 @@ static int cyapa_gen5_calibrate_pwcs(struct cyapa *cyapa, cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); memset(cmd, 0, sizeof(cmd)); - app_cmd_head = (struct gen5_app_cmd_head *)cmd; - put_unaligned_le16(GEN5_OUTPUT_REPORT_ADDR, &app_cmd_head->addr); + app_cmd_head = (struct pip_app_cmd_head *)cmd; + put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR, &app_cmd_head->addr); put_unaligned_le16(sizeof(cmd) - 2, &app_cmd_head->length); - app_cmd_head->report_id = GEN5_APP_CMD_REPORT_ID; - app_cmd_head->cmd_code = GEN5_CMD_CALIBRATE; + app_cmd_head->report_id = PIP_APP_CMD_REPORT_ID; + app_cmd_head->cmd_code = PIP_CMD_CALIBRATE; app_cmd_head->parameter_data[0] = calibrate_sensing_mode_type; resp_len = sizeof(resp_data); error = cyapa_i2c_pip_cmd_irq_sync(cyapa, cmd, sizeof(cmd), resp_data, &resp_len, - 5000, cyapa_gen5_sort_tsg_pip_app_resp_data, true); - if (error || !VALID_CMD_RESP_HEADER(resp_data, GEN5_CMD_CALIBRATE) || - !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5])) + 5000, cyapa_sort_tsg_pip_app_resp_data, true); + if (error || !VALID_CMD_RESP_HEADER(resp_data, PIP_CMD_CALIBRATE) || + !PIP_CMD_COMPLETE_SUCCESS(resp_data)) return error < 0 ? error : -EAGAIN; return 0; } -static ssize_t cyapa_gen5_do_calibrate(struct device *dev, +ssize_t cyapa_pip_do_calibrate(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { @@ -1755,25 +1695,25 @@ static ssize_t cyapa_gen5_do_calibrate(struct device *dev, int error, calibrate_error; /* 1. Suspend Scanning*/ - error = cyapa_gen5_suspend_scanning(cyapa); + error = cyapa_pip_suspend_scanning(cyapa); if (error) return error; /* 2. Do mutual capacitance fine calibrate. */ - calibrate_error = cyapa_gen5_calibrate_pwcs(cyapa, - CYAPA_SENSING_MODE_MUTUAL_CAP_FINE); + calibrate_error = cyapa_pip_calibrate_pwcs(cyapa, + PIP_SENSING_MODE_MUTUAL_CAP_FINE); if (calibrate_error) goto resume_scanning; /* 3. Do self capacitance calibrate. */ - calibrate_error = cyapa_gen5_calibrate_pwcs(cyapa, - CYAPA_SENSING_MODE_SELF_CAP); + calibrate_error = cyapa_pip_calibrate_pwcs(cyapa, + PIP_SENSING_MODE_SELF_CAP); if (calibrate_error) goto resume_scanning; resume_scanning: /* 4. Resume Scanning*/ - error = cyapa_gen5_resume_scanning(cyapa); + error = cyapa_pip_resume_scanning(cyapa); if (error || calibrate_error) return error ? error : calibrate_error; @@ -1856,7 +1796,7 @@ static void cyapa_gen5_guess_electrodes(struct cyapa *cyapa, * If the input value of @data_size is not 0, than means read the mutual or * self local PWC data. The @idac_max, @idac_min and @idac_ave are used to * return the max, min and average value of the mutual or self local PWC data. - * Note, in order to raed mutual local PWC data, must read invoke this function + * Note, in order to read mutual local PWC data, must read invoke this function * to read the mutual global idac data firstly to set the correct Rx number * value, otherwise, the read mutual idac and PWC data may not correct. */ @@ -1864,7 +1804,7 @@ static int cyapa_gen5_read_idac_data(struct cyapa *cyapa, u8 cmd_code, u8 idac_data_type, int *data_size, int *idac_max, int *idac_min, int *idac_ave) { - struct gen5_app_cmd_head *cmd_head; + struct pip_app_cmd_head *cmd_head; u8 cmd[12]; u8 resp_data[256]; int resp_len; @@ -1879,7 +1819,7 @@ static int cyapa_gen5_read_idac_data(struct cyapa *cyapa, int i; int error; - if (cmd_code != GEN5_CMD_RETRIEVE_DATA_STRUCTURE || + if (cmd_code != PIP_RETRIEVE_DATA_STRUCTURE || (idac_data_type != GEN5_RETRIEVE_MUTUAL_PWC_DATA && idac_data_type != GEN5_RETRIEVE_SELF_CAP_PWC_DATA) || !data_size || !idac_max || !idac_min || !idac_ave) @@ -1935,10 +1875,10 @@ static int cyapa_gen5_read_idac_data(struct cyapa *cyapa, } memset(cmd, 0, sizeof(cmd)); - cmd_head = (struct gen5_app_cmd_head *)cmd; - put_unaligned_le16(GEN5_OUTPUT_REPORT_ADDR, &cmd_head->addr); + cmd_head = (struct pip_app_cmd_head *)cmd; + put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR, &cmd_head->addr); put_unaligned_le16(sizeof(cmd) - 2, &cmd_head->length); - cmd_head->report_id = GEN5_APP_CMD_REPORT_ID; + cmd_head->report_id = PIP_APP_CMD_REPORT_ID; cmd_head->cmd_code = cmd_code; do { read_elements = (256 - GEN5_RESP_DATA_STRUCTURE_OFFSET) / @@ -1953,11 +1893,11 @@ static int cyapa_gen5_read_idac_data(struct cyapa *cyapa, error = cyapa_i2c_pip_cmd_irq_sync(cyapa, cmd, sizeof(cmd), resp_data, &resp_len, - 500, cyapa_gen5_sort_tsg_pip_app_resp_data, + 500, cyapa_sort_tsg_pip_app_resp_data, true); if (error || resp_len < GEN5_RESP_DATA_STRUCTURE_OFFSET || !VALID_CMD_RESP_HEADER(resp_data, cmd_code) || - !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5]) || + !PIP_CMD_COMPLETE_SUCCESS(resp_data) || resp_data[6] != idac_data_type) return (error < 0) ? error : -EAGAIN; read_len = get_unaligned_le16(&resp_data[7]); @@ -1997,7 +1937,7 @@ static int cyapa_gen5_read_idac_data(struct cyapa *cyapa, tmp_count < cyapa->aligned_electrodes_rx && read_global_idac) { /* - * The value gap betwen global and local mutual + * The value gap between global and local mutual * idac data must bigger than 50%. * Normally, global value bigger than 50, * local values less than 10. @@ -2061,7 +2001,7 @@ static int cyapa_gen5_read_mutual_idac_data(struct cyapa *cyapa, data_size = 0; error = cyapa_gen5_read_idac_data(cyapa, - GEN5_CMD_RETRIEVE_DATA_STRUCTURE, + PIP_RETRIEVE_DATA_STRUCTURE, GEN5_RETRIEVE_MUTUAL_PWC_DATA, &data_size, gidac_mutual_max, gidac_mutual_min, gidac_mutual_ave); @@ -2069,7 +2009,7 @@ static int cyapa_gen5_read_mutual_idac_data(struct cyapa *cyapa, return error; error = cyapa_gen5_read_idac_data(cyapa, - GEN5_CMD_RETRIEVE_DATA_STRUCTURE, + PIP_RETRIEVE_DATA_STRUCTURE, GEN5_RETRIEVE_MUTUAL_PWC_DATA, &data_size, lidac_mutual_max, lidac_mutual_min, lidac_mutual_ave); @@ -2088,7 +2028,7 @@ static int cyapa_gen5_read_self_idac_data(struct cyapa *cyapa, data_size = 0; error = cyapa_gen5_read_idac_data(cyapa, - GEN5_CMD_RETRIEVE_DATA_STRUCTURE, + PIP_RETRIEVE_DATA_STRUCTURE, GEN5_RETRIEVE_SELF_CAP_PWC_DATA, &data_size, lidac_self_max, lidac_self_min, lidac_self_ave); @@ -2098,7 +2038,7 @@ static int cyapa_gen5_read_self_idac_data(struct cyapa *cyapa, *gidac_self_tx = *lidac_self_min; error = cyapa_gen5_read_idac_data(cyapa, - GEN5_CMD_RETRIEVE_DATA_STRUCTURE, + PIP_RETRIEVE_DATA_STRUCTURE, GEN5_RETRIEVE_SELF_CAP_PWC_DATA, &data_size, lidac_self_max, lidac_self_min, lidac_self_ave); @@ -2107,27 +2047,27 @@ static int cyapa_gen5_read_self_idac_data(struct cyapa *cyapa, static ssize_t cyapa_gen5_execute_panel_scan(struct cyapa *cyapa) { - struct gen5_app_cmd_head *app_cmd_head; + struct pip_app_cmd_head *app_cmd_head; u8 cmd[7]; u8 resp_data[6]; int resp_len; int error; memset(cmd, 0, sizeof(cmd)); - app_cmd_head = (struct gen5_app_cmd_head *)cmd; - put_unaligned_le16(GEN5_OUTPUT_REPORT_ADDR, &app_cmd_head->addr); + app_cmd_head = (struct pip_app_cmd_head *)cmd; + put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR, &app_cmd_head->addr); put_unaligned_le16(sizeof(cmd) - 2, &app_cmd_head->length); - app_cmd_head->report_id = GEN5_APP_CMD_REPORT_ID; + app_cmd_head->report_id = PIP_APP_CMD_REPORT_ID; app_cmd_head->cmd_code = GEN5_CMD_EXECUTE_PANEL_SCAN; resp_len = sizeof(resp_data); error = cyapa_i2c_pip_cmd_irq_sync(cyapa, cmd, sizeof(cmd), resp_data, &resp_len, - 500, cyapa_gen5_sort_tsg_pip_app_resp_data, true); + 500, cyapa_sort_tsg_pip_app_resp_data, true); if (error || resp_len != sizeof(resp_data) || !VALID_CMD_RESP_HEADER(resp_data, GEN5_CMD_EXECUTE_PANEL_SCAN) || - !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5])) + !PIP_CMD_COMPLETE_SUCCESS(resp_data)) return error ? error : -EAGAIN; return 0; @@ -2138,7 +2078,7 @@ static int cyapa_gen5_read_panel_scan_raw_data(struct cyapa *cyapa, int *raw_data_max, int *raw_data_min, int *raw_data_ave, u8 *buffer) { - struct gen5_app_cmd_head *app_cmd_head; + struct pip_app_cmd_head *app_cmd_head; struct gen5_retrieve_panel_scan_data *panel_sacn_data; u8 cmd[12]; u8 resp_data[256]; /* Max bytes can transfer one time. */ @@ -2166,10 +2106,10 @@ static int cyapa_gen5_read_panel_scan_raw_data(struct cyapa *cyapa, /* Assume max element size is 4 currently. */ read_elements = (256 - GEN5_RESP_DATA_STRUCTURE_OFFSET) / 4; read_len = read_elements * 4; - app_cmd_head = (struct gen5_app_cmd_head *)cmd; - put_unaligned_le16(GEN5_OUTPUT_REPORT_ADDR, &app_cmd_head->addr); + app_cmd_head = (struct pip_app_cmd_head *)cmd; + put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR, &app_cmd_head->addr); put_unaligned_le16(sizeof(cmd) - 2, &app_cmd_head->length); - app_cmd_head->report_id = GEN5_APP_CMD_REPORT_ID; + app_cmd_head->report_id = PIP_APP_CMD_REPORT_ID; app_cmd_head->cmd_code = cmd_code; panel_sacn_data = (struct gen5_retrieve_panel_scan_data *) app_cmd_head->parameter_data; @@ -2183,10 +2123,10 @@ static int cyapa_gen5_read_panel_scan_raw_data(struct cyapa *cyapa, error = cyapa_i2c_pip_cmd_irq_sync(cyapa, cmd, sizeof(cmd), resp_data, &resp_len, - 500, cyapa_gen5_sort_tsg_pip_app_resp_data, true); + 500, cyapa_sort_tsg_pip_app_resp_data, true); if (error || resp_len < GEN5_RESP_DATA_STRUCTURE_OFFSET || !VALID_CMD_RESP_HEADER(resp_data, cmd_code) || - !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5]) || + !PIP_CMD_COMPLETE_SUCCESS(resp_data) || resp_data[6] != raw_data_type) return error ? error : -EAGAIN; @@ -2245,11 +2185,11 @@ static ssize_t cyapa_gen5_show_baseline(struct device *dev, int error, resume_error; int size; - if (cyapa->state != CYAPA_STATE_GEN5_APP) + if (!cyapa_is_pip_app_mode(cyapa)) return -EBUSY; /* 1. Suspend Scanning*/ - error = cyapa_gen5_suspend_scanning(cyapa); + error = cyapa_pip_suspend_scanning(cyapa); if (error) return error; @@ -2270,7 +2210,7 @@ static ssize_t cyapa_gen5_show_baseline(struct device *dev, if (error) goto resume_scanning; - /* 4. Execuate panel scan. It must be executed before read data. */ + /* 4. Execute panel scan. It must be executed before read data. */ error = cyapa_gen5_execute_panel_scan(cyapa); if (error) goto resume_scanning; @@ -2343,7 +2283,7 @@ static ssize_t cyapa_gen5_show_baseline(struct device *dev, resume_scanning: /* 11. Resume Scanning*/ - resume_error = cyapa_gen5_resume_scanning(cyapa); + resume_error = cyapa_pip_resume_scanning(cyapa); if (resume_error || error) return resume_error ? resume_error : error; @@ -2364,7 +2304,7 @@ resume_scanning: return size; } -static bool cyapa_gen5_sort_system_info_data(struct cyapa *cyapa, +bool cyapa_pip_sort_system_info_data(struct cyapa *cyapa, u8 *buf, int len) { /* Check the report id and command code */ @@ -2376,20 +2316,17 @@ static bool cyapa_gen5_sort_system_info_data(struct cyapa *cyapa, static int cyapa_gen5_bl_query_data(struct cyapa *cyapa) { - u8 bl_query_data_cmd[] = { 0x04, 0x00, 0x0b, 0x00, 0x40, 0x00, - 0x01, 0x3c, 0x00, 0x00, 0xb0, 0x42, 0x17 - }; - u8 resp_data[GEN5_BL_READ_APP_INFO_RESP_LEN]; + u8 resp_data[PIP_BL_APP_INFO_RESP_LENGTH]; int resp_len; int error; - resp_len = GEN5_BL_READ_APP_INFO_RESP_LEN; + resp_len = sizeof(resp_data); error = cyapa_i2c_pip_cmd_irq_sync(cyapa, - bl_query_data_cmd, sizeof(bl_query_data_cmd), + pip_bl_read_app_info, PIP_BL_READ_APP_INFO_CMD_LENGTH, resp_data, &resp_len, - 500, cyapa_gen5_sort_tsg_pip_bl_resp_data, false); - if (error || resp_len != GEN5_BL_READ_APP_INFO_RESP_LEN || - !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5])) + 500, cyapa_sort_tsg_pip_bl_resp_data, false); + if (error || resp_len < PIP_BL_APP_INFO_RESP_LENGTH || + !PIP_CMD_COMPLETE_SUCCESS(resp_data)) return error ? error : -EIO; memcpy(&cyapa->product_id[0], &resp_data[8], 5); @@ -2407,25 +2344,22 @@ static int cyapa_gen5_bl_query_data(struct cyapa *cyapa) static int cyapa_gen5_get_query_data(struct cyapa *cyapa) { - u8 get_system_information[] = { - 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x02 - }; - u8 resp_data[71]; + u8 resp_data[PIP_READ_SYS_INFO_RESP_LENGTH]; int resp_len; u16 product_family; int error; resp_len = sizeof(resp_data); error = cyapa_i2c_pip_cmd_irq_sync(cyapa, - get_system_information, sizeof(get_system_information), + pip_read_sys_info, PIP_READ_SYS_INFO_CMD_LENGTH, resp_data, &resp_len, - 2000, cyapa_gen5_sort_system_info_data, false); + 2000, cyapa_pip_sort_system_info_data, false); if (error || resp_len < sizeof(resp_data)) return error ? error : -EIO; product_family = get_unaligned_le16(&resp_data[7]); - if ((product_family & GEN5_PRODUCT_FAMILY_MASK) != - GEN5_PRODUCT_FAMILY_TRACKPAD) + if ((product_family & PIP_PRODUCT_FAMILY_MASK) != + PIP_PRODUCT_FAMILY_TRACKPAD) return -EINVAL; cyapa->fw_maj_ver = resp_data[15]; @@ -2472,9 +2406,9 @@ static int cyapa_gen5_do_operational_check(struct cyapa *cyapa) switch (cyapa->state) { case CYAPA_STATE_GEN5_BL: - error = cyapa_gen5_bl_exit(cyapa); + error = cyapa_pip_bl_exit(cyapa); if (error) { - /* Rry to update trackpad product information. */ + /* Try to update trackpad product information. */ cyapa_gen5_bl_query_data(cyapa); goto out; } @@ -2486,7 +2420,7 @@ static int cyapa_gen5_do_operational_check(struct cyapa *cyapa) * If trackpad device in deep sleep mode, * the app command will fail. * So always try to reset trackpad device to full active when - * the device state is requeried. + * the device state is required. */ error = cyapa_gen5_set_power_mode(cyapa, PWR_MODE_FULL_ACTIVE, 0); @@ -2518,14 +2452,14 @@ out: * Return false, do not continue process * Return true, continue process. */ -static bool cyapa_gen5_irq_cmd_handler(struct cyapa *cyapa) +bool cyapa_pip_irq_cmd_handler(struct cyapa *cyapa) { - struct cyapa_gen5_cmd_states *gen5_pip = &cyapa->cmd_states.gen5; + struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip; int length; - if (atomic_read(&gen5_pip->cmd_issued)) { + if (atomic_read(&pip->cmd_issued)) { /* Polling command response data. */ - if (gen5_pip->is_irq_mode == false) + if (pip->is_irq_mode == false) return false; /* @@ -2533,59 +2467,64 @@ static bool cyapa_gen5_irq_cmd_handler(struct cyapa *cyapa) * these output data may caused by user put finger on * trackpad when host waiting the command response. */ - cyapa_i2c_pip_read(cyapa, gen5_pip->irq_cmd_buf, - GEN5_RESP_LENGTH_SIZE); - length = get_unaligned_le16(gen5_pip->irq_cmd_buf); - length = (length <= GEN5_RESP_LENGTH_SIZE) ? - GEN5_RESP_LENGTH_SIZE : length; - if (length > GEN5_RESP_LENGTH_SIZE) + cyapa_i2c_pip_read(cyapa, pip->irq_cmd_buf, + PIP_RESP_LENGTH_SIZE); + length = get_unaligned_le16(pip->irq_cmd_buf); + length = (length <= PIP_RESP_LENGTH_SIZE) ? + PIP_RESP_LENGTH_SIZE : length; + if (length > PIP_RESP_LENGTH_SIZE) cyapa_i2c_pip_read(cyapa, - gen5_pip->irq_cmd_buf, length); - - if (!(gen5_pip->resp_sort_func && - gen5_pip->resp_sort_func(cyapa, - gen5_pip->irq_cmd_buf, length))) { + pip->irq_cmd_buf, length); + if (!(pip->resp_sort_func && + pip->resp_sort_func(cyapa, + pip->irq_cmd_buf, length))) { /* - * Work around the Gen5 V1 firmware - * that does not assert interrupt signalling - * that command response is ready if user - * keeps touching the trackpad while command - * is sent to the device. + * Cover the Gen5 V1 firmware issue. + * The issue is no interrupt would be asserted from + * trackpad device to host for the command response + * ready event. Because when there was a finger touch + * on trackpad device, and the firmware output queue + * won't be empty (always with touch report data), so + * the interrupt signal won't be asserted again until + * the output queue was previous emptied. + * This issue would happen in the scenario that + * user always has his/her fingers touched on the + * trackpad device during system booting/rebooting. */ length = 0; - if (gen5_pip->resp_len) - length = *gen5_pip->resp_len; + if (pip->resp_len) + length = *pip->resp_len; cyapa_empty_pip_output_data(cyapa, - gen5_pip->resp_data, + pip->resp_data, &length, - gen5_pip->resp_sort_func); - if (gen5_pip->resp_len && length != 0) { - *gen5_pip->resp_len = length; - atomic_dec(&gen5_pip->cmd_issued); - complete(&gen5_pip->cmd_ready); + pip->resp_sort_func); + if (pip->resp_len && length != 0) { + *pip->resp_len = length; + atomic_dec(&pip->cmd_issued); + complete(&pip->cmd_ready); } return false; } - if (gen5_pip->resp_data && gen5_pip->resp_len) { - *gen5_pip->resp_len = (*gen5_pip->resp_len < length) ? - *gen5_pip->resp_len : length; - memcpy(gen5_pip->resp_data, gen5_pip->irq_cmd_buf, - *gen5_pip->resp_len); + if (pip->resp_data && pip->resp_len) { + *pip->resp_len = (*pip->resp_len < length) ? + *pip->resp_len : length; + memcpy(pip->resp_data, pip->irq_cmd_buf, + *pip->resp_len); } - atomic_dec(&gen5_pip->cmd_issued); - complete(&gen5_pip->cmd_ready); + atomic_dec(&pip->cmd_issued); + complete(&pip->cmd_ready); return false; } return true; } -static void cyapa_gen5_report_buttons(struct cyapa *cyapa, - const struct cyapa_gen5_report_data *report_data) +static void cyapa_pip_report_buttons(struct cyapa *cyapa, + const struct cyapa_pip_report_data *report_data) { struct input_dev *input = cyapa->input; - u8 buttons = report_data->report_head[GEN5_BUTTONS_OFFSET]; + u8 buttons = report_data->report_head[PIP_BUTTONS_OFFSET]; buttons = (buttons << CAPABILITY_BTN_SHIFT) & CAPABILITY_BTN_MASK; @@ -2605,12 +2544,12 @@ static void cyapa_gen5_report_buttons(struct cyapa *cyapa, input_sync(input); } -static void cyapa_gen5_report_slot_data(struct cyapa *cyapa, - const struct cyapa_gen5_touch_record *touch) +static void cyapa_pip_report_slot_data(struct cyapa *cyapa, + const struct cyapa_pip_touch_record *touch) { struct input_dev *input = cyapa->input; - u8 event_id = GEN5_GET_EVENT_ID(touch->touch_tip_event_id); - int slot = GEN5_GET_TOUCH_ID(touch->touch_tip_event_id); + u8 event_id = PIP_GET_EVENT_ID(touch->touch_tip_event_id); + int slot = PIP_GET_TOUCH_ID(touch->touch_tip_event_id); int x, y; if (event_id == RECORD_EVENT_LIFTOFF) @@ -2621,10 +2560,10 @@ static void cyapa_gen5_report_slot_data(struct cyapa *cyapa, x = (touch->x_hi << 8) | touch->x_lo; if (cyapa->x_origin) x = cyapa->max_abs_x - x; - input_report_abs(input, ABS_MT_POSITION_X, x); y = (touch->y_hi << 8) | touch->y_lo; if (cyapa->y_origin) y = cyapa->max_abs_y - y; + input_report_abs(input, ABS_MT_POSITION_X, x); input_report_abs(input, ABS_MT_POSITION_Y, y); input_report_abs(input, ABS_MT_PRESSURE, touch->z); @@ -2642,50 +2581,49 @@ static void cyapa_gen5_report_slot_data(struct cyapa *cyapa, touch->orientation); } -static void cyapa_gen5_report_touches(struct cyapa *cyapa, - const struct cyapa_gen5_report_data *report_data) +static void cyapa_pip_report_touches(struct cyapa *cyapa, + const struct cyapa_pip_report_data *report_data) { struct input_dev *input = cyapa->input; unsigned int touch_num; int i; - touch_num = report_data->report_head[GEN5_NUMBER_OF_TOUCH_OFFSET] & - GEN5_NUMBER_OF_TOUCH_MASK; + touch_num = report_data->report_head[PIP_NUMBER_OF_TOUCH_OFFSET] & + PIP_NUMBER_OF_TOUCH_MASK; for (i = 0; i < touch_num; i++) - cyapa_gen5_report_slot_data(cyapa, + cyapa_pip_report_slot_data(cyapa, &report_data->touch_records[i]); input_mt_sync_frame(input); input_sync(input); } -static int cyapa_gen5_irq_handler(struct cyapa *cyapa) +int cyapa_pip_irq_handler(struct cyapa *cyapa) { struct device *dev = &cyapa->client->dev; - struct cyapa_gen5_report_data report_data; - int ret; - u8 report_id; + struct cyapa_pip_report_data report_data; unsigned int report_len; + u8 report_id; + int ret; - if (cyapa->gen != CYAPA_GEN5 || - cyapa->state != CYAPA_STATE_GEN5_APP) { + if (!cyapa_is_pip_app_mode(cyapa)) { dev_err(dev, "invalid device state, gen=%d, state=0x%02x\n", cyapa->gen, cyapa->state); return -EINVAL; } ret = cyapa_i2c_pip_read(cyapa, (u8 *)&report_data, - GEN5_RESP_LENGTH_SIZE); - if (ret != GEN5_RESP_LENGTH_SIZE) { + PIP_RESP_LENGTH_SIZE); + if (ret != PIP_RESP_LENGTH_SIZE) { dev_err(dev, "failed to read length bytes, (%d)\n", ret); return -EINVAL; } report_len = get_unaligned_le16( - &report_data.report_head[GEN5_RESP_LENGTH_OFFSET]); - if (report_len < GEN5_RESP_LENGTH_SIZE) { - /* Invliad length or internal reset happened. */ + &report_data.report_head[PIP_RESP_LENGTH_OFFSET]); + if (report_len < PIP_RESP_LENGTH_SIZE) { + /* Invalid length or internal reset happened. */ dev_err(dev, "invalid report_len=%d. bytes: %02x %02x\n", report_len, report_data.report_head[0], report_data.report_head[1]); @@ -2693,7 +2631,7 @@ static int cyapa_gen5_irq_handler(struct cyapa *cyapa) } /* Idle, no data for report. */ - if (report_len == GEN5_RESP_LENGTH_SIZE) + if (report_len == PIP_RESP_LENGTH_SIZE) return 0; ret = cyapa_i2c_pip_read(cyapa, (u8 *)&report_data, report_len); @@ -2703,70 +2641,71 @@ static int cyapa_gen5_irq_handler(struct cyapa *cyapa) return -EINVAL; } - report_id = report_data.report_head[GEN5_RESP_REPORT_ID_OFFSET]; - if (report_id == GEN5_WAKEUP_EVENT_REPORT_ID && - report_len == GEN5_WAKEUP_EVENT_SIZE) { + report_id = report_data.report_head[PIP_RESP_REPORT_ID_OFFSET]; + if (report_id == PIP_WAKEUP_EVENT_REPORT_ID && + report_len == PIP_WAKEUP_EVENT_SIZE) { /* * Device wake event from deep sleep mode for touch. * This interrupt event is used to wake system up. */ return 0; - } else if (report_id != GEN5_TOUCH_REPORT_ID && - report_id != GEN5_BTN_REPORT_ID && + } else if (report_id != PIP_TOUCH_REPORT_ID && + report_id != PIP_BTN_REPORT_ID && report_id != GEN5_OLD_PUSH_BTN_REPORT_ID && - report_id != GEN5_PUSH_BTN_REPORT_ID) { + report_id != PIP_PUSH_BTN_REPORT_ID) { /* Running in BL mode or unknown response data read. */ dev_err(dev, "invalid report_id=0x%02x\n", report_id); return -EINVAL; } - if (report_id == GEN5_TOUCH_REPORT_ID && - (report_len < GEN5_TOUCH_REPORT_HEAD_SIZE || - report_len > GEN5_TOUCH_REPORT_MAX_SIZE)) { + if (report_id == PIP_TOUCH_REPORT_ID && + (report_len < PIP_TOUCH_REPORT_HEAD_SIZE || + report_len > PIP_TOUCH_REPORT_MAX_SIZE)) { /* Invalid report data length for finger packet. */ dev_err(dev, "invalid touch packet length=%d\n", report_len); return 0; } - if ((report_id == GEN5_BTN_REPORT_ID || + if ((report_id == PIP_BTN_REPORT_ID || report_id == GEN5_OLD_PUSH_BTN_REPORT_ID || - report_id == GEN5_PUSH_BTN_REPORT_ID) && - (report_len < GEN5_BTN_REPORT_HEAD_SIZE || - report_len > GEN5_BTN_REPORT_MAX_SIZE)) { + report_id == PIP_PUSH_BTN_REPORT_ID) && + (report_len < PIP_BTN_REPORT_HEAD_SIZE || + report_len > PIP_BTN_REPORT_MAX_SIZE)) { /* Invalid report data length of button packet. */ dev_err(dev, "invalid button packet length=%d\n", report_len); return 0; } - if (report_id == GEN5_TOUCH_REPORT_ID) - cyapa_gen5_report_touches(cyapa, &report_data); + if (report_id == PIP_TOUCH_REPORT_ID) + cyapa_pip_report_touches(cyapa, &report_data); else - cyapa_gen5_report_buttons(cyapa, &report_data); + cyapa_pip_report_buttons(cyapa, &report_data); return 0; } -static int cyapa_gen5_bl_activate(struct cyapa *cyapa) { return 0; } -static int cyapa_gen5_bl_deactivate(struct cyapa *cyapa) { return 0; } +int cyapa_pip_bl_activate(struct cyapa *cyapa) { return 0; } +int cyapa_pip_bl_deactivate(struct cyapa *cyapa) { return 0; } + const struct cyapa_dev_ops cyapa_gen5_ops = { - .check_fw = cyapa_gen5_check_fw, - .bl_enter = cyapa_gen5_bl_enter, - .bl_initiate = cyapa_gen5_bl_initiate, - .update_fw = cyapa_gen5_do_fw_update, - .bl_activate = cyapa_gen5_bl_activate, - .bl_deactivate = cyapa_gen5_bl_deactivate, + .check_fw = cyapa_pip_check_fw, + .bl_enter = cyapa_pip_bl_enter, + .bl_initiate = cyapa_pip_bl_initiate, + .update_fw = cyapa_pip_do_fw_update, + .bl_activate = cyapa_pip_bl_activate, + .bl_deactivate = cyapa_pip_bl_deactivate, .show_baseline = cyapa_gen5_show_baseline, - .calibrate_store = cyapa_gen5_do_calibrate, + .calibrate_store = cyapa_pip_do_calibrate, - .initialize = cyapa_gen5_initialize, + .initialize = cyapa_pip_cmd_state_initialize, .state_parse = cyapa_gen5_state_parse, .operational_check = cyapa_gen5_do_operational_check, - .irq_handler = cyapa_gen5_irq_handler, - .irq_cmd_handler = cyapa_gen5_irq_cmd_handler, + .irq_handler = cyapa_pip_irq_handler, + .irq_cmd_handler = cyapa_pip_irq_cmd_handler, .sort_empty_output_data = cyapa_empty_pip_output_data, .set_power_mode = cyapa_gen5_set_power_mode, }; -- cgit v1.2.3 From c2c06c41f700b544c9331caf71c67edb5d131257 Mon Sep 17 00:00:00 2001 From: Dudley Du Date: Mon, 20 Jul 2015 16:53:30 -0700 Subject: Input: cyapa - add gen6 device module support Based on the cyapa core, add support for basic functionality of the gen6 trackpad devices. The driver can automatically determine what protocol (gen3, gen5, or gen6) should be used with the attached trackpad device. Signed-off-by: Dudley Du Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/Makefile | 2 +- drivers/input/mouse/cyapa.c | 22 ++ drivers/input/mouse/cyapa.h | 15 + drivers/input/mouse/cyapa_gen5.c | 69 +++- drivers/input/mouse/cyapa_gen6.c | 730 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 834 insertions(+), 4 deletions(-) create mode 100644 drivers/input/mouse/cyapa_gen6.c (limited to 'drivers/input/mouse') diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index 793300bfbddd..ee6a6e9563d4 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile @@ -24,7 +24,7 @@ obj-$(CONFIG_MOUSE_SYNAPTICS_I2C) += synaptics_i2c.o obj-$(CONFIG_MOUSE_SYNAPTICS_USB) += synaptics_usb.o obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o -cyapatp-objs := cyapa.o cyapa_gen3.o cyapa_gen5.o +cyapatp-objs := cyapa.o cyapa_gen3.o cyapa_gen5.o cyapa_gen6.o psmouse-objs := psmouse-base.o synaptics.o focaltech.o psmouse-$(CONFIG_MOUSE_PS2_ALPS) += alps.o diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index 4c4429598adb..6952ed1c92c7 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -41,6 +41,9 @@ static int cyapa_reinitialize(struct cyapa *cyapa); bool cyapa_is_pip_bl_mode(struct cyapa *cyapa) { + if (cyapa->gen == CYAPA_GEN6 && cyapa->state == CYAPA_STATE_GEN6_BL) + return true; + if (cyapa->gen == CYAPA_GEN5 && cyapa->state == CYAPA_STATE_GEN5_BL) return true; @@ -49,6 +52,9 @@ bool cyapa_is_pip_bl_mode(struct cyapa *cyapa) bool cyapa_is_pip_app_mode(struct cyapa *cyapa) { + if (cyapa->gen == CYAPA_GEN6 && cyapa->state == CYAPA_STATE_GEN6_APP) + return true; + if (cyapa->gen == CYAPA_GEN5 && cyapa->state == CYAPA_STATE_GEN5_APP) return true; @@ -204,6 +210,15 @@ static int cyapa_get_state(struct cyapa *cyapa) if (!error) goto out_detected; } + if (cyapa->gen == CYAPA_GEN_UNKNOWN || + cyapa->gen == CYAPA_GEN6 || + cyapa->gen == CYAPA_GEN5) { + error = cyapa_pip_state_parse(cyapa, + status, BL_STATUS_SIZE); + if (!error) + goto out_detected; + } + /* For old Gen5 trackpads detecting. */ if ((cyapa->gen == CYAPA_GEN_UNKNOWN || cyapa->gen == CYAPA_GEN5) && !smbus && even_addr) { @@ -300,6 +315,9 @@ static int cyapa_check_is_operational(struct cyapa *cyapa) return error; switch (cyapa->gen) { + case CYAPA_GEN6: + cyapa->ops = &cyapa_gen6_ops; + break; case CYAPA_GEN5: cyapa->ops = &cyapa_gen5_ops; break; @@ -579,6 +597,8 @@ static int cyapa_initialize(struct cyapa *cyapa) error = cyapa_gen3_ops.initialize(cyapa); if (!error) error = cyapa_gen5_ops.initialize(cyapa); + if (!error) + error = cyapa_gen6_ops.initialize(cyapa); if (error) return error; @@ -1136,9 +1156,11 @@ static char *cyapa_state_to_string(struct cyapa *cyapa) case CYAPA_STATE_BL_ACTIVE: return "bootloader active"; case CYAPA_STATE_GEN5_BL: + case CYAPA_STATE_GEN6_BL: return "bootloader"; case CYAPA_STATE_OP: case CYAPA_STATE_GEN5_APP: + case CYAPA_STATE_GEN6_APP: return "operational"; /* Normal valid state. */ default: return "invalid mode"; diff --git a/drivers/input/mouse/cyapa.h b/drivers/input/mouse/cyapa.h index d019d1d2d1e4..3a211c0769e9 100644 --- a/drivers/input/mouse/cyapa.h +++ b/drivers/input/mouse/cyapa.h @@ -19,6 +19,7 @@ #define CYAPA_GEN_UNKNOWN 0x00 /* unknown protocol. */ #define CYAPA_GEN3 0x03 /* support MT-protocol B with tracking ID. */ #define CYAPA_GEN5 0x05 /* support TrueTouch GEN5 trackpad device. */ +#define CYAPA_GEN6 0x06 /* support TrueTouch GEN6 trackpad device. */ #define CYAPA_NAME "Cypress APA Trackpad (cyapa)" @@ -198,6 +199,9 @@ #define PIP_BL_APP_INFO_RESP_LENGTH 30 #define PIP_BL_GET_INFO_RESP_LENGTH 19 +#define PIP_BL_PLATFORM_VER_SHIFT 4 +#define PIP_BL_PLATFORM_VER_MASK 0x0f + #define PIP_PRODUCT_FAMILY_MASK 0xf000 #define PIP_PRODUCT_FAMILY_TRACKPAD 0x1000 @@ -299,6 +303,14 @@ enum cyapa_state { CYAPA_STATE_OP, CYAPA_STATE_GEN5_BL, CYAPA_STATE_GEN5_APP, + CYAPA_STATE_GEN6_BL, + CYAPA_STATE_GEN6_APP, +}; + +struct gen6_interval_setting { + u16 active_interval; + u16 lp1_interval; + u16 lp2_interval; }; /* The main device structure */ @@ -320,9 +332,11 @@ struct cyapa { u16 runtime_suspend_sleep_time; u8 dev_pwr_mode; u16 dev_sleep_time; + struct gen6_interval_setting gen6_interval_setting; /* Read from query data region. */ char product_id[16]; + u8 platform_ver; /* Platform version. */ u8 fw_maj_ver; /* Firmware major version. */ u8 fw_min_ver; /* Firmware minor version. */ u8 btn_capability; @@ -411,5 +425,6 @@ extern u8 pip_bl_read_app_info[]; extern const char product_id[]; extern const struct cyapa_dev_ops cyapa_gen3_ops; extern const struct cyapa_dev_ops cyapa_gen5_ops; +extern const struct cyapa_dev_ops cyapa_gen6_ops; #endif diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c index 9d75c6f9f307..4e19dce1dd62 100644 --- a/drivers/input/mouse/cyapa_gen5.c +++ b/drivers/input/mouse/cyapa_gen5.c @@ -133,7 +133,9 @@ struct cyapa_pip_touch_record { * Bit 7 - 3: reserved * Bit 2 - 0: touch type; * 0 : standard finger; - * 1 - 15 : reserved. + * 1 : proximity (Start supported in Gen5 TP). + * 2 : finger hover (defined, but not used yet.) + * 3 - 15 : reserved. */ u8 touch_type; @@ -167,6 +169,9 @@ struct cyapa_pip_touch_record { * The meaning of this value is different when touch_type is different. * For standard finger type: * Touch intensity in counts, pressure value. + * For proximity type (Start supported in Gen5 TP): + * The distance, in surface units, between the contact and + * the surface. **/ u8 z; @@ -218,6 +223,12 @@ struct cyapa_tsg_bin_image_head { u8 fw_major_version; u8 fw_minor_version; u8 fw_revision_control_number[8]; + u8 silicon_id_hi; + u8 silicon_id_lo; + u8 chip_revision; + u8 family_id; + u8 bl_ver_maj; + u8 bl_ver_min; } __packed; struct cyapa_tsg_bin_image_data_record { @@ -1134,6 +1145,39 @@ int cyapa_pip_bl_enter(struct cyapa *cyapa) cyapa->operational = false; if (cyapa->gen == CYAPA_GEN5) cyapa->state = CYAPA_STATE_GEN5_BL; + else if (cyapa->gen == CYAPA_GEN6) + cyapa->state = CYAPA_STATE_GEN6_BL; + return 0; +} + +static int cyapa_pip_fw_head_check(struct cyapa *cyapa, + struct cyapa_tsg_bin_image_head *image_head) +{ + if (image_head->head_size != 0x0C && image_head->head_size != 0x12) + return -EINVAL; + + switch (cyapa->gen) { + case CYAPA_GEN6: + if (image_head->family_id != 0x9B || + image_head->silicon_id_hi != 0x0B) + return -EINVAL; + break; + case CYAPA_GEN5: + /* Gen5 without proximity support. */ + if (cyapa->platform_ver < 2) { + if (image_head->head_size == 0x0C) + break; + return -EINVAL; + } + + if (image_head->family_id != 0x91 || + image_head->silicon_id_hi != 0x02) + return -EINVAL; + break; + default: + return -EINVAL; + } + return 0; } @@ -1150,6 +1194,14 @@ int cyapa_pip_check_fw(struct cyapa *cyapa, const struct firmware *fw) u16 app_integrity_crc; int i; + /* Verify the firmware image not miss-used for Gen5 and Gen6. */ + if (cyapa_pip_fw_head_check(cyapa, + (struct cyapa_tsg_bin_image_head *)fw->data)) { + dev_err(dev, "%s: firmware image not match TP device.\n", + __func__); + return -EINVAL; + } + image_records = cyapa_get_image_record_data_num(fw, &flash_records_count); @@ -2339,6 +2391,9 @@ static int cyapa_gen5_bl_query_data(struct cyapa *cyapa) cyapa->fw_maj_ver = resp_data[22]; cyapa->fw_min_ver = resp_data[23]; + cyapa->platform_ver = (resp_data[26] >> PIP_BL_PLATFORM_VER_SHIFT) & + PIP_BL_PLATFORM_VER_MASK; + return 0; } @@ -2362,8 +2417,16 @@ static int cyapa_gen5_get_query_data(struct cyapa *cyapa) PIP_PRODUCT_FAMILY_TRACKPAD) return -EINVAL; - cyapa->fw_maj_ver = resp_data[15]; - cyapa->fw_min_ver = resp_data[16]; + cyapa->platform_ver = (resp_data[49] >> PIP_BL_PLATFORM_VER_SHIFT) & + PIP_BL_PLATFORM_VER_MASK; + if (cyapa->gen == CYAPA_GEN5 && cyapa->platform_ver < 2) { + /* Gen5 firmware that does not support proximity. */ + cyapa->fw_maj_ver = resp_data[15]; + cyapa->fw_min_ver = resp_data[16]; + } else { + cyapa->fw_maj_ver = resp_data[9]; + cyapa->fw_min_ver = resp_data[10]; + } cyapa->electrodes_x = resp_data[52]; cyapa->electrodes_y = resp_data[53]; diff --git a/drivers/input/mouse/cyapa_gen6.c b/drivers/input/mouse/cyapa_gen6.c new file mode 100644 index 000000000000..8a6aa73b5373 --- /dev/null +++ b/drivers/input/mouse/cyapa_gen6.c @@ -0,0 +1,730 @@ +/* + * Cypress APA trackpad with I2C interface + * + * Author: Dudley Du + * + * Copyright (C) 2015 Cypress Semiconductor, Inc. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cyapa.h" + + +#define GEN6_ENABLE_CMD_IRQ 0x41 +#define GEN6_DISABLE_CMD_IRQ 0x42 +#define GEN6_ENABLE_DEV_IRQ 0x43 +#define GEN6_DISABLE_DEV_IRQ 0x44 + +#define GEN6_POWER_MODE_ACTIVE 0x01 +#define GEN6_POWER_MODE_LP_MODE1 0x02 +#define GEN6_POWER_MODE_LP_MODE2 0x03 +#define GEN6_POWER_MODE_BTN_ONLY 0x04 + +#define GEN6_SET_POWER_MODE_INTERVAL 0x47 +#define GEN6_GET_POWER_MODE_INTERVAL 0x48 + +#define GEN6_MAX_RX_NUM 14 +#define GEN6_RETRIEVE_DATA_ID_RX_ATTENURATOR_IDAC 0x00 +#define GEN6_RETRIEVE_DATA_ID_ATTENURATOR_TRIM 0x12 + + +struct pip_app_cmd_head { + __le16 addr; + __le16 length; + u8 report_id; + u8 resv; /* Reserved, must be 0 */ + u8 cmd_code; /* bit7: resv, set to 0; bit6~0: command code.*/ +} __packed; + +struct pip_app_resp_head { + __le16 length; + u8 report_id; + u8 resv; /* Reserved, must be 0 */ + u8 cmd_code; /* bit7: TGL; bit6~0: command code.*/ + /* + * The value of data_status can be the first byte of data or + * the command status or the unsupported command code depending on the + * requested command code. + */ + u8 data_status; +} __packed; + +struct pip_fixed_info { + u8 silicon_id_high; + u8 silicon_id_low; + u8 family_id; +}; + +static u8 pip_get_bl_info[] = { + 0x04, 0x00, 0x0B, 0x00, 0x40, 0x00, 0x01, 0x38, + 0x00, 0x00, 0x70, 0x9E, 0x17 +}; + +static bool cyapa_sort_pip_hid_descriptor_data(struct cyapa *cyapa, + u8 *buf, int len) +{ + if (len != PIP_HID_DESCRIPTOR_SIZE) + return false; + + if (buf[PIP_RESP_REPORT_ID_OFFSET] == PIP_HID_APP_REPORT_ID || + buf[PIP_RESP_REPORT_ID_OFFSET] == PIP_HID_BL_REPORT_ID) + return true; + + return false; +} + +static int cyapa_get_pip_fixed_info(struct cyapa *cyapa, + struct pip_fixed_info *pip_info, bool is_bootloader) +{ + u8 resp_data[PIP_READ_SYS_INFO_RESP_LENGTH]; + int resp_len; + u16 product_family; + int error; + + if (is_bootloader) { + /* Read Bootloader Information to determine Gen5 or Gen6. */ + resp_len = sizeof(resp_data); + error = cyapa_i2c_pip_cmd_irq_sync(cyapa, + pip_get_bl_info, sizeof(pip_get_bl_info), + resp_data, &resp_len, + 2000, cyapa_sort_tsg_pip_bl_resp_data, + false); + if (error || resp_len < PIP_BL_GET_INFO_RESP_LENGTH) + return error ? error : -EIO; + + pip_info->family_id = resp_data[8]; + pip_info->silicon_id_low = resp_data[10]; + pip_info->silicon_id_high = resp_data[11]; + + return 0; + } + + /* Get App System Information to determine Gen5 or Gen6. */ + resp_len = sizeof(resp_data); + error = cyapa_i2c_pip_cmd_irq_sync(cyapa, + pip_read_sys_info, PIP_READ_SYS_INFO_CMD_LENGTH, + resp_data, &resp_len, + 2000, cyapa_pip_sort_system_info_data, false); + if (error || resp_len < PIP_READ_SYS_INFO_RESP_LENGTH) + return error ? error : -EIO; + + product_family = get_unaligned_le16(&resp_data[7]); + if ((product_family & PIP_PRODUCT_FAMILY_MASK) != + PIP_PRODUCT_FAMILY_TRACKPAD) + return -EINVAL; + + pip_info->family_id = resp_data[19]; + pip_info->silicon_id_low = resp_data[21]; + pip_info->silicon_id_high = resp_data[22]; + + return 0; + +} + +int cyapa_pip_state_parse(struct cyapa *cyapa, u8 *reg_data, int len) +{ + u8 cmd[] = { 0x01, 0x00}; + struct pip_fixed_info pip_info; + u8 resp_data[PIP_HID_DESCRIPTOR_SIZE]; + int resp_len; + bool is_bootloader; + int error; + + cyapa->state = CYAPA_STATE_NO_DEVICE; + + /* Try to wake from it deep sleep state if it is. */ + cyapa_pip_deep_sleep(cyapa, PIP_DEEP_SLEEP_STATE_ON); + + /* Empty the buffer queue to get fresh data with later commands. */ + cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); + + /* + * Read description info from trackpad device to determine running in + * APP mode or Bootloader mode. + */ + resp_len = PIP_HID_DESCRIPTOR_SIZE; + error = cyapa_i2c_pip_cmd_irq_sync(cyapa, + cmd, sizeof(cmd), + resp_data, &resp_len, + 300, + cyapa_sort_pip_hid_descriptor_data, + false); + if (error) + return error; + + if (resp_data[PIP_RESP_REPORT_ID_OFFSET] == PIP_HID_BL_REPORT_ID) + is_bootloader = true; + else if (resp_data[PIP_RESP_REPORT_ID_OFFSET] == PIP_HID_APP_REPORT_ID) + is_bootloader = false; + else + return -EAGAIN; + + /* Get PIP fixed information to determine Gen5 or Gen6. */ + memset(&pip_info, 0, sizeof(struct pip_fixed_info)); + error = cyapa_get_pip_fixed_info(cyapa, &pip_info, is_bootloader); + if (error) + return error; + + if (pip_info.family_id == 0x9B && pip_info.silicon_id_high == 0x0B) { + cyapa->gen = CYAPA_GEN6; + cyapa->state = is_bootloader ? CYAPA_STATE_GEN6_BL + : CYAPA_STATE_GEN6_APP; + } else if (pip_info.family_id == 0x91 && + pip_info.silicon_id_high == 0x02) { + cyapa->gen = CYAPA_GEN5; + cyapa->state = is_bootloader ? CYAPA_STATE_GEN5_BL + : CYAPA_STATE_GEN5_APP; + } + + return 0; +} + +static int cyapa_gen6_read_sys_info(struct cyapa *cyapa) +{ + u8 resp_data[PIP_READ_SYS_INFO_RESP_LENGTH]; + int resp_len; + u16 product_family; + u8 rotat_align; + int error; + + /* Get App System Information to determine Gen5 or Gen6. */ + resp_len = sizeof(resp_data); + error = cyapa_i2c_pip_cmd_irq_sync(cyapa, + pip_read_sys_info, PIP_READ_SYS_INFO_CMD_LENGTH, + resp_data, &resp_len, + 2000, cyapa_pip_sort_system_info_data, false); + if (error || resp_len < sizeof(resp_data)) + return error ? error : -EIO; + + product_family = get_unaligned_le16(&resp_data[7]); + if ((product_family & PIP_PRODUCT_FAMILY_MASK) != + PIP_PRODUCT_FAMILY_TRACKPAD) + return -EINVAL; + + cyapa->platform_ver = (resp_data[67] >> PIP_BL_PLATFORM_VER_SHIFT) & + PIP_BL_PLATFORM_VER_MASK; + cyapa->fw_maj_ver = resp_data[9]; + cyapa->fw_min_ver = resp_data[10]; + + cyapa->electrodes_x = resp_data[33]; + cyapa->electrodes_y = resp_data[34]; + + cyapa->physical_size_x = get_unaligned_le16(&resp_data[35]) / 100; + cyapa->physical_size_y = get_unaligned_le16(&resp_data[37]) / 100; + + cyapa->max_abs_x = get_unaligned_le16(&resp_data[39]); + cyapa->max_abs_y = get_unaligned_le16(&resp_data[41]); + + cyapa->max_z = get_unaligned_le16(&resp_data[43]); + + cyapa->x_origin = resp_data[45] & 0x01; + cyapa->y_origin = resp_data[46] & 0x01; + + cyapa->btn_capability = (resp_data[70] << 3) & CAPABILITY_BTN_MASK; + + memcpy(&cyapa->product_id[0], &resp_data[51], 5); + cyapa->product_id[5] = '-'; + memcpy(&cyapa->product_id[6], &resp_data[56], 6); + cyapa->product_id[12] = '-'; + memcpy(&cyapa->product_id[13], &resp_data[62], 2); + cyapa->product_id[15] = '\0'; + + rotat_align = resp_data[68]; + if (rotat_align) { + cyapa->electrodes_rx = cyapa->electrodes_y; + cyapa->electrodes_rx = cyapa->electrodes_y; + } else { + cyapa->electrodes_rx = cyapa->electrodes_x; + cyapa->electrodes_rx = cyapa->electrodes_y; + } + cyapa->aligned_electrodes_rx = (cyapa->electrodes_rx + 3) & ~3u; + + if (!cyapa->electrodes_x || !cyapa->electrodes_y || + !cyapa->physical_size_x || !cyapa->physical_size_y || + !cyapa->max_abs_x || !cyapa->max_abs_y || !cyapa->max_z) + return -EINVAL; + + return 0; +} + +static int cyapa_gen6_bl_read_app_info(struct cyapa *cyapa) +{ + u8 resp_data[PIP_BL_APP_INFO_RESP_LENGTH]; + int resp_len; + int error; + + resp_len = sizeof(resp_data); + error = cyapa_i2c_pip_cmd_irq_sync(cyapa, + pip_bl_read_app_info, PIP_BL_READ_APP_INFO_CMD_LENGTH, + resp_data, &resp_len, + 500, cyapa_sort_tsg_pip_bl_resp_data, false); + if (error || resp_len < PIP_BL_APP_INFO_RESP_LENGTH || + !PIP_CMD_COMPLETE_SUCCESS(resp_data)) + return error ? error : -EIO; + + cyapa->fw_maj_ver = resp_data[8]; + cyapa->fw_min_ver = resp_data[9]; + + cyapa->platform_ver = (resp_data[12] >> PIP_BL_PLATFORM_VER_SHIFT) & + PIP_BL_PLATFORM_VER_MASK; + + memcpy(&cyapa->product_id[0], &resp_data[13], 5); + cyapa->product_id[5] = '-'; + memcpy(&cyapa->product_id[6], &resp_data[18], 6); + cyapa->product_id[12] = '-'; + memcpy(&cyapa->product_id[13], &resp_data[24], 2); + cyapa->product_id[15] = '\0'; + + return 0; + +} + +static int cyapa_gen6_config_dev_irq(struct cyapa *cyapa, u8 cmd_code) +{ + u8 cmd[] = { 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, cmd_code }; + u8 resp_data[6]; + int resp_len; + int error; + + resp_len = sizeof(resp_data); + error = cyapa_i2c_pip_cmd_irq_sync(cyapa, cmd, sizeof(cmd), + resp_data, &resp_len, + 500, cyapa_sort_tsg_pip_app_resp_data, false); + if (error || !VALID_CMD_RESP_HEADER(resp_data, cmd_code) || + !PIP_CMD_COMPLETE_SUCCESS(resp_data) + ) + return error < 0 ? error : -EINVAL; + + return 0; +} + +static int cyapa_gen6_change_power_state(struct cyapa *cyapa, u8 power_mode) +{ + u8 cmd[] = { 0x04, 0x00, 0x06, 0x00, 0x2f, 0x00, 0x46, power_mode }; + u8 resp_data[6]; + int resp_len; + int error; + + resp_len = sizeof(resp_data); + error = cyapa_i2c_pip_cmd_irq_sync(cyapa, cmd, sizeof(cmd), + resp_data, &resp_len, + 500, cyapa_sort_tsg_pip_app_resp_data, false); + if (error || !VALID_CMD_RESP_HEADER(resp_data, 0x46)) + return error < 0 ? error : -EINVAL; + + /* New power state applied in device not match the set power state. */ + if (resp_data[5] != power_mode) + return -EAGAIN; + + return 0; +} + +static int cyapa_gen6_set_interval_setting(struct cyapa *cyapa, + struct gen6_interval_setting *interval_setting) +{ + struct gen6_set_interval_cmd { + __le16 addr; + __le16 length; + u8 report_id; + u8 rsvd; /* Reserved, must be 0 */ + u8 cmd_code; + __le16 active_interval; + __le16 lp1_interval; + __le16 lp2_interval; + } __packed set_interval_cmd; + u8 resp_data[11]; + int resp_len; + int error; + + memset(&set_interval_cmd, 0, sizeof(set_interval_cmd)); + put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR, &set_interval_cmd.addr); + put_unaligned_le16(sizeof(set_interval_cmd) - 2, + &set_interval_cmd.length); + set_interval_cmd.report_id = PIP_APP_CMD_REPORT_ID; + set_interval_cmd.cmd_code = GEN6_SET_POWER_MODE_INTERVAL; + put_unaligned_le16(interval_setting->active_interval, + &set_interval_cmd.active_interval); + put_unaligned_le16(interval_setting->lp1_interval, + &set_interval_cmd.lp1_interval); + put_unaligned_le16(interval_setting->lp2_interval, + &set_interval_cmd.lp2_interval); + + resp_len = sizeof(resp_data); + error = cyapa_i2c_pip_cmd_irq_sync(cyapa, + (u8 *)&set_interval_cmd, sizeof(set_interval_cmd), + resp_data, &resp_len, + 500, cyapa_sort_tsg_pip_app_resp_data, false); + if (error || + !VALID_CMD_RESP_HEADER(resp_data, GEN6_SET_POWER_MODE_INTERVAL)) + return error < 0 ? error : -EINVAL; + + /* Get the real set intervals from response. */ + interval_setting->active_interval = get_unaligned_le16(&resp_data[5]); + interval_setting->lp1_interval = get_unaligned_le16(&resp_data[7]); + interval_setting->lp2_interval = get_unaligned_le16(&resp_data[9]); + + return 0; +} + +static int cyapa_gen6_get_interval_setting(struct cyapa *cyapa, + struct gen6_interval_setting *interval_setting) +{ + u8 cmd[] = { 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, + GEN6_GET_POWER_MODE_INTERVAL }; + u8 resp_data[11]; + int resp_len; + int error; + + resp_len = sizeof(resp_data); + error = cyapa_i2c_pip_cmd_irq_sync(cyapa, cmd, sizeof(cmd), + resp_data, &resp_len, + 500, cyapa_sort_tsg_pip_app_resp_data, false); + if (error || + !VALID_CMD_RESP_HEADER(resp_data, GEN6_GET_POWER_MODE_INTERVAL)) + return error < 0 ? error : -EINVAL; + + interval_setting->active_interval = get_unaligned_le16(&resp_data[5]); + interval_setting->lp1_interval = get_unaligned_le16(&resp_data[7]); + interval_setting->lp2_interval = get_unaligned_le16(&resp_data[9]); + + return 0; +} + +static int cyapa_gen6_deep_sleep(struct cyapa *cyapa, u8 state) +{ + u8 ping[] = { 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x00 }; + + if (state == PIP_DEEP_SLEEP_STATE_ON) + /* + * Send ping command to notify device prepare for wake up + * when it's in deep sleep mode. At this time, device will + * response nothing except an I2C NAK. + */ + cyapa_i2c_pip_write(cyapa, ping, sizeof(ping)); + + return cyapa_pip_deep_sleep(cyapa, state); +} + +static int cyapa_gen6_set_power_mode(struct cyapa *cyapa, + u8 power_mode, u16 sleep_time) +{ + struct device *dev = &cyapa->client->dev; + struct gen6_interval_setting *interval_setting = + &cyapa->gen6_interval_setting; + u8 lp_mode; + int error; + + if (cyapa->state != CYAPA_STATE_GEN6_APP) + return 0; + + if (PIP_DEV_GET_PWR_STATE(cyapa) == UNINIT_PWR_MODE) { + /* + * Assume TP in deep sleep mode when driver is loaded, + * avoid driver unload and reload command IO issue caused by TP + * has been set into deep sleep mode when unloading. + */ + PIP_DEV_SET_PWR_STATE(cyapa, PWR_MODE_OFF); + } + + if (PIP_DEV_UNINIT_SLEEP_TIME(cyapa) && + PIP_DEV_GET_PWR_STATE(cyapa) != PWR_MODE_OFF) + PIP_DEV_SET_SLEEP_TIME(cyapa, UNINIT_SLEEP_TIME); + + if (PIP_DEV_GET_PWR_STATE(cyapa) == power_mode) { + if (power_mode == PWR_MODE_OFF || + power_mode == PWR_MODE_FULL_ACTIVE || + power_mode == PWR_MODE_BTN_ONLY || + PIP_DEV_GET_SLEEP_TIME(cyapa) == sleep_time) { + /* Has in correct power mode state, early return. */ + return 0; + } + } + + if (power_mode == PWR_MODE_OFF) { + cyapa_gen6_config_dev_irq(cyapa, GEN6_DISABLE_CMD_IRQ); + + error = cyapa_gen6_deep_sleep(cyapa, PIP_DEEP_SLEEP_STATE_OFF); + if (error) { + dev_err(dev, "enter deep sleep fail: %d\n", error); + return error; + } + + PIP_DEV_SET_PWR_STATE(cyapa, PWR_MODE_OFF); + return 0; + } + + /* + * When trackpad in power off mode, it cannot change to other power + * state directly, must be wake up from sleep firstly, then + * continue to do next power sate change. + */ + if (PIP_DEV_GET_PWR_STATE(cyapa) == PWR_MODE_OFF) { + error = cyapa_gen6_deep_sleep(cyapa, PIP_DEEP_SLEEP_STATE_ON); + if (error) { + dev_err(dev, "deep sleep wake fail: %d\n", error); + return error; + } + } + + /* + * Disable device assert interrupts for command response to avoid + * disturbing system suspending or hibernating process. + */ + cyapa_gen6_config_dev_irq(cyapa, GEN6_DISABLE_CMD_IRQ); + + if (power_mode == PWR_MODE_FULL_ACTIVE) { + error = cyapa_gen6_change_power_state(cyapa, + GEN6_POWER_MODE_ACTIVE); + if (error) { + dev_err(dev, "change to active fail: %d\n", error); + goto out; + } + + PIP_DEV_SET_PWR_STATE(cyapa, PWR_MODE_FULL_ACTIVE); + + /* Sync the interval setting from device. */ + cyapa_gen6_get_interval_setting(cyapa, interval_setting); + + } else if (power_mode == PWR_MODE_BTN_ONLY) { + error = cyapa_gen6_change_power_state(cyapa, + GEN6_POWER_MODE_BTN_ONLY); + if (error) { + dev_err(dev, "fail to button only mode: %d\n", error); + goto out; + } + + PIP_DEV_SET_PWR_STATE(cyapa, PWR_MODE_BTN_ONLY); + } else { + /* + * Gen6 internally supports to 2 low power scan interval time, + * so can help to switch power mode quickly. + * such as runtime suspend and system suspend. + */ + if (interval_setting->lp1_interval == sleep_time) { + lp_mode = GEN6_POWER_MODE_LP_MODE1; + } else if (interval_setting->lp2_interval == sleep_time) { + lp_mode = GEN6_POWER_MODE_LP_MODE2; + } else { + if (interval_setting->lp1_interval == 0) { + interval_setting->lp1_interval = sleep_time; + lp_mode = GEN6_POWER_MODE_LP_MODE1; + } else { + interval_setting->lp2_interval = sleep_time; + lp_mode = GEN6_POWER_MODE_LP_MODE2; + } + cyapa_gen6_set_interval_setting(cyapa, + interval_setting); + } + + error = cyapa_gen6_change_power_state(cyapa, lp_mode); + if (error) { + dev_err(dev, "set power state to 0x%02x failed: %d\n", + lp_mode, error); + goto out; + } + + PIP_DEV_SET_SLEEP_TIME(cyapa, sleep_time); + PIP_DEV_SET_PWR_STATE(cyapa, + cyapa_sleep_time_to_pwr_cmd(sleep_time)); + } + +out: + cyapa_gen6_config_dev_irq(cyapa, GEN6_ENABLE_CMD_IRQ); + return error; +} + +static int cyapa_gen6_initialize(struct cyapa *cyapa) +{ + return 0; +} + +static int cyapa_pip_retrieve_data_structure(struct cyapa *cyapa, + u16 read_offset, u16 read_len, u8 data_id, + u8 *data, int *data_buf_lens) +{ + struct retrieve_data_struct_cmd { + struct pip_app_cmd_head head; + __le16 read_offset; + __le16 read_length; + u8 data_id; + } __packed cmd; + u8 resp_data[GEN6_MAX_RX_NUM + 10]; + int resp_len; + int error; + + memset(&cmd, 0, sizeof(cmd)); + put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR, &cmd.head.addr); + put_unaligned_le16(sizeof(cmd), &cmd.head.length - 2); + cmd.head.report_id = PIP_APP_CMD_REPORT_ID; + cmd.head.cmd_code = PIP_RETRIEVE_DATA_STRUCTURE; + put_unaligned_le16(read_offset, &cmd.read_offset); + put_unaligned_le16(read_len, &cmd.read_length); + cmd.data_id = data_id; + + resp_len = sizeof(resp_data); + error = cyapa_i2c_pip_cmd_irq_sync(cyapa, + (u8 *)&cmd, sizeof(cmd), + resp_data, &resp_len, + 500, cyapa_sort_tsg_pip_app_resp_data, + true); + if (error || !PIP_CMD_COMPLETE_SUCCESS(resp_data) || + resp_data[6] != data_id || + !VALID_CMD_RESP_HEADER(resp_data, PIP_RETRIEVE_DATA_STRUCTURE)) + return (error < 0) ? error : -EAGAIN; + + read_len = get_unaligned_le16(&resp_data[7]); + if (*data_buf_lens < read_len) { + *data_buf_lens = read_len; + return -ENOBUFS; + } + + memcpy(data, &resp_data[10], read_len); + *data_buf_lens = read_len; + return 0; +} + +static ssize_t cyapa_gen6_show_baseline(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + u8 data[GEN6_MAX_RX_NUM]; + int data_len; + int size = 0; + int i; + int error; + int resume_error; + + if (!cyapa_is_pip_app_mode(cyapa)) + return -EBUSY; + + /* 1. Suspend Scanning*/ + error = cyapa_pip_suspend_scanning(cyapa); + if (error) + return error; + + /* 2. IDAC and RX Attenuator Calibration Data (Center Frequency). */ + data_len = sizeof(data); + error = cyapa_pip_retrieve_data_structure(cyapa, 0, data_len, + GEN6_RETRIEVE_DATA_ID_RX_ATTENURATOR_IDAC, + data, &data_len); + if (error) + goto resume_scanning; + + size = scnprintf(buf, PAGE_SIZE, "%d %d %d %d %d %d ", + data[0], /* RX Attenuator Mutual */ + data[1], /* IDAC Mutual */ + data[2], /* RX Attenuator Self RX */ + data[3], /* IDAC Self RX */ + data[4], /* RX Attenuator Self TX */ + data[5] /* IDAC Self TX */ + ); + + /* 3. Read Attenuator Trim. */ + data_len = sizeof(data); + error = cyapa_pip_retrieve_data_structure(cyapa, 0, data_len, + GEN6_RETRIEVE_DATA_ID_ATTENURATOR_TRIM, + data, &data_len); + if (error) + goto resume_scanning; + + /* set attenuator trim values. */ + for (i = 0; i < data_len; i++) + size += scnprintf(buf + size, PAGE_SIZE - size, "%d ", data[i]); + size += scnprintf(buf + size, PAGE_SIZE - size, "\n"); + +resume_scanning: + /* 4. Resume Scanning*/ + resume_error = cyapa_pip_resume_scanning(cyapa); + if (resume_error || error) { + memset(buf, 0, PAGE_SIZE); + return resume_error ? resume_error : error; + } + + return size; +} + +static int cyapa_gen6_operational_check(struct cyapa *cyapa) +{ + struct device *dev = &cyapa->client->dev; + int error; + + if (cyapa->gen != CYAPA_GEN6) + return -ENODEV; + + switch (cyapa->state) { + case CYAPA_STATE_GEN6_BL: + error = cyapa_pip_bl_exit(cyapa); + if (error) { + /* Try to update trackpad product information. */ + cyapa_gen6_bl_read_app_info(cyapa); + goto out; + } + + cyapa->state = CYAPA_STATE_GEN6_APP; + + case CYAPA_STATE_GEN6_APP: + /* + * If trackpad device in deep sleep mode, + * the app command will fail. + * So always try to reset trackpad device to full active when + * the device state is required. + */ + error = cyapa_gen6_set_power_mode(cyapa, + PWR_MODE_FULL_ACTIVE, 0); + if (error) + dev_warn(dev, "%s: failed to set power active mode.\n", + __func__); + + /* Get trackpad product information. */ + error = cyapa_gen6_read_sys_info(cyapa); + if (error) + goto out; + /* Only support product ID starting with CYTRA */ + if (memcmp(cyapa->product_id, product_id, + strlen(product_id)) != 0) { + dev_err(dev, "%s: unknown product ID (%s)\n", + __func__, cyapa->product_id); + error = -EINVAL; + } + break; + default: + error = -EINVAL; + } + +out: + return error; +} + +const struct cyapa_dev_ops cyapa_gen6_ops = { + .check_fw = cyapa_pip_check_fw, + .bl_enter = cyapa_pip_bl_enter, + .bl_initiate = cyapa_pip_bl_initiate, + .update_fw = cyapa_pip_do_fw_update, + .bl_activate = cyapa_pip_bl_activate, + .bl_deactivate = cyapa_pip_bl_deactivate, + + .show_baseline = cyapa_gen6_show_baseline, + .calibrate_store = cyapa_pip_do_calibrate, + + .initialize = cyapa_gen6_initialize, + + .state_parse = cyapa_pip_state_parse, + .operational_check = cyapa_gen6_operational_check, + + .irq_handler = cyapa_pip_irq_handler, + .irq_cmd_handler = cyapa_pip_irq_cmd_handler, + .sort_empty_output_data = cyapa_empty_pip_output_data, + .set_power_mode = cyapa_gen6_set_power_mode, +}; -- cgit v1.2.3 From 945525ee607471630d07c309e036ae4a53abe37f Mon Sep 17 00:00:00 2001 From: Dudley Du Date: Mon, 20 Jul 2015 16:57:53 -0700 Subject: Input: cyapa - add proximity support for gen5 and gen6 modules Gen5 and Gen6 trackpad devices are able to detect and report object proximity data/events, add this function support in the cyapa driver through the ABS_DISTANCE event. Signed-off-by: Dudley Du Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/cyapa.c | 13 ++++++++- drivers/input/mouse/cyapa.h | 3 ++ drivers/input/mouse/cyapa_gen3.c | 7 +++++ drivers/input/mouse/cyapa_gen5.c | 61 +++++++++++++++++++++++++++++++++++++++- drivers/input/mouse/cyapa_gen6.c | 19 +++++++++++++ 5 files changed, 101 insertions(+), 2 deletions(-) (limited to 'drivers/input/mouse') diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index 6952ed1c92c7..2541fbb43533 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -477,6 +477,7 @@ static int cyapa_create_input_dev(struct cyapa *cyapa) if (cyapa->gen >= CYAPA_GEN5) { input_set_abs_params(input, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0); input_set_abs_params(input, ABS_MT_WIDTH_MINOR, 0, 255, 0, 0); + input_set_abs_params(input, ABS_DISTANCE, 0, 1, 0, 0); } input_abs_set_res(input, ABS_MT_POSITION_X, @@ -1340,6 +1341,13 @@ static int __maybe_unused cyapa_suspend(struct device *dev) error); } + /* + * Disable proximity interrupt when system idle, want true touch to + * wake the system. + */ + if (cyapa->dev_pwr_mode != PWR_MODE_OFF) + cyapa->ops->set_proximity(cyapa, false); + if (device_may_wakeup(dev)) cyapa->irq_wake = (enable_irq_wake(client->irq) == 0); @@ -1360,7 +1368,10 @@ static int __maybe_unused cyapa_resume(struct device *dev) cyapa->irq_wake = false; } - /* Update device states and runtime PM states. */ + /* + * Update device states and runtime PM states. + * Re-Enable proximity interrupt after enter operational mode. + */ error = cyapa_reinitialize(cyapa); if (error) dev_warn(dev, "failed to reinitialize TP device: %d\n", error); diff --git a/drivers/input/mouse/cyapa.h b/drivers/input/mouse/cyapa.h index 3a211c0769e9..f51deb69c370 100644 --- a/drivers/input/mouse/cyapa.h +++ b/drivers/input/mouse/cyapa.h @@ -274,6 +274,8 @@ struct cyapa_dev_ops { u8 *, int *, cb_sort); int (*set_power_mode)(struct cyapa *, u8, u16); + + int (*set_proximity)(struct cyapa *, bool); }; struct cyapa_pip_cmd_states { @@ -415,6 +417,7 @@ int cyapa_pip_bl_deactivate(struct cyapa *cyapa); ssize_t cyapa_pip_do_calibrate(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); +int cyapa_pip_set_proximity(struct cyapa *cyapa, bool enable); bool cyapa_pip_irq_cmd_handler(struct cyapa *cyapa); int cyapa_pip_irq_handler(struct cyapa *cyapa); diff --git a/drivers/input/mouse/cyapa_gen3.c b/drivers/input/mouse/cyapa_gen3.c index 3884311410f7..e7bbfee8b5d6 100644 --- a/drivers/input/mouse/cyapa_gen3.c +++ b/drivers/input/mouse/cyapa_gen3.c @@ -999,6 +999,11 @@ static int cyapa_gen3_set_power_mode(struct cyapa *cyapa, u8 power_mode, return ret; } +static int cyapa_gen3_set_proximity(struct cyapa *cyapa, bool enable) +{ + return -EOPNOTSUPP; +} + static int cyapa_gen3_get_query_data(struct cyapa *cyapa) { u8 query_data[QUERY_DATA_SIZE]; @@ -1243,4 +1248,6 @@ const struct cyapa_dev_ops cyapa_gen3_ops = { .irq_cmd_handler = cyapa_gen3_irq_cmd_handler, .sort_empty_output_data = cyapa_gen3_empty_output_data, .set_power_mode = cyapa_gen3_set_power_mode, + + .set_proximity = cyapa_gen3_set_proximity, }; diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c index 4e19dce1dd62..fa135f855f34 100644 --- a/drivers/input/mouse/cyapa_gen5.c +++ b/drivers/input/mouse/cyapa_gen5.c @@ -52,6 +52,11 @@ #define PIP_WAKEUP_EVENT_REPORT_ID 0x04 #define PIP_PUSH_BTN_REPORT_ID 0x06 #define GEN5_OLD_PUSH_BTN_REPORT_ID 0x05 /* Special for old Gen5 TP. */ +#define PIP_PROXIMITY_REPORT_ID 0x07 + +#define PIP_PROXIMITY_REPORT_SIZE 6 +#define PIP_PROXIMITY_DISTANCE_OFFSET 0x05 +#define PIP_PROXIMITY_DISTANCE_MASK 0x01 #define PIP_TOUCH_REPORT_HEAD_SIZE 7 #define PIP_TOUCH_REPORT_MAX_SIZE 127 @@ -78,6 +83,8 @@ #define PIP_SENSING_MODE_MUTUAL_CAP_FINE 0x00 #define PIP_SENSING_MODE_SELF_CAP 0x02 +#define PIP_SET_PROXIMITY 0x49 + /* Macro of Gen5 */ #define GEN5_BL_MAX_OUTPUT_LENGTH 0x0100 #define GEN5_APP_MAX_OUTPUT_LENGTH 0x00fe @@ -1517,6 +1524,28 @@ static int cyapa_gen5_disable_pip_report(struct cyapa *cyapa) return 0; } +int cyapa_pip_set_proximity(struct cyapa *cyapa, bool enable) +{ + u8 cmd[] = { 0x04, 0x00, 0x06, 0x00, 0x2f, 0x00, PIP_SET_PROXIMITY, + (u8)!!enable + }; + u8 resp_data[6]; + int resp_len; + int error; + + resp_len = sizeof(resp_data); + error = cyapa_i2c_pip_cmd_irq_sync(cyapa, cmd, sizeof(cmd), + resp_data, &resp_len, + 500, cyapa_sort_tsg_pip_app_resp_data, false); + if (error || !VALID_CMD_RESP_HEADER(resp_data, PIP_SET_PROXIMITY) || + !PIP_CMD_COMPLETE_SUCCESS(resp_data)) { + error = (error == -ETIMEDOUT) ? -EOPNOTSUPP : error; + return error < 0 ? error : -EINVAL; + } + + return 0; +} + int cyapa_pip_deep_sleep(struct cyapa *cyapa, u8 state) { u8 cmd[] = { 0x05, 0x00, 0x00, 0x08}; @@ -2491,6 +2520,12 @@ static int cyapa_gen5_do_operational_check(struct cyapa *cyapa) dev_warn(dev, "%s: failed to set power active mode.\n", __func__); + /* By default, the trackpad proximity function is enabled. */ + error = cyapa_pip_set_proximity(cyapa, true); + if (error) + dev_warn(dev, "%s: failed to enable proximity.\n", + __func__); + /* Get trackpad product information. */ error = cyapa_gen5_get_query_data(cyapa); if (error) @@ -2607,6 +2642,17 @@ static void cyapa_pip_report_buttons(struct cyapa *cyapa, input_sync(input); } +static void cyapa_pip_report_proximity(struct cyapa *cyapa, + const struct cyapa_pip_report_data *report_data) +{ + struct input_dev *input = cyapa->input; + u8 distance = report_data->report_head[PIP_PROXIMITY_DISTANCE_OFFSET] & + PIP_PROXIMITY_DISTANCE_MASK; + + input_report_abs(input, ABS_DISTANCE, distance); + input_sync(input); +} + static void cyapa_pip_report_slot_data(struct cyapa *cyapa, const struct cyapa_pip_touch_record *touch) { @@ -2628,6 +2674,7 @@ static void cyapa_pip_report_slot_data(struct cyapa *cyapa, y = cyapa->max_abs_y - y; input_report_abs(input, ABS_MT_POSITION_X, x); input_report_abs(input, ABS_MT_POSITION_Y, y); + input_report_abs(input, ABS_DISTANCE, 0); input_report_abs(input, ABS_MT_PRESSURE, touch->z); input_report_abs(input, ABS_MT_TOUCH_MAJOR, @@ -2715,7 +2762,8 @@ int cyapa_pip_irq_handler(struct cyapa *cyapa) } else if (report_id != PIP_TOUCH_REPORT_ID && report_id != PIP_BTN_REPORT_ID && report_id != GEN5_OLD_PUSH_BTN_REPORT_ID && - report_id != PIP_PUSH_BTN_REPORT_ID) { + report_id != PIP_PUSH_BTN_REPORT_ID && + report_id != PIP_PROXIMITY_REPORT_ID) { /* Running in BL mode or unknown response data read. */ dev_err(dev, "invalid report_id=0x%02x\n", report_id); return -EINVAL; @@ -2739,8 +2787,17 @@ int cyapa_pip_irq_handler(struct cyapa *cyapa) return 0; } + if (report_id == PIP_PROXIMITY_REPORT_ID && + report_len != PIP_PROXIMITY_REPORT_SIZE) { + /* Invalid report data length of proximity packet. */ + dev_err(dev, "invalid proximity data, length=%d\n", report_len); + return 0; + } + if (report_id == PIP_TOUCH_REPORT_ID) cyapa_pip_report_touches(cyapa, &report_data); + else if (report_id == PIP_PROXIMITY_REPORT_ID) + cyapa_pip_report_proximity(cyapa, &report_data); else cyapa_pip_report_buttons(cyapa, &report_data); @@ -2771,4 +2828,6 @@ const struct cyapa_dev_ops cyapa_gen5_ops = { .irq_cmd_handler = cyapa_pip_irq_cmd_handler, .sort_empty_output_data = cyapa_empty_pip_output_data, .set_power_mode = cyapa_gen5_set_power_mode, + + .set_proximity = cyapa_pip_set_proximity, }; diff --git a/drivers/input/mouse/cyapa_gen6.c b/drivers/input/mouse/cyapa_gen6.c index 8a6aa73b5373..61f04132eb65 100644 --- a/drivers/input/mouse/cyapa_gen6.c +++ b/drivers/input/mouse/cyapa_gen6.c @@ -310,6 +310,17 @@ static int cyapa_gen6_config_dev_irq(struct cyapa *cyapa, u8 cmd_code) return 0; } +static int cyapa_gen6_set_proximity(struct cyapa *cyapa, bool enable) +{ + int error; + + cyapa_gen6_config_dev_irq(cyapa, GEN6_DISABLE_CMD_IRQ); + error = cyapa_pip_set_proximity(cyapa, enable); + cyapa_gen6_config_dev_irq(cyapa, GEN6_ENABLE_CMD_IRQ); + + return error; +} + static int cyapa_gen6_change_power_state(struct cyapa *cyapa, u8 power_mode) { u8 cmd[] = { 0x04, 0x00, 0x06, 0x00, 0x2f, 0x00, 0x46, power_mode }; @@ -687,6 +698,12 @@ static int cyapa_gen6_operational_check(struct cyapa *cyapa) dev_warn(dev, "%s: failed to set power active mode.\n", __func__); + /* By default, the trackpad proximity function is enabled. */ + error = cyapa_pip_set_proximity(cyapa, true); + if (error) + dev_warn(dev, "%s: failed to enable proximity.\n", + __func__); + /* Get trackpad product information. */ error = cyapa_gen6_read_sys_info(cyapa); if (error) @@ -727,4 +744,6 @@ const struct cyapa_dev_ops cyapa_gen6_ops = { .irq_cmd_handler = cyapa_pip_irq_cmd_handler, .sort_empty_output_data = cyapa_empty_pip_output_data, .set_power_mode = cyapa_gen6_set_power_mode, + + .set_proximity = cyapa_gen6_set_proximity, }; -- cgit v1.2.3 From 757cae5a6f0ac1c61ce149a066377a15d1ed881f Mon Sep 17 00:00:00 2001 From: Dudley Du Date: Mon, 20 Jul 2015 17:09:59 -0700 Subject: Input: cyapa - fully support runtime suspend power management Fix the the runtime suspend power management not working issue when system starts up and before user touches the trackpad device. TEST=test on Chromebook. Signed-off-by: Dudley Du Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/cyapa.c | 73 ++++++++++++++++++++++++++++------------ drivers/input/mouse/cyapa.h | 2 +- drivers/input/mouse/cyapa_gen3.c | 4 +-- drivers/input/mouse/cyapa_gen5.c | 21 ++++++++---- drivers/input/mouse/cyapa_gen6.c | 4 +-- 5 files changed, 70 insertions(+), 34 deletions(-) (limited to 'drivers/input/mouse') diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index 2541fbb43533..5c08eeba6162 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -367,6 +367,7 @@ static int cyapa_open(struct input_dev *input) { struct cyapa *cyapa = input_get_drvdata(input); struct i2c_client *client = cyapa->client; + struct device *dev = &client->dev; int error; error = mutex_lock_interruptible(&cyapa->state_sync_lock); @@ -380,10 +381,9 @@ static int cyapa_open(struct input_dev *input) * when in operational mode. */ error = cyapa->ops->set_power_mode(cyapa, - PWR_MODE_FULL_ACTIVE, 0); + PWR_MODE_FULL_ACTIVE, 0, false); if (error) { - dev_warn(&client->dev, - "set active power failed: %d\n", error); + dev_warn(dev, "set active power failed: %d\n", error); goto out; } } else { @@ -395,10 +395,14 @@ static int cyapa_open(struct input_dev *input) } enable_irq(client->irq); - if (!pm_runtime_enabled(&client->dev)) { - pm_runtime_set_active(&client->dev); - pm_runtime_enable(&client->dev); + if (!pm_runtime_enabled(dev)) { + pm_runtime_set_active(dev); + pm_runtime_enable(dev); } + + pm_runtime_get_sync(dev); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_sync_autosuspend(dev); out: mutex_unlock(&cyapa->state_sync_lock); return error; @@ -408,16 +412,17 @@ static void cyapa_close(struct input_dev *input) { struct cyapa *cyapa = input_get_drvdata(input); struct i2c_client *client = cyapa->client; + struct device *dev = &cyapa->client->dev; mutex_lock(&cyapa->state_sync_lock); disable_irq(client->irq); - if (pm_runtime_enabled(&client->dev)) - pm_runtime_disable(&client->dev); - pm_runtime_set_suspended(&client->dev); + if (pm_runtime_enabled(dev)) + pm_runtime_disable(dev); + pm_runtime_set_suspended(dev); if (cyapa->operational) - cyapa->ops->set_power_mode(cyapa, PWR_MODE_OFF, 0); + cyapa->ops->set_power_mode(cyapa, PWR_MODE_OFF, 0, false); mutex_unlock(&cyapa->state_sync_lock); } @@ -527,7 +532,7 @@ static void cyapa_enable_irq_for_cmd(struct cyapa *cyapa) */ if (!input || cyapa->operational) cyapa->ops->set_power_mode(cyapa, - PWR_MODE_FULL_ACTIVE, 0); + PWR_MODE_FULL_ACTIVE, 0, false); /* Gen3 always using polling mode for command. */ if (cyapa->gen >= CYAPA_GEN5) enable_irq(cyapa->client->irq); @@ -542,7 +547,8 @@ static void cyapa_disable_irq_for_cmd(struct cyapa *cyapa) if (cyapa->gen >= CYAPA_GEN5) disable_irq(cyapa->client->irq); if (!input || cyapa->operational) - cyapa->ops->set_power_mode(cyapa, PWR_MODE_OFF, 0); + cyapa->ops->set_power_mode(cyapa, + PWR_MODE_OFF, 0, false); } } @@ -609,7 +615,7 @@ static int cyapa_initialize(struct cyapa *cyapa) /* Power down the device until we need it. */ if (cyapa->operational) - cyapa->ops->set_power_mode(cyapa, PWR_MODE_OFF, 0); + cyapa->ops->set_power_mode(cyapa, PWR_MODE_OFF, 0, false); return 0; } @@ -625,7 +631,8 @@ static int cyapa_reinitialize(struct cyapa *cyapa) /* Avoid command failures when TP was in OFF state. */ if (cyapa->operational) - cyapa->ops->set_power_mode(cyapa, PWR_MODE_FULL_ACTIVE, 0); + cyapa->ops->set_power_mode(cyapa, + PWR_MODE_FULL_ACTIVE, 0, false); error = cyapa_detect(cyapa); if (error) @@ -644,7 +651,8 @@ out: if (!input || !input->users) { /* Reset to power OFF state to save power when no user open. */ if (cyapa->operational) - cyapa->ops->set_power_mode(cyapa, PWR_MODE_OFF, 0); + cyapa->ops->set_power_mode(cyapa, + PWR_MODE_OFF, 0, false); } else if (!error && cyapa->operational) { /* * Make sure only enable runtime PM when device is @@ -652,6 +660,10 @@ out: */ pm_runtime_set_active(dev); pm_runtime_enable(dev); + + pm_runtime_get_sync(dev); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_sync_autosuspend(dev); } return error; @@ -661,8 +673,8 @@ static irqreturn_t cyapa_irq(int irq, void *dev_id) { struct cyapa *cyapa = dev_id; struct device *dev = &cyapa->client->dev; + int error; - pm_runtime_get_sync(dev); if (device_may_wakeup(dev)) pm_wakeup_event(dev, 0); @@ -681,7 +693,24 @@ static irqreturn_t cyapa_irq(int irq, void *dev_id) goto out; } - if (!cyapa->operational || cyapa->ops->irq_handler(cyapa)) { + if (cyapa->operational) { + error = cyapa->ops->irq_handler(cyapa); + + /* + * Apply runtime power management to touch report event + * except the events caused by the command responses. + * Note: + * It will introduce about 20~40 ms additional delay + * time in receiving for first valid touch report data. + * The time is used to execute device runtime resume + * process. + */ + pm_runtime_get_sync(dev); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_sync_autosuspend(dev); + } + + if (!cyapa->operational || error) { if (!mutex_trylock(&cyapa->state_sync_lock)) { cyapa->ops->sort_empty_output_data(cyapa, NULL, NULL, NULL); @@ -693,8 +722,6 @@ static irqreturn_t cyapa_irq(int irq, void *dev_id) } out: - pm_runtime_mark_last_busy(dev); - pm_runtime_put_sync_autosuspend(dev); return IRQ_HANDLED; } @@ -1335,7 +1362,7 @@ static int __maybe_unused cyapa_suspend(struct device *dev) power_mode = device_may_wakeup(dev) ? cyapa->suspend_power_mode : PWR_MODE_OFF; error = cyapa->ops->set_power_mode(cyapa, power_mode, - cyapa->suspend_sleep_time); + cyapa->suspend_sleep_time, true); if (error) dev_err(dev, "suspend set power mode failed: %d\n", error); @@ -1389,7 +1416,8 @@ static int __maybe_unused cyapa_runtime_suspend(struct device *dev) error = cyapa->ops->set_power_mode(cyapa, cyapa->runtime_suspend_power_mode, - cyapa->runtime_suspend_sleep_time); + cyapa->runtime_suspend_sleep_time, + false); if (error) dev_warn(dev, "runtime suspend failed: %d\n", error); @@ -1401,7 +1429,8 @@ static int __maybe_unused cyapa_runtime_resume(struct device *dev) struct cyapa *cyapa = dev_get_drvdata(dev); int error; - error = cyapa->ops->set_power_mode(cyapa, PWR_MODE_FULL_ACTIVE, 0); + error = cyapa->ops->set_power_mode(cyapa, + PWR_MODE_FULL_ACTIVE, 0, false); if (error) dev_warn(dev, "runtime resume failed: %d\n", error); diff --git a/drivers/input/mouse/cyapa.h b/drivers/input/mouse/cyapa.h index f51deb69c370..af1253640590 100644 --- a/drivers/input/mouse/cyapa.h +++ b/drivers/input/mouse/cyapa.h @@ -273,7 +273,7 @@ struct cyapa_dev_ops { int (*sort_empty_output_data)(struct cyapa *, u8 *, int *, cb_sort); - int (*set_power_mode)(struct cyapa *, u8, u16); + int (*set_power_mode)(struct cyapa *, u8, u16, bool); int (*set_proximity)(struct cyapa *, bool); }; diff --git a/drivers/input/mouse/cyapa_gen3.c b/drivers/input/mouse/cyapa_gen3.c index e7bbfee8b5d6..1a9d12ae7538 100644 --- a/drivers/input/mouse/cyapa_gen3.c +++ b/drivers/input/mouse/cyapa_gen3.c @@ -950,7 +950,7 @@ static u16 cyapa_get_wait_time_for_pwr_cmd(u8 pwr_mode) * Device power mode can only be set when device is in operational mode. */ static int cyapa_gen3_set_power_mode(struct cyapa *cyapa, u8 power_mode, - u16 always_unused) + u16 always_unused, bool is_suspend_unused) { int ret; u8 power; @@ -1112,7 +1112,7 @@ static int cyapa_gen3_do_operational_check(struct cyapa *cyapa) * may cause problems, so we set the power mode first here. */ error = cyapa_gen3_set_power_mode(cyapa, - PWR_MODE_FULL_ACTIVE, 0); + PWR_MODE_FULL_ACTIVE, 0, false); if (error) dev_err(dev, "%s: set full power mode failed: %d\n", __func__, error); diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c index fa135f855f34..6d7abbed67e4 100644 --- a/drivers/input/mouse/cyapa_gen5.c +++ b/drivers/input/mouse/cyapa_gen5.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "cyapa.h" @@ -1565,7 +1566,7 @@ int cyapa_pip_deep_sleep(struct cyapa *cyapa, u8 state) } static int cyapa_gen5_set_power_mode(struct cyapa *cyapa, - u8 power_mode, u16 sleep_time) + u8 power_mode, u16 sleep_time, bool is_suspend) { struct device *dev = &cyapa->client->dev; u8 power_state; @@ -1574,9 +1575,6 @@ static int cyapa_gen5_set_power_mode(struct cyapa *cyapa, if (cyapa->state != CYAPA_STATE_GEN5_APP) return 0; - /* Dump all the report data before do power mode commmands. */ - cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); - if (PIP_DEV_GET_PWR_STATE(cyapa) == UNINIT_PWR_MODE) { /* * Assume TP in deep sleep mode when driver is loaded, @@ -1679,8 +1677,8 @@ static int cyapa_gen5_set_power_mode(struct cyapa *cyapa, * is suspending which may cause interrupt line unable to be * asserted again. */ - cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); - cyapa_gen5_disable_pip_report(cyapa); + if (is_suspend) + cyapa_gen5_disable_pip_report(cyapa); PIP_DEV_SET_PWR_STATE(cyapa, cyapa_sleep_time_to_pwr_cmd(sleep_time)); @@ -2515,7 +2513,7 @@ static int cyapa_gen5_do_operational_check(struct cyapa *cyapa) * the device state is required. */ error = cyapa_gen5_set_power_mode(cyapa, - PWR_MODE_FULL_ACTIVE, 0); + PWR_MODE_FULL_ACTIVE, 0, false); if (error) dev_warn(dev, "%s: failed to set power active mode.\n", __func__); @@ -2757,7 +2755,16 @@ int cyapa_pip_irq_handler(struct cyapa *cyapa) /* * Device wake event from deep sleep mode for touch. * This interrupt event is used to wake system up. + * + * Note: + * It will introduce about 20~40 ms additional delay + * time in receiving for first valid touch report data. + * The time is used to execute device runtime resume + * process. */ + pm_runtime_get_sync(dev); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_sync_autosuspend(dev); return 0; } else if (report_id != PIP_TOUCH_REPORT_ID && report_id != PIP_BTN_REPORT_ID && diff --git a/drivers/input/mouse/cyapa_gen6.c b/drivers/input/mouse/cyapa_gen6.c index 61f04132eb65..5f191071d44a 100644 --- a/drivers/input/mouse/cyapa_gen6.c +++ b/drivers/input/mouse/cyapa_gen6.c @@ -429,7 +429,7 @@ static int cyapa_gen6_deep_sleep(struct cyapa *cyapa, u8 state) } static int cyapa_gen6_set_power_mode(struct cyapa *cyapa, - u8 power_mode, u16 sleep_time) + u8 power_mode, u16 sleep_time, bool is_suspend) { struct device *dev = &cyapa->client->dev; struct gen6_interval_setting *interval_setting = @@ -693,7 +693,7 @@ static int cyapa_gen6_operational_check(struct cyapa *cyapa) * the device state is required. */ error = cyapa_gen6_set_power_mode(cyapa, - PWR_MODE_FULL_ACTIVE, 0); + PWR_MODE_FULL_ACTIVE, 0, false); if (error) dev_warn(dev, "%s: failed to set power active mode.\n", __func__); -- cgit v1.2.3 From ce2ae9e3e6a152866a33972c966f8315aab2cb1d Mon Sep 17 00:00:00 2001 From: Dudley Du Date: Mon, 20 Jul 2015 17:15:46 -0700 Subject: Input: cyapa - add ACPI HID CYAP0002 for Gen6 devices Add CYTP0002 to the list of ACPI HIDs recognized by the driver. Signed-off-by: Dudley Du Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/cyapa.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/input/mouse') diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index 5c08eeba6162..6195ccb3cfde 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -1452,6 +1452,7 @@ MODULE_DEVICE_TABLE(i2c, cyapa_id_table); static const struct acpi_device_id cyapa_acpi_id[] = { { "CYAP0000", 0 }, /* Gen3 trackpad with 0x67 I2C address. */ { "CYAP0001", 0 }, /* Gen5 trackpad with 0x24 I2C address. */ + { "CYAP0002", 0 }, /* Gen6 trackpad with 0x24 I2C address. */ { } }; MODULE_DEVICE_TABLE(acpi, cyapa_acpi_id); -- cgit v1.2.3 From 36e9615bd70dc8cd5d7d4831943f788f5231350f Mon Sep 17 00:00:00 2001 From: Dudley Du Date: Thu, 30 Jul 2015 11:19:18 -0700 Subject: Input: cyapa - add regulator vcc support We need to power up the chip before we can initialize it. On systems that delegate task of powering up regulators to firmware we assume that we'll be simply given a dummy regulator. Signed-off-by: Dudley Du Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/cyapa.c | 29 +++++++++++++++++++++++++++++ drivers/input/mouse/cyapa.h | 1 + 2 files changed, 30 insertions(+) (limited to 'drivers/input/mouse') diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index 6195ccb3cfde..1479ca996647 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -1241,6 +1242,13 @@ static void cyapa_remove_sysfs_group(void *data) sysfs_remove_group(&cyapa->client->dev.kobj, &cyapa_sysfs_group); } +static void cyapa_disable_regulator(void *data) +{ + struct cyapa *cyapa = data; + + regulator_disable(cyapa->vcc); +} + static int cyapa_probe(struct i2c_client *client, const struct i2c_device_id *dev_id) { @@ -1274,6 +1282,27 @@ static int cyapa_probe(struct i2c_client *client, sprintf(cyapa->phys, "i2c-%d-%04x/input0", client->adapter->nr, client->addr); + cyapa->vcc = devm_regulator_get(dev, "vcc"); + if (IS_ERR(cyapa->vcc)) { + error = PTR_ERR(cyapa->vcc); + dev_err(dev, "failed to get vcc regulator: %d\n", error); + return error; + } + + error = regulator_enable(cyapa->vcc); + if (error) { + dev_err(dev, "failed to enable regulator: %d\n", error); + return error; + } + + error = devm_add_action(dev, cyapa_disable_regulator, cyapa); + if (error) { + cyapa_disable_regulator(cyapa); + dev_err(dev, "failed to add disable regulator action: %d\n", + error); + return error; + } + error = cyapa_initialize(cyapa); if (error) { dev_err(dev, "failed to detect and initialize tp device.\n"); diff --git a/drivers/input/mouse/cyapa.h b/drivers/input/mouse/cyapa.h index af1253640590..b812bba8cdd7 100644 --- a/drivers/input/mouse/cyapa.h +++ b/drivers/input/mouse/cyapa.h @@ -321,6 +321,7 @@ struct cyapa { u8 status[BL_STATUS_SIZE]; bool operational; /* true: ready for data reporting; false: not. */ + struct regulator *vcc; struct i2c_client *client; struct input_dev *input; char phys[32]; /* Device physical location */ -- cgit v1.2.3 From ddbb299db0e040aca8e26361ab778224eeacf9d3 Mon Sep 17 00:00:00 2001 From: Dudley Du Date: Thu, 30 Jul 2015 11:24:16 -0700 Subject: Input: cyapa - introduce device tree binding Add device tree support for Cypress trackpad devices. Signed-off-by: Dudley Du Signed-off-by: Dmitry Torokhov --- .../devicetree/bindings/input/cypress,cyapa.txt | 44 ++++++++++++++++++++++ .../devicetree/bindings/vendor-prefixes.txt | 1 + drivers/input/mouse/cyapa.c | 10 +++++ 3 files changed, 55 insertions(+) create mode 100644 Documentation/devicetree/bindings/input/cypress,cyapa.txt (limited to 'drivers/input/mouse') diff --git a/Documentation/devicetree/bindings/input/cypress,cyapa.txt b/Documentation/devicetree/bindings/input/cypress,cyapa.txt new file mode 100644 index 000000000000..635a3b036630 --- /dev/null +++ b/Documentation/devicetree/bindings/input/cypress,cyapa.txt @@ -0,0 +1,44 @@ +Cypress I2C Touchpad + +Required properties: +- compatible: must be "cypress,cyapa". +- reg: I2C address of the chip. +- interrupt-parent: a phandle for the interrupt controller (see interrupt + binding[0]). +- interrupts: interrupt to which the chip is connected (see interrupt + binding[0]). + +Optional properties: +- wakeup-source: touchpad can be used as a wakeup source. +- pinctrl-names: should be "default" (see pinctrl binding [1]). +- pinctrl-0: a phandle pointing to the pin settings for the device (see + pinctrl binding [1]). +- vcc-supply: a phandle for the regulator supplying 3.3V power. + +[0]: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt +[1]: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt + +Example: + &i2c0 { + /* ... */ + + /* Cypress Gen3 touchpad */ + touchpad@67 { + compatible = "cypress,cyapa"; + reg = <0x24>; + interrupt-parent = <&gpio>; + interrupts = <2 IRQ_TYPE_EDGE_FALLING>; /* GPIO 2 */ + wakeup-source; + }; + + /* Cypress Gen5 and later touchpad */ + touchpad@24 { + compatible = "cypress,cyapa"; + reg = <0x24>; + interrupt-parent = <&gpio>; + interrupts = <2 IRQ_TYPE_EDGE_FALLING>; /* GPIO 2 */ + wakeup-source; + }; + + /* ... */ + }; diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index d444757c4d9e..57c0f5f8839c 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -54,6 +54,7 @@ cortina Cortina Systems, Inc. cosmic Cosmic Circuits crystalfontz Crystalfontz America, Inc. cubietech Cubietech, Ltd. +cypress Cypress Semiconductor Corporation dallas Maxim Integrated Products (formerly Dallas Semiconductor) davicom DAVICOM Semiconductor, Inc. delta Delta Electronics, Inc. diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index 1479ca996647..eb76b61418f3 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "cyapa.h" @@ -1487,11 +1488,20 @@ static const struct acpi_device_id cyapa_acpi_id[] = { MODULE_DEVICE_TABLE(acpi, cyapa_acpi_id); #endif +#ifdef CONFIG_OF +static const struct of_device_id cyapa_of_match[] = { + { .compatible = "cypress,cyapa" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, cyapa_of_match); +#endif + static struct i2c_driver cyapa_driver = { .driver = { .name = "cyapa", .pm = &cyapa_pm_ops, .acpi_match_table = ACPI_PTR(cyapa_acpi_id), + .of_match_table = of_match_ptr(cyapa_of_match), }, .probe = cyapa_probe, -- cgit v1.2.3 From 0642ffd6a864629c12a4cd7528782ed5b68ac69c Mon Sep 17 00:00:00 2001 From: Dudley Du Date: Thu, 30 Jul 2015 11:26:39 -0700 Subject: Input: cyapa - do not try to enable proximity reporting on older devices Avoid the driver generate warning message when the cyapa driver working with the old Gen5 trackpad device which does not support the proximity function. Those old Gen5 trackpad device all have the platform version less than 2. Signed-off-by: Dudley Du Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/cyapa_gen5.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers/input/mouse') diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c index 6d7abbed67e4..118ba977181e 100644 --- a/drivers/input/mouse/cyapa_gen5.c +++ b/drivers/input/mouse/cyapa_gen5.c @@ -2519,10 +2519,13 @@ static int cyapa_gen5_do_operational_check(struct cyapa *cyapa) __func__); /* By default, the trackpad proximity function is enabled. */ - error = cyapa_pip_set_proximity(cyapa, true); - if (error) - dev_warn(dev, "%s: failed to enable proximity.\n", - __func__); + if (cyapa->platform_ver >= 2) { + error = cyapa_pip_set_proximity(cyapa, true); + if (error) + dev_warn(dev, + "%s: failed to enable proximity.\n", + __func__); + } /* Get trackpad product information. */ error = cyapa_gen5_get_query_data(cyapa); -- cgit v1.2.3 From 7d6548abcf4ea4845db8a62a5875d93e2c1bf882 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 4 Aug 2015 11:43:40 -0700 Subject: Input: Allow compile test of GPIO consumers if !GPIOLIB The GPIO subsystem provides dummy GPIO consumer functions if GPIOLIB is not enabled. Hence drivers that depend on GPIOLIB, but use GPIO consumer functionality only, can still be compiled if GPIOLIB is not enabled. Relax the dependency on GPIOLIB if COMPILE_TEST is enabled, where appropriate. Signed-off-by: Geert Uytterhoeven Acked-by: Linus Walleij Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/Kconfig | 4 ++-- drivers/input/misc/Kconfig | 11 ++++++----- drivers/input/mouse/Kconfig | 2 +- drivers/input/touchscreen/Kconfig | 8 ++++---- 4 files changed, 13 insertions(+), 12 deletions(-) (limited to 'drivers/input/mouse') diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 4cd94fd6cbad..10dfa23b11a8 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -187,7 +187,7 @@ config KEYBOARD_EP93XX config KEYBOARD_GPIO tristate "GPIO Buttons" - depends on GPIOLIB + depends on GPIOLIB || COMPILE_TEST help This driver implements support for buttons connected to GPIO pins of various CPUs (and some other chips). @@ -253,7 +253,7 @@ config KEYBOARD_TCA8418 config KEYBOARD_MATRIX tristate "GPIO driven matrix keypad support" - depends on GPIOLIB + depends on GPIOLIB || COMPILE_TEST select INPUT_MATRIXKMAP help Enable support for GPIO driven matrix keypad. diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index d4f0a817e858..dade381c7da8 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -259,7 +259,7 @@ config INPUT_APANEL config INPUT_GP2A tristate "Sharp GP2AP002A00F I2C Proximity/Opto sensor driver" depends on I2C - depends on GPIOLIB + depends on GPIOLIB || COMPILE_TEST help Say Y here if you have a Sharp GP2AP002A00F proximity/als combo-chip hooked to an I2C bus. @@ -269,7 +269,7 @@ config INPUT_GP2A config INPUT_GPIO_BEEPER tristate "Generic GPIO Beeper support" - depends on GPIOLIB + depends on GPIOLIB || COMPILE_TEST help Say Y here if you have a beeper connected to a GPIO pin. @@ -278,7 +278,7 @@ config INPUT_GPIO_BEEPER config INPUT_GPIO_TILT_POLLED tristate "Polled GPIO tilt switch" - depends on GPIOLIB + depends on GPIOLIB || COMPILE_TEST select INPUT_POLLDEV help This driver implements support for tilt switches connected @@ -569,7 +569,7 @@ config INPUT_PWM_BEEPER config INPUT_GPIO_ROTARY_ENCODER tristate "Rotary encoders connected to GPIO pins" - depends on GPIOLIB + depends on GPIOLIB || COMPILE_TEST help Say Y here to add support for rotary encoders connected to GPIO lines. Check file:Documentation/input/rotary-encoder.txt for more @@ -776,7 +776,8 @@ config INPUT_SOC_BUTTON_ARRAY config INPUT_DRV260X_HAPTICS tristate "TI DRV260X haptics support" - depends on INPUT && I2C && GPIOLIB + depends on INPUT && I2C + depends on GPIOLIB || COMPILE_TEST select INPUT_FF_MEMLESS select REGMAP_I2C help diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index d7820d1152d2..17f97e5e11e7 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig @@ -341,7 +341,7 @@ config MOUSE_VSXXXAA config MOUSE_GPIO tristate "GPIO mouse" - depends on GPIOLIB + depends on GPIOLIB || COMPILE_TEST select INPUT_POLLDEV help This driver simulates a mouse on GPIO lines of various CPUs (and some diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 860d426c480e..059edeb7f04a 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -118,7 +118,7 @@ config TOUCHSCREEN_ATMEL_MXT config TOUCHSCREEN_AUO_PIXCIR tristate "AUO in-cell touchscreen using Pixcir ICs" depends on I2C - depends on GPIOLIB + depends on GPIOLIB || COMPILE_TEST help Say Y here if you have a AUO display with in-cell touchscreen using Pixcir ICs. @@ -142,7 +142,7 @@ config TOUCHSCREEN_BU21013 config TOUCHSCREEN_CHIPONE_ICN8318 tristate "chipone icn8318 touchscreen controller" - depends on GPIOLIB + depends on GPIOLIB || COMPILE_TEST depends on I2C depends on OF help @@ -156,7 +156,7 @@ config TOUCHSCREEN_CHIPONE_ICN8318 config TOUCHSCREEN_CY8CTMG110 tristate "cy8ctmg110 touchscreen" depends on I2C - depends on GPIOLIB + depends on GPIOLIB || COMPILE_TEST help Say Y here if you have a cy8ctmg110 capacitive touchscreen on an AAVA device. @@ -1030,7 +1030,7 @@ config TOUCHSCREEN_TPS6507X config TOUCHSCREEN_ZFORCE tristate "Neonode zForce infrared touchscreens" depends on I2C - depends on GPIOLIB + depends on GPIOLIB || COMPILE_TEST help Say Y here if you have a touchscreen using the zforce infraread technology from Neonode. -- cgit v1.2.3 From 71d0f562358c3274e78ef371dfeb71ad5e86cb91 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 5 Aug 2015 12:01:30 -0700 Subject: Input: elan_i2c - enable asynchronous probing It takes a bit of time to go through controller power up sequence and initialization. To not stall the overall boot progress let's probe the controller asynchronously, given that userspace is usually prepared for hot-plugging of input devices and thus does not rely on particular ordering. Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elan_i2c_core.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/input/mouse') diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index 0a076d30be8b..67388f42ed9a 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -1185,6 +1185,7 @@ static struct i2c_driver elan_driver = { .pm = &elan_pm_ops, .acpi_match_table = ACPI_PTR(elan_acpi_id), .of_match_table = of_match_ptr(elan_of_match), + .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, .probe = elan_probe, .id_table = elan_id, -- cgit v1.2.3 From 9c8f55798a9d716daed4de6d7038a21c3ca6e673 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 21 Aug 2015 09:29:50 -0700 Subject: Input: sentelic - silence some underflow warnings I have a static checker that complains when we check for an upper bound but don't have a corresponding check for a lower bound. With this code, the upper bound check seems not really required, so it is not a bug to leave the lower bound check out as well. But let's silence the warning by making these variables unsigned. Signed-off-by: Dan Carpenter Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/sentelic.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers/input/mouse') diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c index cc7e0d4a8f93..11c32ac8234b 100644 --- a/drivers/input/mouse/sentelic.c +++ b/drivers/input/mouse/sentelic.c @@ -432,7 +432,7 @@ static int fsp_onpad_hscr(struct psmouse *psmouse, bool enable) static ssize_t fsp_attr_set_setreg(struct psmouse *psmouse, void *data, const char *buf, size_t count) { - int reg, val; + unsigned int reg, val; char *rest; ssize_t retval; @@ -440,7 +440,7 @@ static ssize_t fsp_attr_set_setreg(struct psmouse *psmouse, void *data, if (rest == buf || *rest != ' ' || reg > 0xff) return -EINVAL; - retval = kstrtoint(rest + 1, 16, &val); + retval = kstrtouint(rest + 1, 16, &val); if (retval) return retval; @@ -476,9 +476,10 @@ static ssize_t fsp_attr_set_getreg(struct psmouse *psmouse, void *data, const char *buf, size_t count) { struct fsp_data *pad = psmouse->private; - int reg, val, err; + unsigned int reg, val; + int err; - err = kstrtoint(buf, 16, ®); + err = kstrtouint(buf, 16, ®); if (err) return err; @@ -511,9 +512,10 @@ static ssize_t fsp_attr_show_pagereg(struct psmouse *psmouse, static ssize_t fsp_attr_set_pagereg(struct psmouse *psmouse, void *data, const char *buf, size_t count) { - int val, err; + unsigned int val; + int err; - err = kstrtoint(buf, 16, &val); + err = kstrtouint(buf, 16, &val); if (err) return err; -- cgit v1.2.3 From 534fcb3bdaab801636d2146079462f7fdf52be0a Mon Sep 17 00:00:00 2001 From: Michele Curti Date: Mon, 24 Aug 2015 10:49:29 -0700 Subject: Input: elan_i2c - enable ELAN0100 acpi panels Enable ELAN0100 touchpad driver, found on a Asus X205TA laptop, to gai 2,3 fingers tap and 2 fingers scroll. Signed-off-by: Michele Curti Reviewed-by: Duson Lin Signed-off-by: Dmitry Torokhov --- drivers/hid/hid-core.c | 1 + drivers/input/mouse/elan_i2c_core.c | 4 ++++ 2 files changed, 5 insertions(+) (limited to 'drivers/input/mouse') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 279898c0a160..3028c1687a51 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -2268,6 +2268,7 @@ static const struct hid_device_id hid_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, 0x0004) }, { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, 0x000a) }, { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, 0x0400) }, + { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, 0x0401) }, { HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) }, { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) }, { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) }, diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index 67388f42ed9a..bbdaedc09261 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -98,6 +98,9 @@ static int elan_get_fwinfo(u8 ic_type, u16 *vaildpage_count, u16 *signature_address) { switch(ic_type) { + case 0x08: + *vaildpage_count = 512; + break; case 0x09: *vaildpage_count = 768; break; @@ -1165,6 +1168,7 @@ MODULE_DEVICE_TABLE(i2c, elan_id); #ifdef CONFIG_ACPI static const struct acpi_device_id elan_acpi_id[] = { { "ELAN0000", 0 }, + { "ELAN0100", 0 }, { "ELAN0600", 0 }, { } }; -- cgit v1.2.3 From 66bc2f51ef7deabc8b8f3baa98ae64b65e5e973a Mon Sep 17 00:00:00 2001 From: Stefan Assmann Date: Wed, 26 Aug 2015 13:11:49 -0700 Subject: Input: psmouse - add small delay for IBM trackpoint pass-through mode There are trackpoint devices that fail to respond to the PS2 command PSMOUSE_CMD_GETID if immediately queried after the parent device is deactivated. Add a small delay for the hardware to get in a sane state before sending any PS2 commands. One example of such a system is: Lenovo ThinkPad X120e, model 30515QG synaptics: Touchpad model: 1, fw: 8.0, id: 0x1e2b1, caps: 0xd001a3/0x940300/0x121c00, board id: 1811, fw id: 797391 Signed-off-by: Stefan Assmann Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/psmouse-base.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/input/mouse') diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index ec3477036150..ad18dab0ac47 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -1540,6 +1540,10 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) if (error) goto err_clear_drvdata; + /* give PT device some time to settle down before probing */ + if (serio->id.type == SERIO_PS_PSTHRU) + usleep_range(10000, 15000); + if (psmouse_probe(psmouse) < 0) { error = -ENODEV; goto err_close_serio; -- cgit v1.2.3 From 742f452b9b60c228a33e8d35fd2c74cd15bdaa29 Mon Sep 17 00:00:00 2001 From: Benson Leung Date: Fri, 28 Aug 2015 17:30:16 -0700 Subject: Input: elan_i2c - fix typos for validpage_count Search for "vaildpage_count" and replace with "validpage_count". Signed-off-by: Benson Leung Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elan_i2c_core.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/input/mouse') diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index bbdaedc09261..d4a38caa1ab1 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -84,7 +84,7 @@ struct elan_tp_data { int pressure_adjustment; u8 mode; u8 ic_type; - u16 fw_vaildpage_count; + u16 fw_validpage_count; u16 fw_signature_address; bool irq_wake; @@ -94,28 +94,28 @@ struct elan_tp_data { bool baseline_ready; }; -static int elan_get_fwinfo(u8 ic_type, u16 *vaildpage_count, +static int elan_get_fwinfo(u8 ic_type, u16 *validpage_count, u16 *signature_address) { switch(ic_type) { case 0x08: - *vaildpage_count = 512; + *validpage_count = 512; break; case 0x09: - *vaildpage_count = 768; + *validpage_count = 768; break; case 0x0D: - *vaildpage_count = 896; + *validpage_count = 896; break; default: /* unknown ic type clear value */ - *vaildpage_count = 0; + *validpage_count = 0; *signature_address = 0; return -ENXIO; } *signature_address = - (*vaildpage_count * ETP_FW_PAGE_SIZE) - ETP_FW_SIGNATURE_SIZE; + (*validpage_count * ETP_FW_PAGE_SIZE) - ETP_FW_SIGNATURE_SIZE; return 0; } @@ -264,7 +264,7 @@ static int elan_query_device_info(struct elan_tp_data *data) if (error) return error; - error = elan_get_fwinfo(data->ic_type, &data->fw_vaildpage_count, + error = elan_get_fwinfo(data->ic_type, &data->fw_validpage_count, &data->fw_signature_address); if (error) { dev_err(&data->client->dev, @@ -356,7 +356,7 @@ static int __elan_update_firmware(struct elan_tp_data *data, iap_start_addr = get_unaligned_le16(&fw->data[ETP_IAP_START_ADDR * 2]); boot_page_count = (iap_start_addr * 2) / ETP_FW_PAGE_SIZE; - for (i = boot_page_count; i < data->fw_vaildpage_count; i++) { + for (i = boot_page_count; i < data->fw_validpage_count; i++) { u16 checksum = 0; const u8 *page = &fw->data[i * ETP_FW_PAGE_SIZE]; -- cgit v1.2.3 From 58f1eae48e5372200553de07b5ecc7574803ee91 Mon Sep 17 00:00:00 2001 From: Duson Lin Date: Thu, 3 Sep 2015 09:46:45 -0700 Subject: Input: elan_i2c - use iap_version to get firmware information When driver is in IAP mode ic_type query may return 0xff. However iap_version will always be valid, so let's use it to determine parameters of the firmware that the controller is supposed to accept. Signed-off-by: Duson Lin Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elan_i2c_core.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/input/mouse') diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index d4a38caa1ab1..e2b7420eed97 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -4,7 +4,7 @@ * Copyright (c) 2013 ELAN Microelectronics Corp. * * Author: 林政維 (Duson Lin) - * Version: 1.5.9 + * Version: 1.6.0 * * Based on cyapa driver: * copyright (c) 2011-2012 Cypress Semiconductor, Inc. @@ -40,7 +40,7 @@ #include "elan_i2c.h" #define DRIVER_NAME "elan_i2c" -#define ELAN_DRIVER_VERSION "1.5.9" +#define ELAN_DRIVER_VERSION "1.6.0" #define ETP_MAX_PRESSURE 255 #define ETP_FWIDTH_REDUCE 90 #define ETP_FINGER_WIDTH 15 @@ -94,10 +94,10 @@ struct elan_tp_data { bool baseline_ready; }; -static int elan_get_fwinfo(u8 ic_type, u16 *validpage_count, +static int elan_get_fwinfo(u8 iap_version, u16 *validpage_count, u16 *signature_address) { - switch(ic_type) { + switch (iap_version) { case 0x08: *validpage_count = 512; break; @@ -264,11 +264,11 @@ static int elan_query_device_info(struct elan_tp_data *data) if (error) return error; - error = elan_get_fwinfo(data->ic_type, &data->fw_validpage_count, + error = elan_get_fwinfo(data->iap_version, &data->fw_validpage_count, &data->fw_signature_address); if (error) { dev_err(&data->client->dev, - "unknown ic type %d\n", data->ic_type); + "unknown iap version %d\n", data->iap_version); return error; } -- cgit v1.2.3