Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
  Input: ads7846 - fix unsafe disable_irq
  Input: mainstone-wm97xx - fix condition in pen_up
  Input: pc110pad - remove unused variable dev
  Input: bf54x-keys - remove depreciated IRQF_SAMPLE_RANDOM flag
  Input: ad7877, ad7879 - remove depreciated IRQF_SAMPLE_RANDOM flag
  Input: da9034-ts - make pen {down,up} events more reliable
  Input: da9034-ts - add Bin Yang as co-author of the driver
  Input: atkbd - add forced release keys quirk for Samsung NC20
  Input: atkbd - add forced release keys quirk for Samsung Q45
  Input: gameport - fix attach driver code
  Input: hp_sdc_rtc should depend on serio
  Input: wm97xx - don't specify IRQF_SAMPLE_RANDOM
  Input: ads7846 - introduce platform specific way to synchronize sampling
  Input: remove unnecessary synchronize_rcu() call
  Input: i8042 - add a DMI table for the i8042.reset option
  Input: i8042 - introduce a tougher reset
This commit is contained in:
Linus Torvalds 2009-04-17 10:08:13 -07:00
commit 91ec65ba33
15 changed files with 121 additions and 43 deletions

View File

@ -50,9 +50,8 @@ static LIST_HEAD(gameport_list);
static struct bus_type gameport_bus; static struct bus_type gameport_bus;
static void gameport_add_driver(struct gameport_driver *drv);
static void gameport_add_port(struct gameport *gameport); static void gameport_add_port(struct gameport *gameport);
static void gameport_destroy_port(struct gameport *gameport); static void gameport_attach_driver(struct gameport_driver *drv);
static void gameport_reconnect_port(struct gameport *gameport); static void gameport_reconnect_port(struct gameport *gameport);
static void gameport_disconnect_port(struct gameport *gameport); static void gameport_disconnect_port(struct gameport *gameport);
@ -230,7 +229,6 @@ static void gameport_find_driver(struct gameport *gameport)
enum gameport_event_type { enum gameport_event_type {
GAMEPORT_REGISTER_PORT, GAMEPORT_REGISTER_PORT,
GAMEPORT_REGISTER_DRIVER,
GAMEPORT_ATTACH_DRIVER, GAMEPORT_ATTACH_DRIVER,
}; };
@ -374,8 +372,8 @@ static void gameport_handle_event(void)
gameport_add_port(event->object); gameport_add_port(event->object);
break; break;
case GAMEPORT_REGISTER_DRIVER: case GAMEPORT_ATTACH_DRIVER:
gameport_add_driver(event->object); gameport_attach_driver(event->object);
break; break;
default: default:
@ -706,14 +704,14 @@ static int gameport_driver_remove(struct device *dev)
return 0; return 0;
} }
static void gameport_add_driver(struct gameport_driver *drv) static void gameport_attach_driver(struct gameport_driver *drv)
{ {
int error; int error;
error = driver_register(&drv->driver); error = driver_attach(&drv->driver);
if (error) if (error)
printk(KERN_ERR printk(KERN_ERR
"gameport: driver_register() failed for %s, error: %d\n", "gameport: driver_attach() failed for %s, error: %d\n",
drv->driver.name, error); drv->driver.name, error);
} }

View File

@ -1549,7 +1549,6 @@ int input_register_handle(struct input_handle *handle)
return error; return error;
list_add_tail_rcu(&handle->d_node, &dev->h_list); list_add_tail_rcu(&handle->d_node, &dev->h_list);
mutex_unlock(&dev->mutex); mutex_unlock(&dev->mutex);
synchronize_rcu();
/* /*
* Since we are supposed to be called from ->connect() * Since we are supposed to be called from ->connect()

View File

@ -880,7 +880,7 @@ static unsigned int atkbd_hp_zv6100_forced_release_keys[] = {
}; };
/* /*
* Samsung NC10 with Fn+F? key release not working * Samsung NC10,NC20 with Fn+F? key release not working
*/ */
static unsigned int atkbd_samsung_forced_release_keys[] = { static unsigned int atkbd_samsung_forced_release_keys[] = {
0x82, 0x83, 0x84, 0x86, 0x88, 0x89, 0xb3, 0xf7, 0xf9, -1U 0x82, 0x83, 0x84, 0x86, 0x88, 0x89, 0xb3, 0xf7, 0xf9, -1U
@ -1533,6 +1533,24 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
.callback = atkbd_setup_forced_release, .callback = atkbd_setup_forced_release,
.driver_data = atkbd_samsung_forced_release_keys, .driver_data = atkbd_samsung_forced_release_keys,
}, },
{
.ident = "Samsung NC20",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
DMI_MATCH(DMI_PRODUCT_NAME, "NC20"),
},
.callback = atkbd_setup_forced_release,
.driver_data = atkbd_samsung_forced_release_keys,
},
{
.ident = "Samsung SQ45S70S",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
DMI_MATCH(DMI_PRODUCT_NAME, "SQ45S70S"),
},
.callback = atkbd_setup_forced_release,
.driver_data = atkbd_samsung_forced_release_keys,
},
{ {
.ident = "Fujitsu Amilo PA 1510", .ident = "Fujitsu Amilo PA 1510",
.matches = { .matches = {

View File

@ -252,7 +252,7 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev)
} }
error = request_irq(bf54x_kpad->irq, bfin_kpad_isr, error = request_irq(bf54x_kpad->irq, bfin_kpad_isr,
IRQF_SAMPLE_RANDOM, DRV_NAME, pdev); 0, DRV_NAME, pdev);
if (error) { if (error) {
printk(KERN_ERR DRV_NAME printk(KERN_ERR DRV_NAME
": unable to claim irq %d; error %d\n", ": unable to claim irq %d; error %d\n",

View File

@ -214,7 +214,7 @@ config INPUT_SGI_BTNS
config HP_SDC_RTC config HP_SDC_RTC
tristate "HP SDC Real Time Clock" tristate "HP SDC Real Time Clock"
depends on GSC || HP300 depends on (GSC || HP300) && SERIO
select HP_SDC select HP_SDC
help help
Say Y here if you want to support the built-in real time clock Say Y here if you want to support the built-in real time clock

View File

@ -108,7 +108,6 @@ static int pc110pad_open(struct input_dev *dev)
*/ */
static int __init pc110pad_init(void) static int __init pc110pad_init(void)
{ {
struct pci_dev *dev;
int err; int err;
if (!no_pci_devices()) if (!no_pci_devices())

View File

@ -377,6 +377,24 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
{ } { }
}; };
static struct dmi_system_id __initdata i8042_dmi_reset_table[] = {
{
.ident = "MSI Wind U-100",
.matches = {
DMI_MATCH(DMI_BOARD_NAME, "U-100"),
DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
},
},
{
.ident = "LG Electronics X110",
.matches = {
DMI_MATCH(DMI_BOARD_NAME, "X110"),
DMI_MATCH(DMI_BOARD_VENDOR, "LG Electronics Inc."),
},
},
{ }
};
#ifdef CONFIG_PNP #ifdef CONFIG_PNP
static struct dmi_system_id __initdata i8042_dmi_nopnp_table[] = { static struct dmi_system_id __initdata i8042_dmi_nopnp_table[] = {
{ {
@ -386,6 +404,13 @@ static struct dmi_system_id __initdata i8042_dmi_nopnp_table[] = {
DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"), DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
}, },
}, },
{
.ident = "MSI Wind U-100",
.matches = {
DMI_MATCH(DMI_BOARD_NAME, "U-100"),
DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
},
},
{ } { }
}; };
#endif #endif
@ -698,6 +723,9 @@ static int __init i8042_platform_init(void)
#endif #endif
#ifdef CONFIG_X86 #ifdef CONFIG_X86
if (dmi_check_system(i8042_dmi_reset_table))
i8042_reset = 1;
if (dmi_check_system(i8042_dmi_noloop_table)) if (dmi_check_system(i8042_dmi_noloop_table))
i8042_noloop = 1; i8042_noloop = 1;

View File

@ -712,22 +712,43 @@ static int i8042_controller_check(void)
static int i8042_controller_selftest(void) static int i8042_controller_selftest(void)
{ {
unsigned char param; unsigned char param;
int i = 0;
if (!i8042_reset) if (!i8042_reset)
return 0; return 0;
if (i8042_command(&param, I8042_CMD_CTL_TEST)) { /*
printk(KERN_ERR "i8042.c: i8042 controller self test timeout.\n"); * We try this 5 times; on some really fragile systems this does not
return -ENODEV; * take the first time...
} */
do {
if (i8042_command(&param, I8042_CMD_CTL_TEST)) {
printk(KERN_ERR "i8042.c: i8042 controller self test timeout.\n");
return -ENODEV;
}
if (param == I8042_RET_CTL_TEST)
return 0;
if (param != I8042_RET_CTL_TEST) {
printk(KERN_ERR "i8042.c: i8042 controller selftest failed. (%#x != %#x)\n", printk(KERN_ERR "i8042.c: i8042 controller selftest failed. (%#x != %#x)\n",
param, I8042_RET_CTL_TEST); param, I8042_RET_CTL_TEST);
return -EIO; msleep(50);
} } while (i++ < 5);
#ifdef CONFIG_X86
/*
* On x86, we don't fail entire i8042 initialization if controller
* reset fails in hopes that keyboard port will still be functional
* and user will still get a working keyboard. This is especially
* important on netbooks. On other arches we trust hardware more.
*/
printk(KERN_INFO
"i8042: giving up on controller selftest, continuing anyway...\n");
return 0; return 0;
#else
return -EIO;
#endif
} }
/* /*

View File

@ -736,8 +736,8 @@ static int __devinit ad7877_probe(struct spi_device *spi)
/* Request AD7877 /DAV GPIO interrupt */ /* Request AD7877 /DAV GPIO interrupt */
err = request_irq(spi->irq, ad7877_irq, IRQF_TRIGGER_FALLING | err = request_irq(spi->irq, ad7877_irq, IRQF_TRIGGER_FALLING,
IRQF_SAMPLE_RANDOM, spi->dev.driver->name, ts); spi->dev.driver->name, ts);
if (err) { if (err) {
dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq);
goto err_free_mem; goto err_free_mem;

View File

@ -448,8 +448,7 @@ static int __devinit ad7879_construct(bus_device *bus, struct ad7879 *ts)
ad7879_setup(ts); ad7879_setup(ts);
err = request_irq(bus->irq, ad7879_irq, err = request_irq(bus->irq, ad7879_irq,
IRQF_TRIGGER_FALLING | IRQF_SAMPLE_RANDOM, IRQF_TRIGGER_FALLING, bus->dev.driver->name, ts);
bus->dev.driver->name, ts);
if (err) { if (err) {
dev_err(&bus->dev, "irq %d busy?\n", bus->irq); dev_err(&bus->dev, "irq %d busy?\n", bus->irq);

View File

@ -127,6 +127,8 @@ struct ads7846 {
void (*filter_cleanup)(void *data); void (*filter_cleanup)(void *data);
int (*get_pendown_state)(void); int (*get_pendown_state)(void);
int gpio_pendown; int gpio_pendown;
void (*wait_for_sync)(void);
}; };
/* leave chip selected when we're done, for quicker re-select? */ /* leave chip selected when we're done, for quicker re-select? */
@ -511,6 +513,10 @@ static int get_pendown_state(struct ads7846 *ts)
return !gpio_get_value(ts->gpio_pendown); return !gpio_get_value(ts->gpio_pendown);
} }
static void null_wait_for_sync(void)
{
}
/* /*
* PENIRQ only kicks the timer. The timer only reissues the SPI transfer, * PENIRQ only kicks the timer. The timer only reissues the SPI transfer,
* to retrieve touchscreen status. * to retrieve touchscreen status.
@ -686,6 +692,7 @@ static void ads7846_rx_val(void *ads)
default: default:
BUG(); BUG();
} }
ts->wait_for_sync();
status = spi_async(ts->spi, m); status = spi_async(ts->spi, m);
if (status) if (status)
dev_err(&ts->spi->dev, "spi_async --> %d\n", dev_err(&ts->spi->dev, "spi_async --> %d\n",
@ -723,6 +730,7 @@ static enum hrtimer_restart ads7846_timer(struct hrtimer *handle)
} else { } else {
/* pen is still down, continue with the measurement */ /* pen is still down, continue with the measurement */
ts->msg_idx = 0; ts->msg_idx = 0;
ts->wait_for_sync();
status = spi_async(ts->spi, &ts->msg[0]); status = spi_async(ts->spi, &ts->msg[0]);
if (status) if (status)
dev_err(&ts->spi->dev, "spi_async --> %d\n", status); dev_err(&ts->spi->dev, "spi_async --> %d\n", status);
@ -746,7 +754,7 @@ static irqreturn_t ads7846_irq(int irq, void *handle)
* that here. (The "generic irq" framework may help...) * that here. (The "generic irq" framework may help...)
*/ */
ts->irq_disabled = 1; ts->irq_disabled = 1;
disable_irq(ts->spi->irq); disable_irq_nosync(ts->spi->irq);
ts->pending = 1; ts->pending = 1;
hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_DELAY), hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_DELAY),
HRTIMER_MODE_REL); HRTIMER_MODE_REL);
@ -947,6 +955,8 @@ static int __devinit ads7846_probe(struct spi_device *spi)
ts->penirq_recheck_delay_usecs = ts->penirq_recheck_delay_usecs =
pdata->penirq_recheck_delay_usecs; pdata->penirq_recheck_delay_usecs;
ts->wait_for_sync = pdata->wait_for_sync ? : null_wait_for_sync;
snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&spi->dev)); snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&spi->dev));
input_dev->name = "ADS784x Touchscreen"; input_dev->name = "ADS784x Touchscreen";

View File

@ -3,6 +3,7 @@
* *
* Copyright (C) 2006-2008 Marvell International Ltd. * Copyright (C) 2006-2008 Marvell International Ltd.
* Fengwei Yin <fengwei.yin@marvell.com> * Fengwei Yin <fengwei.yin@marvell.com>
* Bin Yang <bin.yang@marvell.com>
* Eric Miao <eric.miao@marvell.com> * Eric Miao <eric.miao@marvell.com>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -175,6 +176,16 @@ static void da9034_event_handler(struct da9034_touch *touch, int event)
goto err_reset; goto err_reset;
touch->state = STATE_STOP; touch->state = STATE_STOP;
/* FIXME: PEN_{UP/DOWN} events are expected to be
* available by stopping TSI, but this is found not
* always true, delay and simulate such an event
* here is more reliable
*/
mdelay(1);
da9034_event_handler(touch,
is_pen_down(touch) ? EVENT_PEN_DOWN :
EVENT_PEN_UP);
break; break;
case STATE_STOP: case STATE_STOP:
@ -189,8 +200,6 @@ static void da9034_event_handler(struct da9034_touch *touch, int event)
report_pen_up(touch); report_pen_up(touch);
touch->state = STATE_IDLE; touch->state = STATE_IDLE;
} }
input_sync(touch->input_dev);
break; break;
case STATE_WAIT: case STATE_WAIT:
@ -200,8 +209,10 @@ static void da9034_event_handler(struct da9034_touch *touch, int event)
if (is_pen_down(touch)) { if (is_pen_down(touch)) {
start_tsi(touch); start_tsi(touch);
touch->state = STATE_BUSY; touch->state = STATE_BUSY;
} else } else {
report_pen_up(touch);
touch->state = STATE_IDLE; touch->state = STATE_IDLE;
}
break; break;
} }
return; return;
@ -226,16 +237,12 @@ static int da9034_touch_notifier(struct notifier_block *nb,
struct da9034_touch *touch = struct da9034_touch *touch =
container_of(nb, struct da9034_touch, notifier); container_of(nb, struct da9034_touch, notifier);
if (event & DA9034_EVENT_PEN_DOWN) {
if (is_pen_down(touch))
da9034_event_handler(touch, EVENT_PEN_DOWN);
else
da9034_event_handler(touch, EVENT_PEN_UP);
}
if (event & DA9034_EVENT_TSI_READY) if (event & DA9034_EVENT_TSI_READY)
da9034_event_handler(touch, EVENT_TSI_READY); da9034_event_handler(touch, EVENT_TSI_READY);
if ((event & DA9034_EVENT_PEN_DOWN) && touch->state == STATE_IDLE)
da9034_event_handler(touch, EVENT_PEN_DOWN);
return 0; return 0;
} }
@ -385,6 +392,6 @@ static void __exit da9034_touch_exit(void)
module_exit(da9034_touch_exit); module_exit(da9034_touch_exit);
MODULE_DESCRIPTION("Touchscreen driver for Dialog Semiconductor DA9034"); MODULE_DESCRIPTION("Touchscreen driver for Dialog Semiconductor DA9034");
MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"); MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>, Bin Yang <bin.yang@marvell.com>");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:da9034-touch"); MODULE_ALIAS("platform:da9034-touch");

View File

@ -111,13 +111,12 @@ static void wm97xx_acc_pen_up(struct wm97xx *wm)
#else #else
static void wm97xx_acc_pen_up(struct wm97xx *wm) static void wm97xx_acc_pen_up(struct wm97xx *wm)
{ {
int count = 16; unsigned int count;
schedule_timeout_uninterruptible(1); schedule_timeout_uninterruptible(1);
while (count < 16) { for (count = 0; count < 16; count++)
MODR; MODR;
count--;
}
} }
#endif #endif

View File

@ -370,8 +370,7 @@ static int wm97xx_init_pen_irq(struct wm97xx *wm)
* provided. */ * provided. */
BUG_ON(!wm->mach_ops->irq_enable); BUG_ON(!wm->mach_ops->irq_enable);
if (request_irq(wm->pen_irq, wm97xx_pen_interrupt, if (request_irq(wm->pen_irq, wm97xx_pen_interrupt, IRQF_SHARED,
IRQF_SHARED | IRQF_SAMPLE_RANDOM,
"wm97xx-pen", wm)) { "wm97xx-pen", wm)) {
dev_err(wm->dev, dev_err(wm->dev,
"Failed to register pen down interrupt, polling"); "Failed to register pen down interrupt, polling");

View File

@ -51,5 +51,6 @@ struct ads7846_platform_data {
void **filter_data); void **filter_data);
int (*filter) (void *filter_data, int data_idx, int *val); int (*filter) (void *filter_data, int data_idx, int *val);
void (*filter_cleanup)(void *filter_data); void (*filter_cleanup)(void *filter_data);
void (*wait_for_sync)(void);
}; };