Re: [PATCH] Driver for AUO In-Cell touchscreens using pixcir ICs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, 2011-12-05 at 09:20 +0100, Heiko Stübner wrote:
> Hi Christoph,
> 
> thanks for taking the time to look it over.
> 
> comments below
> 
> Heiko
> Am Sonntag, 4. Dezember 2011, 14:31:41 schrieb Christoph Fritz:
> > Hi Heiko,
> > 
> >  you can find some annotations below.
> > 
> > Thanks,
> >  -- chf
> > 
> > On Sat, 2011-12-03 at 15:09 +0100, Heiko Stübner wrote:
> > > Some displays from AUO have a so called in-cell touchscreen, meaning it
> > > is built directly into the display unit.
> > > 
> > > Touchdata is gathered through PIXCIR Tango-ICs and processed in an
> > > Atmel ATmega168P with custom firmware. Communication between the host
> > > system and ATmega is done via I2C.
> > > 
> > > Devices using this touch solution include the Dell Streak5 and the family
> > > of Qisda ebook readers.
> > > 
> > > The driver reports single- and multi-touch events including touch area
> > > values.
> > > 
> > > Signed-off-by: Heiko Stuebner <heiko@xxxxxxxxx>
> > > ---
> > > 
> > >  drivers/input/touchscreen/Kconfig         |   14 +
> > >  drivers/input/touchscreen/Makefile        |    1 +
> > >  drivers/input/touchscreen/auo-pixcir-ts.c |  657
> > >  +++++++++++++++++++++++++++++ include/linux/input/auo-pixcir-ts.h      
> > >  |   57 +++
> > >  4 files changed, 729 insertions(+), 0 deletions(-)
> > >  create mode 100644 drivers/input/touchscreen/auo-pixcir-ts.c
> > >  create mode 100644 include/linux/input/auo-pixcir-ts.h
> 
> [...]
> 
> > > +
> > > +static int auo_pixcir_int_config(struct auo_pixcir_ts *ts, int
> > > int_setting) +{
> > > +	struct i2c_client *client = ts->client;
> > > +	struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data;
> > > +	uint8_t value;
> > > +
> > > +	value = i2c_smbus_read_byte_data(client, AUO_PIXCIR_REG_INT_SETTING);
> > > +	if (value < 0) {
> > 
> > value is an unsigned int and can't be less than zero. An int value would
> > be more appropriate.
> you're right of course and I will fix the type
> 
> > > +		dev_err(&client->dev, "unable to read reg %Xh, %d\n",
> > > +			AUO_PIXCIR_REG_INT_SETTING, value);
> > > +		return value;
> > > +	}
> > > +
> > > +	value &= (~AUO_PIXCIR_INT_MODE_MASK);
> > > +	value |= int_setting;
> > > +	value |= AUO_PIXCIR_INT_POL_HIGH; /* always use high for interrupts 
> */
> > > +
> > > +	value = i2c_smbus_write_byte_data(client, AUO_PIXCIR_REG_INT_SETTING,
> > > +					  value);
> > > +	if (value < 0) {
> > 
> > the same here
> here too
> 
> [...]
> 
> > > +static int __devinit auo_pixcir_probe(struct i2c_client *client,
> > > +				      const struct i2c_device_id *id)
> > > +{
> > > +	struct auo_pixcir_ts *ts;
> > > +	struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data;
> > > +	struct input_dev *input_dev;
> > > +	int ret;
> > > +
> > > +	if (!pdata)
> > > +		return -EINVAL;
> > > +
> > > +	ts = kzalloc(sizeof(struct auo_pixcir_ts), GFP_KERNEL);
> > > +	if (!ts)
> > > +		return -ENOMEM;
> > > +
> > > +	ret = gpio_request(pdata->gpio_int, "auo_pixcir_ts_int");
> > > +	if (ret) {
> > > +		dev_err(&client->dev, "request of gpio %d failed, %d\n",
> > > +			pdata->gpio_int, ret);
> > > +		goto err_gpio_int;
> > > +	}
> > > +
> > > +	ret = gpio_request(pdata->gpio_rst, "auo_pixcir_ts_rst");
> > > +	if (ret) {
> > > +		dev_err(&client->dev, "request of gpio %d failed, %d\n",
> > > +			pdata->gpio_int, ret);
> > > +		goto err_gpio_rst;
> > > +	}
> > > +
> > > +	if (pdata->init_hw)
> > > +		pdata->init_hw();
> > > +
> > > +	ts->client = client;
> > > +	ts->touch_ind_mode = 0;
> > > +	init_waitqueue_head(&ts->wait);
> > > +
> > > +	snprintf(ts->phys, sizeof(ts->phys),
> > > +		 "%s/input0", dev_name(&client->dev));
> > > +
> > > +	input_dev = input_allocate_device();
> > > +	if (!input_dev) {
> > > +		dev_err(&client->dev, "could not allocate input device\n");
> > > +		goto err_input_alloc;
> > > +	}
> > > +
> > > +	ts->input = input_dev;
> > > +
> > > +	input_dev->name = "auo_pixcir_ts";
> > > +	input_dev->phys = ts->phys;
> > > +	input_dev->id.bustype = BUS_I2C;
> > > +	input_dev->dev.parent = &client->dev;
> > > +
> > > +	input_dev->open = auo_pixcir_input_open;
> > > +	input_dev->close = auo_pixcir_input_close;
> > > +
> > > +	__set_bit(EV_ABS, input_dev->evbit);
> > > +	__set_bit(EV_KEY, input_dev->evbit);
> > > +
> > > +	__set_bit(BTN_TOUCH, input_dev->keybit);
> > > +
> > > +	/* For single touch */
> > > +	input_set_abs_params(input_dev, ABS_X, 0, pdata->x_max, 0, 0);
> > > +	input_set_abs_params(input_dev, ABS_Y, 0, pdata->y_max, 0, 0);
> > > +
> > > +	/* For multi touch */
> > > +	input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0,
> > > +			     pdata->x_max, 0, 0);
> > > +	input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0,
> > > +			     pdata->y_max, 0, 0);
> > > +	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0,
> > > +			     AUO_PIXCIR_MAX_AREA, 0, 0);
> > > +	input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR, 0,
> > > +			     AUO_PIXCIR_MAX_AREA, 0, 0);
> > > +	input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0);
> > > +
> > > +	ret = i2c_smbus_read_byte_data(client, AUO_PIXCIR_REG_VERSION);
> > > +	if (ret < 0)
> > > +		goto err_fw_vers;
> > > +	dev_info(&client->dev, "firmware version 0x%X\n", ret);
> > > +
> > > +	ret = auo_pixcir_int_config(ts, pdata->int_setting);
> > > +	if (ret)
> > > +		goto err_fw_vers;
> > > +
> > > +	/* disable irqs on the device side before irq-request */
> > > +	auo_pixcir_int_enable(ts, 0);
> > > +	ts->stopped = true;
> > > +	ts->is_open = false;
> > > +
> > > +	ret = request_threaded_irq(client->irq, NULL, auo_pixcir_interrupt,
> > > +				   IRQF_TRIGGER_RISING | IRQF_ONESHOT,
> > > +				   input_dev->name, ts);
> > > +	if (ret) {
> > > +		dev_err(&client->dev, "irq %d requested failed\n", client->irq);
> > > +		goto err_fw_vers;
> > > +	}
> > > +
> > > +	/* stop device and put it into deep sleep until it is opened */
> > > +	ret = auo_pixcir_stop(ts);
> > > +	if (ret < 0)
> > > +		goto err_input_register;
> > > +
> > > +	ret = input_register_device(input_dev);
> > > +	if (ret) {
> > > +		dev_err(&client->dev, "could not register input device\n");
> > > +		goto err_input_register;
> > > +	}
> > > +
> > > +	input_set_drvdata(ts->input, ts);
> > > +
> > > +	i2c_set_clientdata(client, ts);
> > > +
> > > +	return 0;
> > > +
> > > +err_input_register:
> > > +	free_irq(client->irq, ts);
> > > +err_fw_vers:
> > > +	input_free_device(input_dev);
> > > +err_input_alloc:
> > > +	if (pdata->exit_hw)
> > > +		pdata->exit_hw();
> > > +	gpio_free(pdata->gpio_rst);
> > > +err_gpio_rst:
> > > +	gpio_free(pdata->gpio_int);
> > > +err_gpio_int:
> > > +	kfree(ts);
> > > +
> > > +	return ret;
> > > +}
> > > +
> > > +static int __devexit auo_pixcir_remove(struct i2c_client *client)
> > > +{
> > > +	struct auo_pixcir_ts *ts = (struct auo_pixcir_ts *)
> > > +						i2c_get_clientdata(client);
> > > +	struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data;
> > > +
> > > +	auo_pixcir_stop(ts);
> > > +
> > > +	free_irq(client->irq, ts);
> > > +
> > > +	input_unregister_device(ts->input);
> > > +	input_free_device(ts->input);
> > 
> > to quote input.c:
> > 
> > /**
> >  * input_free_device - free memory occupied by input_dev structure
> >  * @dev: input device to free
> >  *
> >  * This function should only be used if input_register_device()
> >  * was not called yet or if it failed. Once device was registered
> >  * use input_unregister_device() and memory will be freed once last
> >  * reference to the device is dropped.
> >  *
> >  * Device should be allocated by input_allocate_device().
> >  *
> >  * NOTE: If there are references to the input device then memory
> >  * will not be freed until last reference is dropped.
> >  */
> thanks for this quote and I will remove the input_free_device call.
> 
> 
> > the same applies to the error path in auo_pixcir_probe()
> according to the docs your quoted this wouldn't be the same, as 
> input_free_device is called in _probe either before the input_register_device 
> call or if the call to it failed.

Yes, it's done right.

 Thanks,
   -- chf


--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux