Ejemplo n.º 1
0
static int tca6416_setup_registers(struct tca6416_keypad_chip *chip)
{
	int error;

	error = tca6416_read_reg(chip, TCA6416_OUTPUT, &chip->reg_output);
	if (error)
		return error;

	error = tca6416_read_reg(chip, TCA6416_DIRECTION, &chip->reg_direction);
	if (error)
		return error;

	/* ensure that keypad pins are set to input */
	error = tca6416_write_reg(chip, TCA6416_DIRECTION,
				  chip->reg_direction | chip->pinmask);
	if (error)
		return error;

	error = tca6416_read_reg(chip, TCA6416_DIRECTION, &chip->reg_direction);
	if (error)
		return error;

	error = tca6416_read_reg(chip, TCA6416_INPUT, &chip->reg_input);
	if (error)
		return error;

	chip->reg_input &= chip->pinmask;

	return 0;
}
Ejemplo n.º 2
0
static int __devinit tca6416_keypad_probe(struct i2c_client *client,
				   const struct i2c_device_id *id)
{
	struct tca6416_keys_platform_data *pdata;
	struct tca6416_keypad_chip *chip;
	struct tca6416_drv_data *ddata;
	struct input_dev *input;
	int i, ret, pin_index;
	uint16_t reg_val;

	chip = kzalloc(sizeof(struct tca6416_keypad_chip), GFP_KERNEL);
	if (chip == NULL)
		return -ENOMEM;

	pdata = client->dev.platform_data;
	if (pdata == NULL) {
		dev_dbg(&client->dev, "no platform data\n");
		ret = -EINVAL;
		goto fail1;
	}

	chip->client = client;
	chip->pinmask = pdata->pinmask;

	/* initialize cached registers from their original values.
	 * we can't share this chip with another i2c master.
	 */
	ret = tca6416_read_reg(chip, TCA6416_OUTPUT, &chip->reg_output);
	if (ret)
		goto fail1;

	ret = tca6416_read_reg(chip, TCA6416_DIRECTION, &chip->reg_direction);
	if (ret)
		goto fail1;

	/* ensure that keypad pins are set to input */
	reg_val = chip->reg_direction | chip->pinmask;
	ret = tca6416_write_reg(chip, TCA6416_DIRECTION, reg_val);

	ret = tca6416_read_reg(chip, TCA6416_DIRECTION, &chip->reg_direction);
	if (ret)
		goto fail1;

	ret = tca6416_read_reg(chip, TCA6416_INPUT, &chip->reg_input);
	if (ret)
		goto fail1;

	i2c_set_clientdata(client, chip);


	ddata = kzalloc(sizeof(struct tca6416_drv_data) +
			pdata->nbuttons * sizeof(struct tca6416_button_data),
			GFP_KERNEL);
	if(!ddata) {
		ret = -ENOMEM;
		goto fail1;
	}

	input = input_allocate_device();
	if (!input) {
		printk("failed to allocate state\n");
		ret = -ENOMEM;
		kfree(ddata);
		goto fail2;
	}

	input->phys = "tca6416-keys/input0";
	input->dev.parent = &client->dev;

	input->id.bustype = BUS_HOST;
	input->id.vendor = 0x0001;
	input->id.product = 0x0001;
	input->id.version = 0x0100;

	/* Enable auto repeat feature of Linux input subsystem */
	if (pdata->rep)
		__set_bit(EV_REP, input->evbit);

	ddata->input = input;

	for (i = 0; i < pdata->nbuttons; i++) {
		struct gpio_keys_button *button = &pdata->buttons[i];
		struct tca6416_button_data *bdata = &ddata->data[i];
		unsigned int type = button->type ?: EV_KEY;

		bdata->input = input;
		bdata->button = button;

		input_set_capability(input, type, button->code);
	}

	chip->drv_data = ddata;
	chip->use_polling = pdata->use_polling;

	INIT_DELAYED_WORK(&chip->dwork, tca6416_keys_work_func);

	if (!chip->use_polling){
		if(pdata->irq_is_gpio)
			chip->irqnum = gpio_to_irq(pdata->irqnum);
		else
			chip->irqnum = pdata->irqnum;

		ret = request_irq(chip->irqnum, tca6416_keys_isr,
				IRQF_SHARED |
				IRQF_TRIGGER_FALLING ,
				"tca6416-keypad", chip);
		if (ret) {
			printk( "Unable to claim irq %d; error %d\n",
				chip->irqnum, ret);
			goto fail3;
		}
		disable_irq(chip->irqnum);
	}

	ret = input_register_device(input);
	if (ret) {
		printk( "Unable to register input device, "
			"error: %d\n", ret);
		goto fail3;
	}

	/* get current state of buttons */

	ret = tca6416_read_reg(chip, TCA6416_INPUT, &reg_val);
	chip->reg_input = reg_val & chip->pinmask;

	for (i = 0, pin_index = 0; i < 16; i++){
		if(chip->pinmask & (1 << i) ){
		struct tca6416_button_data * tca_button = &ddata->data[pin_index];
		struct gpio_keys_button * button = tca_button->button;
		struct input_dev *input = tca_button->input;
		unsigned int type = button->type ?: EV_KEY;
		int state = ((reg_val & (1 << i)) ? 1 : 0) ^ button->active_low;

			input_event(input, type, button->code, !!state);
			input_sync(input);
			pin_index++;
		}
	}
	input_sync(input);

	if(chip->use_polling)
		schedule_delayed_work(&chip->dwork, msecs_to_jiffies(100));
	else
		enable_irq(chip->irqnum);

	return 0;
fail3:
	input_free_device(input);
fail2:
	kfree(ddata);
fail1:
	kfree(chip);
	return ret;
}