⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ads7846.c

📁 linux2.6.16版本
💻 C
📖 第 1 页 / 共 2 页
字号:
	struct ads7846	*ts = (void *)handle;	int		status = 0;	unsigned long	flags;	spin_lock_irqsave(&ts->lock, flags);	if (!ts->pending) {		ts->pending = 1;		if (!ts->irq_disabled) {			ts->irq_disabled = 1;			disable_irq(ts->spi->irq);		}		status = spi_async(ts->spi, &ts->msg);		if (status)			dev_err(&ts->spi->dev, "spi_async --> %d\n",					status);	}	spin_unlock_irqrestore(&ts->lock, flags);}static irqreturn_t ads7846_irq(int irq, void *handle, struct pt_regs *regs){	ads7846_timer((unsigned long) handle);	return IRQ_HANDLED;}/*--------------------------------------------------------------------------*/static intads7846_suspend(struct spi_device *spi, pm_message_t message){	struct ads7846 *ts = dev_get_drvdata(&spi->dev);	unsigned long	flags;	spin_lock_irqsave(&ts->lock, flags);	spi->dev.power.power_state = message;	/* are we waiting for IRQ, or polling? */	if (!ts->pendown) {		if (!ts->irq_disabled) {			ts->irq_disabled = 1;			disable_irq(ts->spi->irq);		}	} else {		/* polling; force a final SPI completion;		 * that will clean things up neatly		 */		if (!ts->pending)			mod_timer(&ts->timer, jiffies);		while (ts->pendown || ts->pending) {			spin_unlock_irqrestore(&ts->lock, flags);			udelay(10);			spin_lock_irqsave(&ts->lock, flags);		}	}	/* we know the chip's in lowpower mode since we always	 * leave it that way after every request	 */	spin_unlock_irqrestore(&ts->lock, flags);	return 0;}static int ads7846_resume(struct spi_device *spi){	struct ads7846 *ts = dev_get_drvdata(&spi->dev);	ts->irq_disabled = 0;	enable_irq(ts->spi->irq);	spi->dev.power.power_state = PMSG_ON;	return 0;}static int __devinit ads7846_probe(struct spi_device *spi){	struct ads7846			*ts;	struct input_dev		*input_dev;	struct ads7846_platform_data	*pdata = spi->dev.platform_data;	struct spi_transfer		*x;	int				err;	if (!spi->irq) {		dev_dbg(&spi->dev, "no IRQ?\n");		return -ENODEV;	}	if (!pdata) {		dev_dbg(&spi->dev, "no platform data?\n");		return -ENODEV;	}	/* don't exceed max specified sample rate */	if (spi->max_speed_hz > (125000 * SAMPLE_BITS)) {		dev_dbg(&spi->dev, "f(sample) %d KHz?\n",				(spi->max_speed_hz/SAMPLE_BITS)/1000);		return -EINVAL;	}	/* We'd set the wordsize to 12 bits ... except that some controllers	 * will then treat the 8 bit command words as 12 bits (and drop the	 * four MSBs of the 12 bit result).  Result: inputs must be shifted	 * to discard the four garbage LSBs.	 */	ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL);	input_dev = input_allocate_device();	if (!ts || !input_dev) {		err = -ENOMEM;		goto err_free_mem;	}	dev_set_drvdata(&spi->dev, ts);	spi->dev.power.power_state = PMSG_ON;	ts->spi = spi;	ts->input = input_dev;	init_timer(&ts->timer);	ts->timer.data = (unsigned long) ts;	ts->timer.function = ads7846_timer;	ts->model = pdata->model ? : 7846;	ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100;	ts->x_plate_ohms = pdata->x_plate_ohms ? : 400;	snprintf(ts->phys, sizeof(ts->phys), "%s/input0", spi->dev.bus_id);	input_dev->name = "ADS784x Touchscreen";	input_dev->phys = ts->phys;	input_dev->cdev.dev = &spi->dev;	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);	input_set_abs_params(input_dev, ABS_X,			pdata->x_min ? : 0,			pdata->x_max ? : MAX_12BIT,			0, 0);	input_set_abs_params(input_dev, ABS_Y,			pdata->y_min ? : 0,			pdata->y_max ? : MAX_12BIT,			0, 0);	input_set_abs_params(input_dev, ABS_PRESSURE,			pdata->pressure_min, pdata->pressure_max, 0, 0);	/* set up the transfers to read touchscreen state; this assumes we	 * use formula #2 for pressure, not #3.	 */	INIT_LIST_HEAD(&ts->msg.transfers);	x = ts->xfer;	/* y- still on; turn on only y+ (and ADC) */	ts->read_y = READ_Y;	x->tx_buf = &ts->read_y;	x->len = 1;	spi_message_add_tail(x, &ts->msg);	x++;	x->rx_buf = &ts->tc.y;	x->len = 2;	spi_message_add_tail(x, &ts->msg);	/* turn y+ off, x- on; we'll use formula #2 */	if (ts->model == 7846) {		x++;		ts->read_z1 = READ_Z1;		x->tx_buf = &ts->read_z1;		x->len = 1;		spi_message_add_tail(x, &ts->msg);		x++;		x->rx_buf = &ts->tc.z1;		x->len = 2;		spi_message_add_tail(x, &ts->msg);		x++;		ts->read_z2 = READ_Z2;		x->tx_buf = &ts->read_z2;		x->len = 1;		spi_message_add_tail(x, &ts->msg);		x++;		x->rx_buf = &ts->tc.z2;		x->len = 2;		spi_message_add_tail(x, &ts->msg);	}	/* turn y- off, x+ on, then leave in lowpower */	x++;	ts->read_x = READ_X;	x->tx_buf = &ts->read_x;	x->len = 1;	spi_message_add_tail(x, &ts->msg);	x++;	x->rx_buf = &ts->tc.x;	x->len = 2;	CS_CHANGE(*x);	spi_message_add_tail(x, &ts->msg);	ts->msg.complete = ads7846_rx;	ts->msg.context = ts;	if (request_irq(spi->irq, ads7846_irq,			SA_SAMPLE_RANDOM | SA_TRIGGER_FALLING,			spi->dev.bus_id, ts)) {		dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq);		err = -EBUSY;		goto err_free_mem;	}	dev_info(&spi->dev, "touchscreen, irq %d\n", spi->irq);	/* take a first sample, leaving nPENIRQ active; avoid	 * the touchscreen, in case it's not connected.	 */	(void) ads7846_read12_ser(&spi->dev,			  READ_12BIT_SER(vaux) | ADS_PD10_ALL_ON);	/* ads7843/7845 don't have temperature sensors, and	 * use the other sensors a bit differently too	 */	if (ts->model == 7846) {		device_create_file(&spi->dev, &dev_attr_temp0);		device_create_file(&spi->dev, &dev_attr_temp1);	}	if (ts->model != 7845)		device_create_file(&spi->dev, &dev_attr_vbatt);	device_create_file(&spi->dev, &dev_attr_vaux);	err = input_register_device(input_dev);	if (err)		goto err_free_irq;	return 0; err_free_irq:	free_irq(spi->irq, ts); err_free_mem:	input_free_device(input_dev);	kfree(ts);	return err;}static int __devexit ads7846_remove(struct spi_device *spi){	struct ads7846		*ts = dev_get_drvdata(&spi->dev);	ads7846_suspend(spi, PMSG_SUSPEND);	free_irq(ts->spi->irq, ts);	if (ts->irq_disabled)		enable_irq(ts->spi->irq);	if (ts->model == 7846) {		device_remove_file(&spi->dev, &dev_attr_temp0);		device_remove_file(&spi->dev, &dev_attr_temp1);	}	if (ts->model != 7845)		device_remove_file(&spi->dev, &dev_attr_vbatt);	device_remove_file(&spi->dev, &dev_attr_vaux);	input_unregister_device(ts->input);	kfree(ts);	dev_dbg(&spi->dev, "unregistered touchscreen\n");	return 0;}static struct spi_driver ads7846_driver = {	.driver = {		.name	= "ads7846",		.bus	= &spi_bus_type,		.owner	= THIS_MODULE,	},	.probe		= ads7846_probe,	.remove		= __devexit_p(ads7846_remove),	.suspend	= ads7846_suspend,	.resume		= ads7846_resume,};static int __init ads7846_init(void){	/* grr, board-specific init should stay out of drivers!! */#ifdef	CONFIG_ARCH_OMAP	if (machine_is_omap_osk()) {		/* GPIO4 = PENIRQ; GPIO6 = BUSY */		omap_request_gpio(4);		omap_set_gpio_direction(4, 1);		omap_request_gpio(6);		omap_set_gpio_direction(6, 1);	}	// also TI 1510 Innovator, bitbanging through FPGA	// also Nokia 770	// also Palm Tungsten T2#endif	// PXA:	// also Dell Axim X50	// also HP iPaq H191x/H192x/H415x/H435x	// also Intel Lubbock (additional to UCB1400; as temperature sensor)	// also Sharp Zaurus C7xx, C8xx (corgi/sheperd/husky)	// Atmel at91sam9261-EK uses ads7843	// also various AMD Au1x00 devel boards	return spi_register_driver(&ads7846_driver);}module_init(ads7846_init);static void __exit ads7846_exit(void){	spi_unregister_driver(&ads7846_driver);#ifdef	CONFIG_ARCH_OMAP	if (machine_is_omap_osk()) {		omap_free_gpio(4);		omap_free_gpio(6);	}#endif}module_exit(ads7846_exit);MODULE_DESCRIPTION("ADS7846 TouchScreen Driver");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -