cap1106: add support for cap11xx variants
Subsystems (3)
v2 cover cap1106: add support for cap11xx variants
Changes from v1:
* Reworked various devices support to check product id for respective device.
* Added check for invalid zero channels.
* Renamed active-high option to more clear irq-active-high
* Use regmap_update_bits() instead of regmap_write_bits()
Matt Ranostay (2):
cap1106: Add support for various cap11xx devices
cap1106: support for irq-active-high option
.../devicetree/bindings/input/cap1106.txt | 4 ++ drivers/input/keyboard/cap1106.c | 70 ++++++++++++++++------ 2 files changed, 55 insertions(+), 19 deletions(-)
Signature · 1 line
1.9.1
PATCH v2 1/2 cap1106: Add support for various cap11xx devices
Several other variants of the cap11xx device exists with a varying number of capacitance detection channels. Add support for creating the channels dynamically.
--- drivers/input/keyboard/cap1106.c | 64 +++++++++++++++++++++++++++------------- 1 file changed, 44 insertions(+), 20 deletions(-)
drivers/input/keyboard/cap1106.c +44 -20
@@ -55,8 +55,6 @@#define CAP1106_REG_MANUFACTURER_ID 0xfe#define CAP1106_REG_REVISION 0xff -#define CAP1106_NUM_CHN 6 -#define CAP1106_PRODUCT_ID 0x55#define CAP1106_MANUFACTURER_ID 0x5dstruct cap1106_priv {
@@ -64,7 +62,25 @@ struct cap1106_priv {struct input_dev *idev;/* config */ -unsigned short keycodes[CAP1106_NUM_CHN ]; +u32 *keycodes; +unsigned int num_channels; +}; + +struct cap11xx_hw_model { +uint8_t product_id; +unsigned int num_channels; +}; + +enum { +CAP1106 , +CAP1126 , +CAP1188 , +}; + +struct cap11xx_hw_model cap11xx_devices[] = { + [CAP1106 ] = { .product_id =0x55 , .num_channels =6 }, + [CAP1126 ] = { .product_id =0x53 , .num_channels =6 }, + [CAP1188 ] = { .product_id =0x50 , .num_channels =8 }, };static const struct reg_default cap1106_reg_defaults[] = {
@@ -151,7 +167,7 @@ static irqreturn_t cap1106_thread_func(int irq_num, void *data)if (ret <0 ) goto out; -for (i =0 ; i <CAP1106_NUM_CHN ; i++) +for (i =0 ; i < priv->num_channels; i++)input_report_key (priv->idev, priv->keycodes[i], status & (1 << i));
@@ -188,14 +204,23 @@ static int cap1106_i2c_probe(struct i2c_client *i2c_client,struct device *dev = &i2c_client->dev;struct cap1106_priv *priv;struct device_node *node; +struct cap11xx_hw_model *cap = &cap11xx_devices[id->driver_data];int i, error, irq, gain =0 ;unsigned int val, rev; -u32 gain32, keycodes[CAP1106_NUM_CHN ]; +u32 gain32; priv =devm_kzalloc (dev,sizeof (*priv),GFP_KERNEL );if (!priv)return -ENOMEM ; +BUG_ON (!cap->num_channels); + + priv->num_channels = cap->num_channels; + priv->keycodes =devm_kcalloc (dev, + priv->num_channels,sizeof (u32),GFP_KERNEL ); +if (!priv->keycodes) +return -ENOMEM ; + priv->regmap =devm_regmap_init_i2c (i2c_client, &cap1106_regmap_config);if (IS_ERR (priv->regmap))return PTR_ERR (priv->regmap);
@@ -204,9 +229,9 @@ static int cap1106_i2c_probe(struct i2c_client *i2c_client,if (error)return error; -if (val !=CAP1106_PRODUCT_ID ) { +if (val != cap->product_id) {dev_err (dev,"Product ID: Got 0x%02x, expected 0x%02x\n" , - val,CAP1106_PRODUCT_ID ); + val, cap->product_id);return -ENODEV ; }
@@ -235,17 +260,12 @@ static int cap1106_i2c_probe(struct i2c_client *i2c_client,dev_err (dev,"Invalid sensor-gain value %d\n" , gain32); } -BUILD_BUG_ON (ARRAY_SIZE (keycodes) !=ARRAY_SIZE (priv->keycodes)); -/* Provide some useful defaults */ -for (i =0 ; i <ARRAY_SIZE (keycodes); i++) - keycodes[i] =KEY_A + i; +for (i =0 ; i < priv->num_channels; i++) + priv->keycodes[i] =KEY_A + i;of_property_read_u32_array (node,"linux,keycodes" , - keycodes,ARRAY_SIZE (keycodes)); - -for (i =0 ; i <ARRAY_SIZE (keycodes); i++) - priv->keycodes[i] = keycodes[i]; + priv->keycodes, priv->num_channels); error = regmap_update_bits(priv->regmap, CAP1106_REG_MAIN_CONTROL, CAP1106_REG_MAIN_CONTROL_GAIN_MASK,
@@ -269,17 +289,17 @@ static int cap1106_i2c_probe(struct i2c_client *i2c_client,if (of_property_read_bool (node,"autorepeat" ))__set_bit (EV_REP , priv->idev->evbit); -for (i =0 ; i <CAP1106_NUM_CHN ; i++) +for (i =0 ; i < priv->num_channels; i++)__set_bit (priv->keycodes[i], priv->idev->keybit);__clear_bit (KEY_RESERVED , priv->idev->keybit); priv->idev->keycode = priv->keycodes; - priv->idev->keycodesize =sizeof (priv->keycodes[0 ]); - priv->idev->keycodemax =ARRAY_SIZE (priv->keycodes); + priv->idev->keycodesize =sizeof (u32); + priv->idev->keycodemax = priv->num_channels; priv->idev->id.vendor =CAP1106_MANUFACTURER_ID ; - priv->idev->id.product =CAP1106_PRODUCT_ID ; + priv->idev->id.product = cap->product_id; priv->idev->id.version = rev; priv->idev->open = cap1106_input_open;
@@ -313,12 +333,16 @@ static int cap1106_i2c_probe(struct i2c_client *i2c_client,static const struct of_device_id cap1106_dt_ids[] = { { .compatible ="microchip,cap1106" , }, + { .compatible ="microchip,cap1126" , }, + { .compatible ="microchip,cap1188" , }, {} };MODULE_DEVICE_TABLE (of, cap1106_dt_ids);static const struct i2c_device_id cap1106_i2c_ids[] = { - {"cap1106" ,0 }, + {"cap1106" ,CAP1106 }, + {"cap1126" ,CAP1126 }, + {"cap1188" ,CAP1188 }, {} };MODULE_DEVICE_TABLE (i2c, cap1106_i2c_ids);
Signature · 1 line
1.9.1
Re: [PATCH v2 1/2] cap1106: Add support for various cap11xx devices
Quoted 24 lines · Matt Ranostay
drivers/input/keyboard/cap1106.c +6
-3@@ -55,8 +55,6 @@#define CAP1106_REG_MANUFACTURER_ID 0xfe#define CAP1106_REG_REVISION 0xff -#define CAP1106_NUM_CHN 6 -#define CAP1106_PRODUCT_ID 0x55#define CAP1106_MANUFACTURER_ID 0x5dstruct cap1106_priv {@@ -64,7 +62,25 @@ struct cap1106_priv {struct input_dev *idev;/* config */ -unsigned short keycodes[CAP1106_NUM_CHN ]; +u32 *keycodes; +unsigned int num_channels; +}; + +struct cap11xx_hw_model { +uint8_t product_id;
drivers/input/keyboard/cap1106.c struct cap1106_priv { · line 80
Quoted 10 lines
drivers/input/keyboard/cap1106.c +10
-0+unsigned int num_channels; +}; + +enum { +CAP1106 , +CAP1126 , +CAP1188 , +}; + +struct cap11xx_hw_model cap11xx_devices[] = {
This can be static const.
And, as I said, there should be a 3rd patch that renames the file and its functions, structs, defines etc to the more generic "11xx" variants.
Thanks,
Daniel
Re: [PATCH v2 1/2] cap1106: Add support for various cap11xx devices
Quoted 29 lines · Daniel Mack
Quoted 28 lines · Matt Ranostay
drivers/input/keyboard/cap1106.c +10
-3@@ -55,8 +55,6 @@#define CAP1106_REG_MANUFACTURER_ID 0xfe#define CAP1106_REG_REVISION 0xff -#define CAP1106_NUM_CHN 6 -#define CAP1106_PRODUCT_ID 0x55#define CAP1106_MANUFACTURER_ID 0x5dstruct cap1106_priv {@@ -64,7 +62,25 @@ struct cap1106_priv {struct input_dev *idev;/* config */ -unsigned short keycodes[CAP1106_NUM_CHN ]; +u32 *keycodes; +unsigned int num_channels; +}; + +struct cap11xx_hw_model { +uint8_t product_id; +unsigned int num_channels; +}; + +enum {
Quoted 9 lines
drivers/input/keyboard/cap1106.c struct cap1106_priv { · line 80
Quoted 6 lines
drivers/input/keyboard/cap1106.c +6
-0+CAP1106 , +CAP1126 , + CAP1188, +}; + +struct cap11xx_hw_model cap11xx_devices[] = {This can be static const.
D'oh how did I miss that?
Quoted 3 lines
And, as I said, there should be a 3rd patch that renames the file and its functions, structs, defines etc to the more generic "11xx" variants.
Ok will do and resubmit.
Quoted 4 lines
Thanks,
Daniel
PATCH v2 2/2 cap1106: support for irq-active-high option
In reply to Matt RanostaySome applications need to use the irq-active-high push-pull option. This allows it be enabled in the device tree child node.
--- Documentation/devicetree/bindings/input/cap1106.txt | 4 ++++ drivers/input/keyboard/cap1106.c | 8 ++++++++ 2 files changed, 12 insertions(+)
Documentation/devicetree/bindings/input/cap1106.txt +4 -0
@@ -26,6 +26,10 @@ Optional properties: Valid values are 1, 2, 4, and 8. By default, a gain of 1 is set. + microchip,irq-active-high: By default the interrupt pin is active low + open drain. This property allows using the active + high push-pull output. + linux,keycodes: Specifies an array of numeric keycode values to be used for the channels. If this property is omitted, KEY_A, KEY_B, etc are used as
drivers/input/keyboard/cap1106.c +8 -0
@@ -47,6 +47,7 @@#define CAP1106_REG_STANDBY_SENSITIVITY 0x42#define CAP1106_REG_STANDBY_THRESH 0x43#define CAP1106_REG_CONFIG2 0x44 +#define CAP1106_REG_CONFIG2_ALT_POL BIT(6)#define CAP1106_REG_SENSOR_BASE_CNT (X ) (0x50 + (X))#define CAP1106_REG_SENSOR_CALIB (0xb1 + (X))#define CAP1106_REG_SENSOR_CALIB_LSB1 0xb9
@@ -260,6 +261,13 @@ static int cap1106_i2c_probe(struct i2c_client *i2c_client,dev_err (dev,"Invalid sensor-gain value %d\n" , gain32); } +if (of_property_read_bool (node,"microchip,irq-active-high" )) { + error =regmap_update_bits (priv->regmap,CAP1106_REG_CONFIG2 , +CAP1106_REG_CONFIG2_ALT_POL ,0 ); +if (error) +return error; + } +/* Provide some useful defaults */ for (i =0 ; i < priv->num_channels; i++) priv->keycodes[i] =KEY_A + i;
Signature · 1 line
1.9.1