RE: [Uclinux-dist-devel] [PATCH 2/2] add ad714x input driver forbutton/scrollwhell/slider/touchpad

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

 



 

>-----Original Message-----
>From: uclinux-dist-devel-bounces@xxxxxxxxxxxxxxxxxxxx 
>[mailto:uclinux-dist-devel-bounces@xxxxxxxxxxxxxxxxxxxx] On 
>Behalf Of David Brownell
>Sent: Wednesday, September 02, 2009 9:52 AM
>To: Barry Song
>Cc: dbrownell@xxxxxxxxxxxxxxxxxxxxx; dtor@xxxxxxx; 
>dmitry.torokhov@xxxxxxxxx; 
>spi-devel-general@xxxxxxxxxxxxxxxxxxxxx; 
>linux-input@xxxxxxxxxxxxxxx; uclinux-dist-devel@xxxxxxxxxxxxxxxxxxxx
>Subject: Re: [Uclinux-dist-devel] [PATCH 2/2] add ad714x input 
>driver forbutton/scrollwhell/slider/touchpad
>
>On Monday 31 August 2009, Barry Song wrote:
>> +
>> +#define AD714x_SPI_ADDR        0x1C
>> +#define AD714x_SPI_ADDR_SHFT   11
>> +#define AD714x_SPI_READ        1
>> +#define AD714x_SPI_READ_SHFT   10
>
>Confusing; it is not an address but a fixed bit pattern
>flagging command words.  Be less opaque; maybe
>
>  #define AD714x_CMD_PREFIX       0xe000   /* bits 15:11 */
>  #define AD714x_READ             BIT(10)
>
>
>> +#if defined(CONFIG_INPUT_AD714X_SPI)
>> +#define bus_device		struct spi_device
>> +#elif defined(CONFIG_INPUT_AD714X_I2C)
>> +#define bus_device		struct i2c_client
>> +#else
>> +#error Communication method needs to be selected (I2C or SPI)
>> +#endif
>
>Best to allow both interfaces in the same kernel, for build
>tests and kernels that can run on more than one board.
>
>The way that works in some contexts is to record
>
>	struct device *dev;
>
>(or somesuch) in the driver state struct and use it pretty much
>everywhere (including dev_* messaging!) except bus-related code
>which uses to_i2c_client() or to_spi_device() to get the right
>pointer view.
>
>And the (missing) Kconfig would depend on "SPI || I2C"; and this
>driver would register (and unregister) either or both driver
>facets depending on which were possible.  (Someone might even
>provide stubs for the I2C=n or SPI=n cases, to let such drivers
>avoid #ifdeffery.  Someday.)

Great Idea. I will enable the two buses at the same time. 
But in fact, I2C=n or SPI=n is not necessary because matched spi/i2c
name should trigger the probe called multi-times if there are
multi-devices. But those devices have different hardware resources.

>
>
>> +	pr_debug("slider %d absolute position:%d\n", idx, sw->abs_pos);
>
>You should use the dev_*() functions not pr_*().
>
>
>> +#define RIGHT_END_POINT_DETECTION_LEVEL			750
>> +#define LEFT_RIGHT_END_POINT_DEAVTIVALION_LEVEL		850
>> +#define TOP_END_POINT_DETECTION_LEVEL			550
>> +#define BOTTOM_END_POINT_DETECTION_LEVEL		950
>> +#define TOP_BOTTOM_END_POINT_DEAVTIVALION_LEVEL		700
>> +static int touchpad_check_endpoint(struct ad714x_chip 
>*ad714x, int idx)
>> +{
>
>Here and elsewhere:  whitespace between CPP directives and
>the Real Code (tm), please...
>
>
>> +#define MAX_DEVICE_NUM 8
>> +static int __devinit ad714x_probe(struct ad714x_chip *ad714x)
>> +{
>> +	int ret = 0;
>> +	struct input_dev *input[MAX_DEVICE_NUM];
>> +
>> +	struct ad714x_driver_data *drv_data = NULL;
>> +
>> +	struct ad714x_button_plat *bt_plat   = ad714x->hw->button;
>> +	struct ad714x_slider_plat *sd_plat   = ad714x->hw->slider;
>> +	struct ad714x_wheel_plat *wl_plat    = ad714x->hw->wheel;
>> +	struct ad714x_touchpad_plat *tp_plat = ad714x->hw->touchpad;
>> +
>> +	struct ad714x_button_drv *bt_drv   = NULL;
>> +	struct ad714x_slider_drv *sd_drv   = NULL;
>> +	struct ad714x_wheel_drv *wl_drv    = NULL;
>> +	struct ad714x_touchpad_drv *tp_drv = NULL;
>> +
>> +	int alloc_idx = 0, reg_idx = 0;
>> +	int i;
>> +
>> +	ret = ad714x_hw_detect(ad714x);
>> +	if (ret)
>> +		goto det_err;
>> +
>> +	/*
>> +	 * Allocate and register AD714x input device
>> +	 */
>> +
>> +	drv_data = kzalloc(sizeof(struct ad714x_driver_data), 
>GFP_KERNEL);
>
>drv_data is not an input device.
>
>
>> +	if (!drv_data) {
>> +		dev_err(&ad714x->bus->dev,
>> +			"Can't allocate memory for ad714x 
>driver info\n");
>> +		ret = -ENOMEM;
>> +		goto fail_alloc_reg;
>> +	}
>> +	ad714x->sw = drv_data;
>> +
>> +	/* a slider uses one input_dev instance */
>> +	if (ad714x->hw->slider_num > 0) {
>> +		sd_drv = kzalloc(sizeof(struct ad714x_slider_drv) *
>> +				ad714x->hw->slider_num, GFP_KERNEL);
>> +		if (!sd_drv) {
>> +			dev_err(&ad714x->bus->dev,
>> +				"Can't allocate memory for 
>slider info\n");
>> +			ret = -ENOMEM;
>> +			goto fail_alloc_reg;
>> +		}
>> +
>> +		for (i = 0; i < ad714x->hw->slider_num; i++) {
>> +			input[alloc_idx] = input_allocate_device();
>> +			if (!input[alloc_idx]) {
>> +				dev_err(&ad714x->bus->dev,
>> +				"Can't allocate input device 
>%d\n", alloc_idx);
>> +				ret = -ENOMEM;
>> +				goto fail_alloc_reg;
>> +			}
>> +			alloc_idx++;
>> +
>> +			__set_bit(EV_ABS, input[alloc_idx-1]->evbit);
>> +			__set_bit(ABS_X, input[alloc_idx-1]->absbit);
>> +			__set_bit(ABS_PRESSURE, 
>input[alloc_idx-1]->absbit);
>> +			
>input_set_abs_params(input[alloc_idx-1], ABS_X, 0,
>> +					sd_plat->max_coord, 0, 0);
>> +			
>input_set_abs_params(input[alloc_idx-1], ABS_PRESSURE,
>> +				0, 1, 0, 0);
>> +
>> +			input[alloc_idx-1]->id.bustype = BUS_I2C;
>
>This could be SPI instead... and there are some fields you
>forgot to set.  Like the ones putting this into the device tree
>in the right spot, and some identifiers...
>
>Take that bus type code as an input param to this function.
>
>
>> +
>> +			ret = input_register_device(input[reg_idx]);
>> +			if (ret) {
>> +				dev_err(&ad714x->bus->dev,
>> +				"Failed to register AD714x 
>input device!\n");
>> +				goto fail_alloc_reg;
>> +			}
>> +			reg_idx++;
>> +
>> +			sd_drv[i].input = input[alloc_idx-1];
>> +			ad714x->sw->slider = sd_drv;
>> +		}
>> +	}
>> +
>> +	/* a wheel uses one input_dev instance */
>> +	if (ad714x->hw->wheel_num > 0) {
>> +		wl_drv = kzalloc(sizeof(struct ad714x_wheel_drv) *
>> +				ad714x->hw->wheel_num, GFP_KERNEL);
>> +		if (!wl_drv) {
>> +			dev_err(&ad714x->bus->dev,
>> +				"Can't allocate memory for 
>wheel info\n");
>> +			ret = -ENOMEM;
>> +			goto fail_alloc_reg;
>> +		}
>> +
>> +		for (i = 0; i < ad714x->hw->wheel_num; i++) {
>> +			input[alloc_idx] = input_allocate_device();
>> +			if (!input[alloc_idx]) {
>> +				dev_err(&ad714x->bus->dev,
>> +				"Can't allocate input device 
>%d\n", alloc_idx);
>> +				ret = -ENOMEM;
>> +				goto fail_alloc_reg;
>> +			}
>> +			alloc_idx++;
>> +
>> +			__set_bit(EV_ABS, input[alloc_idx-1]->evbit);
>> +			__set_bit(ABS_WHEEL, 
>input[alloc_idx-1]->absbit);
>> +			__set_bit(ABS_PRESSURE, 
>input[alloc_idx-1]->absbit);
>> +			
>input_set_abs_params(input[alloc_idx-1], ABS_WHEEL, 0,
>> +					wl_plat->max_coord, 0, 0);
>> +			
>input_set_abs_params(input[alloc_idx-1], ABS_PRESSURE,
>> +				0, 1, 0, 0);
>> +
>> +			input[alloc_idx-1]->id.bustype = BUS_I2C;
>
>Same as above:  it's not necessarily I2C, and there are important
>fields left uninitialized.  Probably worth abstracting that setup
>into some kind of helper.
>
>
>> +
>> +			ret = input_register_device(input[reg_idx]);
>> +			if (ret) {
>> +				dev_err(&ad714x->bus->dev,
>> +				"Failed to register AD714x 
>input device!\n");
>> +				goto fail_alloc_reg;
>> +			}
>> +			reg_idx++;
>> +
>> +			wl_drv[i].input = input[alloc_idx-1];
>> +			ad714x->sw->wheel = wl_drv;
>> +		}
>> +	}
>> +
>> +	/* a touchpad uses one input_dev instance */
>> +	if (ad714x->hw->touchpad_num > 0) {
>> +		tp_drv = kzalloc(sizeof(struct ad714x_touchpad_drv) *
>> +				ad714x->hw->touchpad_num, GFP_KERNEL);
>> +		if (!tp_drv) {
>> +			dev_err(&ad714x->bus->dev,
>> +				"Can't allocate memory for 
>touchpad info\n");
>> +			ret = -ENOMEM;
>> +			goto fail_alloc_reg;
>> +		}
>> +
>> +		for (i = 0; i < ad714x->hw->touchpad_num; i++) {
>> +			input[alloc_idx] = input_allocate_device();
>> +			if (!input[alloc_idx]) {
>> +				dev_err(&ad714x->bus->dev,
>> +					"Can't allocate input 
>device %d\n",
>> +					alloc_idx);
>> +				ret = -ENOMEM;
>> +				goto fail_alloc_reg;
>> +			}
>> +			alloc_idx++;
>> +
>> +			__set_bit(EV_ABS, input[alloc_idx-1]->evbit);
>> +			__set_bit(ABS_X, input[alloc_idx-1]->absbit);
>> +			__set_bit(ABS_Y, input[alloc_idx-1]->absbit);
>> +			__set_bit(ABS_PRESSURE, 
>input[alloc_idx-1]->absbit);
>> +			
>input_set_abs_params(input[alloc_idx-1], ABS_X, 0,
>> +					tp_plat->x_max_coord, 0, 0);
>> +			
>input_set_abs_params(input[alloc_idx-1], ABS_Y, 0,
>> +					tp_plat->y_max_coord, 0, 0);
>> +			
>input_set_abs_params(input[alloc_idx-1], ABS_PRESSURE,
>> +				0, 1, 0, 0);
>> +
>> +			input[alloc_idx-1]->id.bustype = BUS_I2C;
>
>Again with the I2C-only and incomplete setup...
>
>
>> +
>> +			ret = input_register_device(input[reg_idx]);
>> +			if (ret) {
>> +				dev_err(&ad714x->bus->dev,
>> +				"Failed to register AD714x 
>input device!\n");
>> +				goto fail_alloc_reg;
>> +			}
>> +			reg_idx++;
>> +
>> +			tp_drv[i].input = input[alloc_idx-1];
>> +			ad714x->sw->touchpad = tp_drv;
>> +		}
>> +	}
>> +
>> +	/* all buttons use one input node */
>> +	if (ad714x->hw->button_num > 0) {
>> +		bt_drv = kzalloc(sizeof(struct ad714x_button_drv) *
>> +				ad714x->hw->button_num, GFP_KERNEL);
>> +		if (!bt_drv) {
>> +			dev_err(&ad714x->bus->dev,
>> +				"Can't allocate memory for 
>button info\n");
>> +			ret = -ENOMEM;
>> +			goto fail_alloc_reg;
>> +		}
>> +
>> +		input[alloc_idx] = input_allocate_device();
>> +		if (!input[alloc_idx]) {
>> +			dev_err(&ad714x->bus->dev,
>> +					"Can't allocate input 
>device %d\n",
>> +					alloc_idx);
>> +			ret = -ENOMEM;
>> +			goto fail_alloc_reg;
>> +		}
>> +		alloc_idx++;
>> +
>> +		__set_bit(EV_KEY, input[alloc_idx-1]->evbit);
>> +		for (i = 0; i < ad714x->hw->button_num; i++) {
>> +			__set_bit(bt_plat[i].keycode,
>> +				input[alloc_idx-1]->keybit);
>> +		}
>> +
>> +		input[alloc_idx-1]->id.bustype = BUS_I2C;
>
>... and again ...
>
>
>> +
>> +		ret = input_register_device(input[reg_idx]);
>> +		if (ret) {
>> +			dev_err(&ad714x->bus->dev,
>> +				"Failed to register AD714x 
>input device!\n");
>> +			goto fail_alloc_reg;
>> +		}
>> +		reg_idx++;
>> +
>> +		for (i = 0; i < ad714x->hw->button_num; i++)
>> +			bt_drv[i].input = input[alloc_idx-1];
>> +		ad714x->sw->button = bt_drv;
>> +	}
>> +
>> +	/* initilize and request sw/hw resources */
>> +
>> +	ad714x_hw_init(ad714x);
>> +	mutex_init(&ad714x->mutex);
>> +
>> +	if (ad714x->bus->irq > 0) {
>> +		ret = request_threaded_irq(ad714x->bus->irq, 
>ad714x_interrupt,
>> +				ad714x_interrupt_thread, 
>IRQF_TRIGGER_FALLING,
>> +				"ad714x_captouch", ad714x);
>> +		if (ret) {
>> +			dev_err(&ad714x->bus->dev, "Can't 
>allocate irq %d\n",
>> +					ad714x->bus->irq);
>> +			goto fail_irq;
>> +		}
>> +	} else
>> +		dev_warn(&ad714x->bus->dev, "IRQ not configured!\n");
>> +
>> +	return 0;
>> +
>> +fail_irq:
>> +fail_alloc_reg:
>> +	for (i = 0; i < reg_idx; i++)
>> +		input_unregister_device(input[i]);
>> +	for (i = 0; i < alloc_idx; i++)
>> +		input_free_device(input[i]);
>> +	kfree(bt_drv); /* kfree(NULL) is safe check is not required */
>> +	kfree(sd_drv);
>> +	kfree(wl_drv);
>> +	kfree(tp_drv);
>> +	kfree(drv_data);
>> +det_err:
>> +	return ret;
>> +}
>> +
>> +
>> +static const struct i2c_device_id ad714x_id[] = {
>> +	{ "ad714x_captouch", 0 },
>
>Plain old "ad714x" please.  Though it might be
>better to see "ad7147" and "ad7142" separately;
>this doesn't work for the ad7143 and ad7148 too,
>does it?  Do you know if it will work for as-yet
>undefined (I think) ad714[014569] chips?
>
>
>> +	{ }
>> +};
>> +MODULE_DEVICE_TABLE(i2c, ad714x_id);
>_______________________________________________
>Uclinux-dist-devel mailing list
>Uclinux-dist-devel@xxxxxxxxxxxxxxxxxxxx
>https://blackfin.uclinux.org/mailman/listinfo/uclinux-dist-devel
>
--
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