diff options
Diffstat (limited to 'drivers/input/keyboard/tca8418_keypad.c')
| -rw-r--r-- | drivers/input/keyboard/tca8418_keypad.c | 179 | 
1 files changed, 84 insertions, 95 deletions
diff --git a/drivers/input/keyboard/tca8418_keypad.c b/drivers/input/keyboard/tca8418_keypad.c index 893869b29ed..a34cc6714e5 100644 --- a/drivers/input/keyboard/tca8418_keypad.c +++ b/drivers/input/keyboard/tca8418_keypad.c @@ -35,6 +35,7 @@  #include <linux/i2c.h>  #include <linux/input.h>  #include <linux/input/tca8418_keypad.h> +#include <linux/of.h>  /* TCA8418 hardware limits */  #define TCA8418_MAX_ROWS	8 @@ -109,25 +110,11 @@  #define KEY_EVENT_CODE		0x7f  #define KEY_EVENT_VALUE		0x80 - -static const struct i2c_device_id tca8418_id[] = { -	{ TCA8418_NAME, 8418, }, -	{ } -}; -MODULE_DEVICE_TABLE(i2c, tca8418_id); -  struct tca8418_keypad { -	unsigned int rows; -	unsigned int cols; -	unsigned int keypad_mask; /* Mask for keypad col/rol regs */ -	unsigned int irq; -	unsigned int row_shift; -  	struct i2c_client *client;  	struct input_dev *input; -	/* Flexible array member, must be at end of struct */ -	unsigned short keymap[]; +	unsigned int row_shift;  };  /* @@ -172,6 +159,8 @@ static int tca8418_read_byte(struct tca8418_keypad *keypad_data,  static void tca8418_read_keypad(struct tca8418_keypad *keypad_data)  { +	struct input_dev *input = keypad_data->input; +	unsigned short *keymap = input->keycode;  	int error, col, row;  	u8 reg, state, code; @@ -190,9 +179,8 @@ static void tca8418_read_keypad(struct tca8418_keypad *keypad_data)  		col = (col) ? col - 1 : TCA8418_MAX_COLS - 1;  		code = MATRIX_SCAN_CODE(row, col, keypad_data->row_shift); -		input_event(keypad_data->input, EV_MSC, MSC_SCAN, code); -		input_report_key(keypad_data->input, -				keypad_data->keymap[code], state); +		input_event(input, EV_MSC, MSC_SCAN, code); +		input_report_key(input, keymap[code], state);  		/* Read for next loop */  		error = tca8418_read_byte(keypad_data, REG_KEY_EVENT_A, ®); @@ -202,7 +190,7 @@ static void tca8418_read_keypad(struct tca8418_keypad *keypad_data)  		dev_err(&keypad_data->client->dev,  			"unable to read REG_KEY_EVENT_A\n"); -	input_sync(keypad_data->input); +	input_sync(input);  }  /* @@ -218,16 +206,18 @@ static irqreturn_t tca8418_irq_handler(int irq, void *dev_id)  	if (error) {  		dev_err(&keypad_data->client->dev,  			"unable to read REG_INT_STAT\n"); -		goto exit; +		return IRQ_NONE;  	} +	if (!reg) +		return IRQ_NONE; +  	if (reg & INT_STAT_OVR_FLOW_INT)  		dev_warn(&keypad_data->client->dev, "overflow occurred\n");  	if (reg & INT_STAT_K_INT)  		tca8418_read_keypad(keypad_data); -exit:  	/* Clear all interrupts, even IRQs we didn't check (GPI, CAD, LCK) */  	reg = 0xff;  	error = tca8418_write_byte(keypad_data, REG_INT_STAT, reg); @@ -241,7 +231,8 @@ exit:  /*   * Configure the TCA8418 for keypad operation   */ -static int __devinit tca8418_configure(struct tca8418_keypad *keypad_data) +static int tca8418_configure(struct tca8418_keypad *keypad_data, +			     u32 rows, u32 cols)  {  	int reg, error; @@ -253,9 +244,8 @@ static int __devinit tca8418_configure(struct tca8418_keypad *keypad_data)  	/* Assemble a mask for row and column registers */ -	reg  =  ~(~0 << keypad_data->rows); -	reg += (~(~0 << keypad_data->cols)) << 8; -	keypad_data->keypad_mask = reg; +	reg  =  ~(~0 << rows); +	reg += (~(~0 << cols)) << 8;  	/* Set registers to keypad mode */  	error |= tca8418_write_byte(keypad_data, REG_KP_GPIO1, reg); @@ -270,145 +260,144 @@ static int __devinit tca8418_configure(struct tca8418_keypad *keypad_data)  	return error;  } -static int __devinit tca8418_keypad_probe(struct i2c_client *client, +static int tca8418_keypad_probe(struct i2c_client *client,  					  const struct i2c_device_id *id)  { +	struct device *dev = &client->dev;  	const struct tca8418_keypad_platform_data *pdata = -						client->dev.platform_data; +						dev_get_platdata(dev);  	struct tca8418_keypad *keypad_data;  	struct input_dev *input; +	const struct matrix_keymap_data *keymap_data = NULL; +	u32 rows = 0, cols = 0; +	bool rep = false; +	bool irq_is_gpio = false; +	int irq;  	int error, row_shift, max_keys;  	/* Copy the platform data */ -	if (!pdata) { -		dev_dbg(&client->dev, "no platform data\n"); -		return -EINVAL; -	} - -	if (!pdata->keymap_data) { -		dev_err(&client->dev, "no keymap data defined\n"); -		return -EINVAL; +	if (pdata) { +		if (!pdata->keymap_data) { +			dev_err(dev, "no keymap data defined\n"); +			return -EINVAL; +		} +		keymap_data = pdata->keymap_data; +		rows = pdata->rows; +		cols = pdata->cols; +		rep  = pdata->rep; +		irq_is_gpio = pdata->irq_is_gpio; +	} else { +		struct device_node *np = dev->of_node; +		of_property_read_u32(np, "keypad,num-rows", &rows); +		of_property_read_u32(np, "keypad,num-columns", &cols); +		rep = of_property_read_bool(np, "keypad,autorepeat");  	} -	if (!pdata->rows || pdata->rows > TCA8418_MAX_ROWS) { -		dev_err(&client->dev, "invalid rows\n"); +	if (!rows || rows > TCA8418_MAX_ROWS) { +		dev_err(dev, "invalid rows\n");  		return -EINVAL;  	} -	if (!pdata->cols || pdata->cols > TCA8418_MAX_COLS) { -		dev_err(&client->dev, "invalid columns\n"); +	if (!cols || cols > TCA8418_MAX_COLS) { +		dev_err(dev, "invalid columns\n");  		return -EINVAL;  	}  	/* Check i2c driver capabilities */  	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE)) { -		dev_err(&client->dev, "%s adapter not supported\n", +		dev_err(dev, "%s adapter not supported\n",  			dev_driver_string(&client->adapter->dev));  		return -ENODEV;  	} -	row_shift = get_count_order(pdata->cols); -	max_keys = pdata->rows << row_shift; +	row_shift = get_count_order(cols); +	max_keys = rows << row_shift; -	/* Allocate memory for keypad_data, keymap and input device */ -	keypad_data = kzalloc(sizeof(*keypad_data) + -			max_keys * sizeof(keypad_data->keymap[0]), GFP_KERNEL); +	/* Allocate memory for keypad_data and input device */ +	keypad_data = devm_kzalloc(dev, sizeof(*keypad_data), GFP_KERNEL);  	if (!keypad_data)  		return -ENOMEM; -	keypad_data->rows = pdata->rows; -	keypad_data->cols = pdata->cols;  	keypad_data->client = client;  	keypad_data->row_shift = row_shift;  	/* Initialize the chip or fail if chip isn't present */ -	error = tca8418_configure(keypad_data); +	error = tca8418_configure(keypad_data, rows, cols);  	if (error < 0) -		goto fail1; +		return error;  	/* Configure input device */ -	input = input_allocate_device(); -	if (!input) { -		error = -ENOMEM; -		goto fail1; -	} +	input = devm_input_allocate_device(dev); +	if (!input) +		return -ENOMEM; +  	keypad_data->input = input;  	input->name = client->name; -	input->dev.parent = &client->dev; -  	input->id.bustype = BUS_I2C;  	input->id.vendor  = 0x0001;  	input->id.product = 0x001;  	input->id.version = 0x0001; -	error = matrix_keypad_build_keymap(pdata->keymap_data, NULL, -					   pdata->rows, pdata->cols, -					   keypad_data->keymap, input); +	error = matrix_keypad_build_keymap(keymap_data, NULL, rows, cols, +					   NULL, input);  	if (error) { -		dev_dbg(&client->dev, "Failed to build keymap\n"); -		goto fail2; +		dev_err(dev, "Failed to build keymap\n"); +		return error;  	} -	if (pdata->rep) +	if (rep)  		__set_bit(EV_REP, input->evbit);  	input_set_capability(input, EV_MSC, MSC_SCAN);  	input_set_drvdata(input, keypad_data); -	if (pdata->irq_is_gpio) -		client->irq = gpio_to_irq(client->irq); +	irq = client->irq; +	if (irq_is_gpio) +		irq = gpio_to_irq(irq); -	error = request_threaded_irq(client->irq, NULL, tca8418_irq_handler, -				     IRQF_TRIGGER_FALLING | IRQF_ONESHOT, -				     client->name, keypad_data); +	error = devm_request_threaded_irq(dev, irq, NULL, tca8418_irq_handler, +					  IRQF_TRIGGER_FALLING | +						IRQF_SHARED | +						IRQF_ONESHOT, +					  client->name, keypad_data);  	if (error) { -		dev_dbg(&client->dev, -			"Unable to claim irq %d; error %d\n", +		dev_err(dev, "Unable to claim irq %d; error %d\n",  			client->irq, error); -		goto fail2; +		return error;  	}  	error = input_register_device(input);  	if (error) { -		dev_dbg(&client->dev, -			"Unable to register input device, error: %d\n", error); -		goto fail3; +		dev_err(dev, "Unable to register input device, error: %d\n", +			error); +		return error;  	} -	i2c_set_clientdata(client, keypad_data);  	return 0; - -fail3: -	free_irq(client->irq, keypad_data); -fail2: -	input_free_device(input); -fail1: -	kfree(keypad_data); -	return error;  } -static int __devexit tca8418_keypad_remove(struct i2c_client *client) -{ -	struct tca8418_keypad *keypad_data = i2c_get_clientdata(client); - -	free_irq(keypad_data->client->irq, keypad_data); - -	input_unregister_device(keypad_data->input); - -	kfree(keypad_data); - -	return 0; -} +static const struct i2c_device_id tca8418_id[] = { +	{ TCA8418_NAME, 8418, }, +	{ } +}; +MODULE_DEVICE_TABLE(i2c, tca8418_id); +#ifdef CONFIG_OF +static const struct of_device_id tca8418_dt_ids[] = { +	{ .compatible = "ti,tca8418", }, +	{ } +}; +MODULE_DEVICE_TABLE(of, tca8418_dt_ids); +#endif  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, -	.remove		= __devexit_p(tca8418_keypad_remove),  	.id_table	= tca8418_id,  };  |