Merge tag 'v3.7-rc3' into next to sync up with recent USB and MFD changes
This commit is contained in:
@@ -292,7 +292,6 @@ static int evdev_release(struct inode *inode, struct file *file)
|
||||
kfree(client);
|
||||
|
||||
evdev_close_device(evdev);
|
||||
put_device(&evdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -331,7 +330,6 @@ static int evdev_open(struct inode *inode, struct file *file)
|
||||
file->private_data = client;
|
||||
nonseekable_open(inode, file);
|
||||
|
||||
get_device(&evdev->dev);
|
||||
return 0;
|
||||
|
||||
err_free_client:
|
||||
@@ -1001,6 +999,7 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
|
||||
goto err_free_evdev;
|
||||
|
||||
cdev_init(&evdev->cdev, &evdev_fops);
|
||||
evdev->cdev.kobj.parent = &evdev->dev.kobj;
|
||||
error = cdev_add(&evdev->cdev, evdev->dev.devt, 1);
|
||||
if (error)
|
||||
goto err_unregister_handle;
|
||||
|
@@ -243,7 +243,6 @@ static int joydev_release(struct inode *inode, struct file *file)
|
||||
kfree(client);
|
||||
|
||||
joydev_close_device(joydev);
|
||||
put_device(&joydev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -270,7 +269,6 @@ static int joydev_open(struct inode *inode, struct file *file)
|
||||
file->private_data = client;
|
||||
nonseekable_open(inode, file);
|
||||
|
||||
get_device(&joydev->dev);
|
||||
return 0;
|
||||
|
||||
err_free_client:
|
||||
@@ -858,6 +856,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
|
||||
goto err_free_joydev;
|
||||
|
||||
cdev_init(&joydev->cdev, &joydev_fops);
|
||||
joydev->cdev.kobj.parent = &joydev->dev.kobj;
|
||||
error = cdev_add(&joydev->cdev, joydev->dev.devt, 1);
|
||||
if (error)
|
||||
goto err_unregister_handle;
|
||||
|
@@ -533,7 +533,7 @@ config KEYBOARD_DAVINCI
|
||||
|
||||
config KEYBOARD_OMAP
|
||||
tristate "TI OMAP keypad support"
|
||||
depends on (ARCH_OMAP1 || ARCH_OMAP2)
|
||||
depends on ARCH_OMAP1
|
||||
select INPUT_MATRIXKMAP
|
||||
help
|
||||
Say Y here if you want to use the OMAP keypad.
|
||||
|
@@ -36,7 +36,7 @@
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/irqs.h>
|
||||
#include <mach/keyscan.h>
|
||||
#include <linux/platform_data/keyscan-davinci.h>
|
||||
|
||||
/* Key scan registers */
|
||||
#define DAVINCI_KEYSCAN_KEYCTRL 0x0000
|
||||
|
@@ -29,7 +29,7 @@
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/ep93xx_keypad.h>
|
||||
#include <linux/platform_data/keypad-ep93xx.h>
|
||||
|
||||
/*
|
||||
* Keypad Interface Register offsets
|
||||
|
@@ -358,6 +358,7 @@ static void imx_keypad_inhibit(struct imx_keypad *keypad)
|
||||
/* Inhibit KDI and KRI interrupts. */
|
||||
reg_val = readw(keypad->mmio_base + KPSR);
|
||||
reg_val &= ~(KBD_STAT_KRIE | KBD_STAT_KDIE);
|
||||
reg_val |= KBD_STAT_KPKR | KBD_STAT_KPKD;
|
||||
writew(reg_val, keypad->mmio_base + KPSR);
|
||||
|
||||
/* Colums as open drain and disable all rows */
|
||||
@@ -515,7 +516,9 @@ static int __devinit imx_keypad_probe(struct platform_device *pdev)
|
||||
input_set_drvdata(input_dev, keypad);
|
||||
|
||||
/* Ensure that the keypad will stay dormant until opened */
|
||||
clk_prepare_enable(keypad->clk);
|
||||
imx_keypad_inhibit(keypad);
|
||||
clk_disable_unprepare(keypad->clk);
|
||||
|
||||
error = request_irq(irq, imx_keypad_irq_handler, 0,
|
||||
pdev->name, keypad);
|
||||
|
@@ -20,7 +20,7 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <plat/ske.h>
|
||||
#include <linux/platform_data/keypad-nomadik-ske.h>
|
||||
|
||||
/* SKE_CR bits */
|
||||
#define SKE_KPMLT (0x1 << 6)
|
||||
|
@@ -35,13 +35,9 @@
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <plat/keypad.h>
|
||||
#include <plat/menelaus.h>
|
||||
#include <asm/irq.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/io.h>
|
||||
#include <plat/mux.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/platform_data/gpio-omap.h>
|
||||
#include <linux/platform_data/keypad-omap.h>
|
||||
|
||||
#undef NEW_BOARD_LEARNING_MODE
|
||||
|
||||
@@ -96,28 +92,8 @@ static u8 get_row_gpio_val(struct omap_kp *omap_kp)
|
||||
|
||||
static irqreturn_t omap_kp_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct omap_kp *omap_kp = dev_id;
|
||||
|
||||
/* disable keyboard interrupt and schedule for handling */
|
||||
if (cpu_is_omap24xx()) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < omap_kp->rows; i++) {
|
||||
int gpio_irq = gpio_to_irq(row_gpios[i]);
|
||||
/*
|
||||
* The interrupt which we're currently handling should
|
||||
* be disabled _nosync() to avoid deadlocks waiting
|
||||
* for this handler to complete. All others should
|
||||
* be disabled the regular way for SMP safety.
|
||||
*/
|
||||
if (gpio_irq == irq)
|
||||
disable_irq_nosync(gpio_irq);
|
||||
else
|
||||
disable_irq(gpio_irq);
|
||||
}
|
||||
} else
|
||||
/* disable keyboard interrupt and schedule for handling */
|
||||
omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
|
||||
omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
|
||||
|
||||
tasklet_schedule(&kp_tasklet);
|
||||
|
||||
@@ -133,33 +109,22 @@ static void omap_kp_scan_keypad(struct omap_kp *omap_kp, unsigned char *state)
|
||||
{
|
||||
int col = 0;
|
||||
|
||||
/* disable keyboard interrupt and schedule for handling */
|
||||
omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
|
||||
|
||||
/* read the keypad status */
|
||||
if (cpu_is_omap24xx()) {
|
||||
/* read the keypad status */
|
||||
for (col = 0; col < omap_kp->cols; col++) {
|
||||
set_col_gpio_val(omap_kp, ~(1 << col));
|
||||
state[col] = ~(get_row_gpio_val(omap_kp)) & 0xff;
|
||||
}
|
||||
set_col_gpio_val(omap_kp, 0);
|
||||
omap_writew(0xff, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBC);
|
||||
for (col = 0; col < omap_kp->cols; col++) {
|
||||
omap_writew(~(1 << col) & 0xff,
|
||||
OMAP1_MPUIO_BASE + OMAP_MPUIO_KBC);
|
||||
|
||||
} else {
|
||||
/* disable keyboard interrupt and schedule for handling */
|
||||
omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
|
||||
udelay(omap_kp->delay);
|
||||
|
||||
/* read the keypad status */
|
||||
omap_writew(0xff, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBC);
|
||||
for (col = 0; col < omap_kp->cols; col++) {
|
||||
omap_writew(~(1 << col) & 0xff,
|
||||
OMAP1_MPUIO_BASE + OMAP_MPUIO_KBC);
|
||||
|
||||
udelay(omap_kp->delay);
|
||||
|
||||
state[col] = ~omap_readw(OMAP1_MPUIO_BASE +
|
||||
OMAP_MPUIO_KBR_LATCH) & 0xff;
|
||||
}
|
||||
omap_writew(0x00, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBC);
|
||||
udelay(2);
|
||||
state[col] = ~omap_readw(OMAP1_MPUIO_BASE +
|
||||
OMAP_MPUIO_KBR_LATCH) & 0xff;
|
||||
}
|
||||
omap_writew(0x00, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBC);
|
||||
udelay(2);
|
||||
}
|
||||
|
||||
static void omap_kp_tasklet(unsigned long data)
|
||||
@@ -222,14 +187,8 @@ static void omap_kp_tasklet(unsigned long data)
|
||||
mod_timer(&omap_kp_data->timer, jiffies + delay);
|
||||
} else {
|
||||
/* enable interrupts */
|
||||
if (cpu_is_omap24xx()) {
|
||||
int i;
|
||||
for (i = 0; i < omap_kp_data->rows; i++)
|
||||
enable_irq(gpio_to_irq(row_gpios[i]));
|
||||
} else {
|
||||
omap_writew(0, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
|
||||
kp_cur_group = -1;
|
||||
}
|
||||
omap_writew(0, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
|
||||
kp_cur_group = -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,6 +201,7 @@ static ssize_t omap_kp_enable_show(struct device *dev,
|
||||
static ssize_t omap_kp_enable_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct omap_kp *omap_kp = dev_get_drvdata(dev);
|
||||
int state;
|
||||
|
||||
if (sscanf(buf, "%u", &state) != 1)
|
||||
@@ -253,9 +213,9 @@ static ssize_t omap_kp_enable_store(struct device *dev, struct device_attribute
|
||||
mutex_lock(&kp_enable_mutex);
|
||||
if (state != kp_enable) {
|
||||
if (state)
|
||||
enable_irq(INT_KEYBOARD);
|
||||
enable_irq(omap_kp->irq);
|
||||
else
|
||||
disable_irq(INT_KEYBOARD);
|
||||
disable_irq(omap_kp->irq);
|
||||
kp_enable = state;
|
||||
}
|
||||
mutex_unlock(&kp_enable_mutex);
|
||||
@@ -289,7 +249,7 @@ static int __devinit omap_kp_probe(struct platform_device *pdev)
|
||||
struct omap_kp *omap_kp;
|
||||
struct input_dev *input_dev;
|
||||
struct omap_kp_platform_data *pdata = pdev->dev.platform_data;
|
||||
int i, col_idx, row_idx, irq_idx, ret;
|
||||
int i, col_idx, row_idx, ret;
|
||||
unsigned int row_shift, keycodemax;
|
||||
|
||||
if (!pdata->rows || !pdata->cols || !pdata->keymap_data) {
|
||||
@@ -314,8 +274,7 @@ static int __devinit omap_kp_probe(struct platform_device *pdev)
|
||||
omap_kp->input = input_dev;
|
||||
|
||||
/* Disable the interrupt for the MPUIO keyboard */
|
||||
if (!cpu_is_omap24xx())
|
||||
omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
|
||||
omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
|
||||
|
||||
if (pdata->delay)
|
||||
omap_kp->delay = pdata->delay;
|
||||
@@ -328,31 +287,8 @@ static int __devinit omap_kp_probe(struct platform_device *pdev)
|
||||
omap_kp->rows = pdata->rows;
|
||||
omap_kp->cols = pdata->cols;
|
||||
|
||||
if (cpu_is_omap24xx()) {
|
||||
/* Cols: outputs */
|
||||
for (col_idx = 0; col_idx < omap_kp->cols; col_idx++) {
|
||||
if (gpio_request(col_gpios[col_idx], "omap_kp_col") < 0) {
|
||||
printk(KERN_ERR "Failed to request"
|
||||
"GPIO%d for keypad\n",
|
||||
col_gpios[col_idx]);
|
||||
goto err1;
|
||||
}
|
||||
gpio_direction_output(col_gpios[col_idx], 0);
|
||||
}
|
||||
/* Rows: inputs */
|
||||
for (row_idx = 0; row_idx < omap_kp->rows; row_idx++) {
|
||||
if (gpio_request(row_gpios[row_idx], "omap_kp_row") < 0) {
|
||||
printk(KERN_ERR "Failed to request"
|
||||
"GPIO%d for keypad\n",
|
||||
row_gpios[row_idx]);
|
||||
goto err2;
|
||||
}
|
||||
gpio_direction_input(row_gpios[row_idx]);
|
||||
}
|
||||
} else {
|
||||
col_idx = 0;
|
||||
row_idx = 0;
|
||||
}
|
||||
col_idx = 0;
|
||||
row_idx = 0;
|
||||
|
||||
setup_timer(&omap_kp->timer, omap_kp_timer, (unsigned long)omap_kp);
|
||||
|
||||
@@ -394,27 +330,16 @@ static int __devinit omap_kp_probe(struct platform_device *pdev)
|
||||
|
||||
/* scan current status and enable interrupt */
|
||||
omap_kp_scan_keypad(omap_kp, keypad_state);
|
||||
if (!cpu_is_omap24xx()) {
|
||||
omap_kp->irq = platform_get_irq(pdev, 0);
|
||||
if (omap_kp->irq >= 0) {
|
||||
if (request_irq(omap_kp->irq, omap_kp_interrupt, 0,
|
||||
"omap-keypad", omap_kp) < 0)
|
||||
goto err4;
|
||||
}
|
||||
omap_writew(0, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
|
||||
} else {
|
||||
for (irq_idx = 0; irq_idx < omap_kp->rows; irq_idx++) {
|
||||
if (request_irq(gpio_to_irq(row_gpios[irq_idx]),
|
||||
omap_kp_interrupt,
|
||||
IRQF_TRIGGER_FALLING,
|
||||
"omap-keypad", omap_kp) < 0)
|
||||
goto err5;
|
||||
}
|
||||
omap_kp->irq = platform_get_irq(pdev, 0);
|
||||
if (omap_kp->irq >= 0) {
|
||||
if (request_irq(omap_kp->irq, omap_kp_interrupt, 0,
|
||||
"omap-keypad", omap_kp) < 0)
|
||||
goto err4;
|
||||
}
|
||||
omap_writew(0, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
|
||||
|
||||
return 0;
|
||||
err5:
|
||||
for (i = irq_idx - 1; i >= 0; i--)
|
||||
free_irq(row_gpios[i], omap_kp);
|
||||
|
||||
err4:
|
||||
input_unregister_device(omap_kp->input);
|
||||
input_dev = NULL;
|
||||
@@ -423,7 +348,6 @@ err3:
|
||||
err2:
|
||||
for (i = row_idx - 1; i >= 0; i--)
|
||||
gpio_free(row_gpios[i]);
|
||||
err1:
|
||||
for (i = col_idx - 1; i >= 0; i--)
|
||||
gpio_free(col_gpios[i]);
|
||||
|
||||
@@ -439,18 +363,8 @@ static int __devexit omap_kp_remove(struct platform_device *pdev)
|
||||
|
||||
/* disable keypad interrupt handling */
|
||||
tasklet_disable(&kp_tasklet);
|
||||
if (cpu_is_omap24xx()) {
|
||||
int i;
|
||||
for (i = 0; i < omap_kp->cols; i++)
|
||||
gpio_free(col_gpios[i]);
|
||||
for (i = 0; i < omap_kp->rows; i++) {
|
||||
gpio_free(row_gpios[i]);
|
||||
free_irq(gpio_to_irq(row_gpios[i]), omap_kp);
|
||||
}
|
||||
} else {
|
||||
omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
|
||||
free_irq(omap_kp->irq, omap_kp);
|
||||
}
|
||||
omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
|
||||
free_irq(omap_kp->irq, omap_kp);
|
||||
|
||||
del_timer_sync(&omap_kp->timer);
|
||||
tasklet_kill(&kp_tasklet);
|
||||
|
@@ -32,7 +32,7 @@
|
||||
#include <asm/mach/map.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <plat/pxa27x_keypad.h>
|
||||
#include <linux/platform_data/keypad-pxa27x.h>
|
||||
/*
|
||||
* Keypad Controller registers
|
||||
*/
|
||||
|
@@ -15,7 +15,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <mach/pxa930_rotary.h>
|
||||
#include <linux/platform_data/keyboard-pxa930_rotary.h>
|
||||
|
||||
#define SBCR (0x04)
|
||||
#define ERCR (0x0c)
|
||||
|
@@ -156,8 +156,7 @@ static irqreturn_t qt2160_irq(int irq, void *_qt2160)
|
||||
|
||||
spin_lock_irqsave(&qt2160->lock, flags);
|
||||
|
||||
__cancel_delayed_work(&qt2160->dwork);
|
||||
schedule_delayed_work(&qt2160->dwork, 0);
|
||||
mod_delayed_work(system_wq, &qt2160->dwork, 0);
|
||||
|
||||
spin_unlock_irqrestore(&qt2160->lock, flags);
|
||||
|
||||
|
@@ -24,7 +24,7 @@
|
||||
#include <linux/pm_wakeup.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/types.h>
|
||||
#include <plat/keyboard.h>
|
||||
#include <linux/platform_data/keyboard-spear.h>
|
||||
|
||||
/* Keyboard Registers */
|
||||
#define MODE_CTL_REG 0x00
|
||||
|
@@ -21,7 +21,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <mach/w90p910_keypad.h>
|
||||
#include <linux/platform_data/keypad-w90p910.h>
|
||||
|
||||
/* Keypad Interface Control Registers */
|
||||
#define KPI_CONF 0x00
|
||||
|
@@ -74,8 +74,8 @@ static int __devinit ab8500_ponkey_probe(struct platform_device *pdev)
|
||||
|
||||
ponkey->idev = input;
|
||||
ponkey->ab8500 = ab8500;
|
||||
ponkey->irq_dbf = ab8500_irq_get_virq(ab8500, irq_dbf);
|
||||
ponkey->irq_dbr = ab8500_irq_get_virq(ab8500, irq_dbr);
|
||||
ponkey->irq_dbf = irq_dbf;
|
||||
ponkey->irq_dbr = irq_dbr;
|
||||
|
||||
input->name = "AB8500 POn(PowerOn) Key";
|
||||
input->dev.parent = &pdev->dev;
|
||||
|
@@ -151,22 +151,7 @@ static struct acpi_driver atlas_acpi_driver = {
|
||||
.remove = atlas_acpi_button_remove,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init atlas_acpi_init(void)
|
||||
{
|
||||
if (acpi_disabled)
|
||||
return -ENODEV;
|
||||
|
||||
return acpi_bus_register_driver(&atlas_acpi_driver);
|
||||
}
|
||||
|
||||
static void __exit atlas_acpi_exit(void)
|
||||
{
|
||||
acpi_bus_unregister_driver(&atlas_acpi_driver);
|
||||
}
|
||||
|
||||
module_init(atlas_acpi_init);
|
||||
module_exit(atlas_acpi_exit);
|
||||
module_acpi_driver(atlas_acpi_driver);
|
||||
|
||||
MODULE_AUTHOR("Jaya Kumar");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@@ -26,6 +26,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/i2c/twl.h>
|
||||
#include <linux/mfd/twl4030-audio.h>
|
||||
@@ -194,13 +195,26 @@ static int twl4030_vibra_resume(struct device *dev)
|
||||
static SIMPLE_DEV_PM_OPS(twl4030_vibra_pm_ops,
|
||||
twl4030_vibra_suspend, twl4030_vibra_resume);
|
||||
|
||||
static bool twl4030_vibra_check_coexist(struct twl4030_vibra_data *pdata,
|
||||
struct device_node *node)
|
||||
{
|
||||
if (pdata && pdata->coexist)
|
||||
return true;
|
||||
|
||||
if (of_find_node_by_name(node, "codec"))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int __devinit twl4030_vibra_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct twl4030_vibra_data *pdata = pdev->dev.platform_data;
|
||||
struct device_node *twl4030_core_node = pdev->dev.parent->of_node;
|
||||
struct vibra_info *info;
|
||||
int ret;
|
||||
|
||||
if (!pdata) {
|
||||
if (!pdata && !twl4030_core_node) {
|
||||
dev_dbg(&pdev->dev, "platform_data not available\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -210,7 +224,7 @@ static int __devinit twl4030_vibra_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
|
||||
info->dev = &pdev->dev;
|
||||
info->coexist = pdata->coexist;
|
||||
info->coexist = twl4030_vibra_check_coexist(pdata, twl4030_core_node);
|
||||
INIT_WORK(&info->play_work, vibra_play_work);
|
||||
|
||||
info->input_dev = input_allocate_device();
|
||||
|
@@ -20,7 +20,7 @@
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/pxa930_trkball.h>
|
||||
#include <linux/platform_data/mouse-pxa930_trkball.h>
|
||||
|
||||
/* Trackball Controller Register Definitions */
|
||||
#define TBCR (0x000C)
|
||||
|
@@ -42,7 +42,7 @@ static irqreturn_t rpcmouse_irq(int irq, void *dev_id)
|
||||
|
||||
x = (short) iomd_readl(IOMD_MOUSEX);
|
||||
y = (short) iomd_readl(IOMD_MOUSEY);
|
||||
b = (short) (__raw_readl(0xe0310000) ^ 0x70);
|
||||
b = (short) (__raw_readl(IOMEM(0xe0310000)) ^ 0x70);
|
||||
|
||||
dx = x - rpcmouse_lastx;
|
||||
dy = y - rpcmouse_lasty;
|
||||
|
@@ -721,6 +721,17 @@ static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse)
|
||||
|
||||
switch (psmouse->packet[0] >> FSP_PKT_TYPE_SHIFT) {
|
||||
case FSP_PKT_TYPE_ABS:
|
||||
|
||||
if ((packet[0] == 0x48 || packet[0] == 0x49) &&
|
||||
packet[1] == 0 && packet[2] == 0) {
|
||||
/*
|
||||
* Ignore coordinate noise when finger leaving the
|
||||
* surface, otherwise cursor may jump to upper-left
|
||||
* corner.
|
||||
*/
|
||||
packet[3] &= 0xf0;
|
||||
}
|
||||
|
||||
abs_x = GET_ABS_X(packet);
|
||||
abs_y = GET_ABS_Y(packet);
|
||||
|
||||
|
@@ -53,14 +53,19 @@
|
||||
#define ABS_POS_BITS 13
|
||||
|
||||
/*
|
||||
* Any position values from the hardware above the following limits are
|
||||
* treated as "wrapped around negative" values that have been truncated to
|
||||
* the 13-bit reporting range of the hardware. These are just reasonable
|
||||
* guesses and can be adjusted if hardware is found that operates outside
|
||||
* of these parameters.
|
||||
* These values should represent the absolute maximum value that will
|
||||
* be reported for a positive position value. Some Synaptics firmware
|
||||
* uses this value to indicate a finger near the edge of the touchpad
|
||||
* whose precise position cannot be determined.
|
||||
*
|
||||
* At least one touchpad is known to report positions in excess of this
|
||||
* value which are actually negative values truncated to the 13-bit
|
||||
* reporting range. These values have never been observed to be lower
|
||||
* than 8184 (i.e. -8), so we treat all values greater than 8176 as
|
||||
* negative and any other value as positive.
|
||||
*/
|
||||
#define X_MAX_POSITIVE (((1 << ABS_POS_BITS) + XMAX) / 2)
|
||||
#define Y_MAX_POSITIVE (((1 << ABS_POS_BITS) + YMAX) / 2)
|
||||
#define X_MAX_POSITIVE 8176
|
||||
#define Y_MAX_POSITIVE 8176
|
||||
|
||||
/*****************************************************************************
|
||||
* Stuff we need even when we do not want native Synaptics support
|
||||
@@ -604,11 +609,21 @@ static int synaptics_parse_hw_state(const unsigned char buf[],
|
||||
hw->right = (buf[0] & 0x02) ? 1 : 0;
|
||||
}
|
||||
|
||||
/* Convert wrap-around values to negative */
|
||||
/*
|
||||
* Convert wrap-around values to negative. (X|Y)_MAX_POSITIVE
|
||||
* is used by some firmware to indicate a finger at the edge of
|
||||
* the touchpad whose precise position cannot be determined, so
|
||||
* convert these values to the maximum axis value.
|
||||
*/
|
||||
if (hw->x > X_MAX_POSITIVE)
|
||||
hw->x -= 1 << ABS_POS_BITS;
|
||||
else if (hw->x == X_MAX_POSITIVE)
|
||||
hw->x = XMAX;
|
||||
|
||||
if (hw->y > Y_MAX_POSITIVE)
|
||||
hw->y -= 1 << ABS_POS_BITS;
|
||||
else if (hw->y == Y_MAX_POSITIVE)
|
||||
hw->y = YMAX;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -376,12 +376,7 @@ static void synaptics_i2c_reschedule_work(struct synaptics_i2c *touch,
|
||||
|
||||
spin_lock_irqsave(&touch->lock, flags);
|
||||
|
||||
/*
|
||||
* If work is already scheduled then subsequent schedules will not
|
||||
* change the scheduled time that's why we have to cancel it first.
|
||||
*/
|
||||
__cancel_delayed_work(&touch->dwork);
|
||||
schedule_delayed_work(&touch->dwork, delay);
|
||||
mod_delayed_work(system_wq, &touch->dwork, delay);
|
||||
|
||||
spin_unlock_irqrestore(&touch->lock, flags);
|
||||
}
|
||||
|
@@ -523,7 +523,6 @@ static int mousedev_release(struct inode *inode, struct file *file)
|
||||
kfree(client);
|
||||
|
||||
mousedev_close_device(mousedev);
|
||||
put_device(&mousedev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -558,7 +557,6 @@ static int mousedev_open(struct inode *inode, struct file *file)
|
||||
file->private_data = client;
|
||||
nonseekable_open(inode, file);
|
||||
|
||||
get_device(&mousedev->dev);
|
||||
return 0;
|
||||
|
||||
err_free_client:
|
||||
@@ -892,6 +890,7 @@ static struct mousedev *mousedev_create(struct input_dev *dev,
|
||||
}
|
||||
|
||||
cdev_init(&mousedev->cdev, &mousedev_fops);
|
||||
mousedev->cdev.kobj.parent = &mousedev->dev.kobj;
|
||||
error = cdev_add(&mousedev->cdev, mousedev->dev.devt, 1);
|
||||
if (error)
|
||||
goto err_unregister_handle;
|
||||
|
@@ -72,7 +72,7 @@ static int amba_kmi_open(struct serio *io)
|
||||
unsigned int divisor;
|
||||
int ret;
|
||||
|
||||
ret = clk_enable(kmi->clk);
|
||||
ret = clk_prepare_enable(kmi->clk);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@@ -92,7 +92,7 @@ static int amba_kmi_open(struct serio *io)
|
||||
return 0;
|
||||
|
||||
clk_disable:
|
||||
clk_disable(kmi->clk);
|
||||
clk_disable_unprepare(kmi->clk);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
@@ -104,7 +104,7 @@ static void amba_kmi_close(struct serio *io)
|
||||
writeb(0, KMICR);
|
||||
|
||||
free_irq(kmi->irq, kmi);
|
||||
clk_disable(kmi->clk);
|
||||
clk_disable_unprepare(kmi->clk);
|
||||
}
|
||||
|
||||
static int __devinit amba_kmi_probe(struct amba_device *dev,
|
||||
|
@@ -27,7 +27,7 @@
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <plat/board-ams-delta.h>
|
||||
#include <mach/board-ams-delta.h>
|
||||
|
||||
#include <mach/ams-delta-fiq.h>
|
||||
|
||||
|
@@ -176,6 +176,20 @@ static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = {
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Spring Peak"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* Gigabyte T1005 - defines wrong chassis type ("Other") */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "T1005"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* Gigabyte T1005M/P - defines wrong chassis type ("Other") */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "T1005M/P"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
|
||||
@@ -319,6 +333,12 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = {
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "EQUIUM A110"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE C850D"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ALIENWARE"),
|
||||
|
@@ -391,7 +391,7 @@ static int wacom_parse_hid(struct usb_interface *intf,
|
||||
features->pktlen = WACOM_PKGLEN_TPC2FG;
|
||||
}
|
||||
|
||||
if (features->type == MTSCREEN)
|
||||
if (features->type == MTSCREEN || WACOM_24HDT)
|
||||
features->pktlen = WACOM_PKGLEN_MTOUCH;
|
||||
|
||||
if (features->type == BAMBOO_PT) {
|
||||
@@ -402,6 +402,14 @@ static int wacom_parse_hid(struct usb_interface *intf,
|
||||
features->x_max =
|
||||
get_unaligned_le16(&report[i + 8]);
|
||||
i += 15;
|
||||
} else if (features->type == WACOM_24HDT) {
|
||||
features->x_max =
|
||||
get_unaligned_le16(&report[i + 3]);
|
||||
features->x_phy =
|
||||
get_unaligned_le16(&report[i + 8]);
|
||||
features->unit = report[i - 1];
|
||||
features->unitExpo = report[i - 3];
|
||||
i += 12;
|
||||
} else {
|
||||
features->x_max =
|
||||
get_unaligned_le16(&report[i + 3]);
|
||||
@@ -434,6 +442,12 @@ static int wacom_parse_hid(struct usb_interface *intf,
|
||||
features->y_phy =
|
||||
get_unaligned_le16(&report[i + 6]);
|
||||
i += 7;
|
||||
} else if (type == WACOM_24HDT) {
|
||||
features->y_max =
|
||||
get_unaligned_le16(&report[i + 3]);
|
||||
features->y_phy =
|
||||
get_unaligned_le16(&report[i - 2]);
|
||||
i += 7;
|
||||
} else if (type == BAMBOO_PT) {
|
||||
features->y_phy =
|
||||
get_unaligned_le16(&report[i + 3]);
|
||||
@@ -541,6 +555,9 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat
|
||||
/* MT Tablet PC touch */
|
||||
return wacom_set_device_mode(intf, 3, 4, 4);
|
||||
}
|
||||
else if (features->type == WACOM_24HDT) {
|
||||
return wacom_set_device_mode(intf, 18, 3, 2);
|
||||
}
|
||||
} else if (features->device_type == BTN_TOOL_PEN) {
|
||||
if (features->type <= BAMBOO_PT && features->type != WIRELESS) {
|
||||
return wacom_set_device_mode(intf, 2, 2, 2);
|
||||
@@ -613,6 +630,30 @@ struct wacom_usbdev_data {
|
||||
static LIST_HEAD(wacom_udev_list);
|
||||
static DEFINE_MUTEX(wacom_udev_list_lock);
|
||||
|
||||
static struct usb_device *wacom_get_sibling(struct usb_device *dev, int vendor, int product)
|
||||
{
|
||||
int port1;
|
||||
struct usb_device *sibling;
|
||||
|
||||
if (vendor == 0 && product == 0)
|
||||
return dev;
|
||||
|
||||
if (dev->parent == NULL)
|
||||
return NULL;
|
||||
|
||||
usb_hub_for_each_child(dev->parent, port1, sibling) {
|
||||
struct usb_device_descriptor *d;
|
||||
if (sibling == NULL)
|
||||
continue;
|
||||
|
||||
d = &sibling->descriptor;
|
||||
if (d->idVendor == vendor && d->idProduct == product)
|
||||
return sibling;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct wacom_usbdev_data *wacom_get_usbdev_data(struct usb_device *dev)
|
||||
{
|
||||
struct wacom_usbdev_data *data;
|
||||
@@ -1257,13 +1298,19 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
|
||||
strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name));
|
||||
|
||||
if (features->quirks & WACOM_QUIRK_MULTI_INPUT) {
|
||||
struct usb_device *other_dev;
|
||||
|
||||
/* Append the device type to the name */
|
||||
strlcat(wacom_wac->name,
|
||||
features->device_type == BTN_TOOL_PEN ?
|
||||
" Pen" : " Finger",
|
||||
sizeof(wacom_wac->name));
|
||||
|
||||
error = wacom_add_shared_data(wacom_wac, dev);
|
||||
|
||||
other_dev = wacom_get_sibling(dev, features->oVid, features->oPid);
|
||||
if (other_dev == NULL || wacom_get_usbdev_data(other_dev) == NULL)
|
||||
other_dev = dev;
|
||||
error = wacom_add_shared_data(wacom_wac, other_dev);
|
||||
if (error)
|
||||
goto fail3;
|
||||
}
|
||||
|
@@ -611,7 +611,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
|
||||
input_report_abs(input, ABS_WHEEL, 0);
|
||||
}
|
||||
|
||||
if (data[2] | (data[3] & 0x01) | data[4]) {
|
||||
if (data[2] | (data[3] & 0x01) | data[4] | data[5]) {
|
||||
input_report_key(input, wacom->tool[1], 1);
|
||||
input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
|
||||
} else {
|
||||
@@ -806,6 +806,70 @@ static int find_slot_from_contactid(struct wacom_wac *wacom, int contactid)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int int_dist(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
int x = x2 - x1;
|
||||
int y = y2 - y1;
|
||||
|
||||
return int_sqrt(x*x + y*y);
|
||||
}
|
||||
|
||||
static int wacom_24hdt_irq(struct wacom_wac *wacom)
|
||||
{
|
||||
struct input_dev *input = wacom->input;
|
||||
char *data = wacom->data;
|
||||
int i;
|
||||
int current_num_contacts = data[61];
|
||||
int contacts_to_send = 0;
|
||||
|
||||
/*
|
||||
* First packet resets the counter since only the first
|
||||
* packet in series will have non-zero current_num_contacts.
|
||||
*/
|
||||
if (current_num_contacts)
|
||||
wacom->num_contacts_left = current_num_contacts;
|
||||
|
||||
/* There are at most 4 contacts per packet */
|
||||
contacts_to_send = min(4, wacom->num_contacts_left);
|
||||
|
||||
for (i = 0; i < contacts_to_send; i++) {
|
||||
int offset = (WACOM_BYTES_PER_24HDT_PACKET * i) + 1;
|
||||
bool touch = data[offset] & 0x1 && !wacom->shared->stylus_in_proximity;
|
||||
int id = data[offset + 1];
|
||||
int slot = find_slot_from_contactid(wacom, id);
|
||||
|
||||
if (slot < 0)
|
||||
continue;
|
||||
input_mt_slot(input, slot);
|
||||
input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
|
||||
|
||||
if (touch) {
|
||||
int t_x = le16_to_cpup((__le16 *)&data[offset + 2]);
|
||||
int c_x = le16_to_cpup((__le16 *)&data[offset + 4]);
|
||||
int t_y = le16_to_cpup((__le16 *)&data[offset + 6]);
|
||||
int c_y = le16_to_cpup((__le16 *)&data[offset + 8]);
|
||||
int w = le16_to_cpup((__le16 *)&data[offset + 10]);
|
||||
int h = le16_to_cpup((__le16 *)&data[offset + 12]);
|
||||
|
||||
input_report_abs(input, ABS_MT_POSITION_X, t_x);
|
||||
input_report_abs(input, ABS_MT_POSITION_Y, t_y);
|
||||
input_report_abs(input, ABS_MT_TOUCH_MAJOR, min(w,h));
|
||||
input_report_abs(input, ABS_MT_WIDTH_MAJOR, min(w, h) + int_dist(t_x, t_y, c_x, c_y));
|
||||
input_report_abs(input, ABS_MT_WIDTH_MINOR, min(w, h));
|
||||
input_report_abs(input, ABS_MT_ORIENTATION, w > h);
|
||||
}
|
||||
wacom->slots[slot] = touch ? id : -1;
|
||||
}
|
||||
|
||||
input_mt_report_pointer_emulation(input, true);
|
||||
|
||||
wacom->num_contacts_left -= contacts_to_send;
|
||||
if (wacom->num_contacts_left <= 0)
|
||||
wacom->num_contacts_left = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int wacom_mt_touch(struct wacom_wac *wacom)
|
||||
{
|
||||
struct input_dev *input = wacom->input;
|
||||
@@ -1255,6 +1319,10 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
|
||||
sync = wacom_intuos_irq(wacom_wac);
|
||||
break;
|
||||
|
||||
case WACOM_24HDT:
|
||||
sync = wacom_24hdt_irq(wacom_wac);
|
||||
break;
|
||||
|
||||
case INTUOS5S:
|
||||
case INTUOS5:
|
||||
case INTUOS5L:
|
||||
@@ -1340,7 +1408,8 @@ void wacom_setup_device_quirks(struct wacom_features *features)
|
||||
|
||||
/* these device have multiple inputs */
|
||||
if (features->type >= WIRELESS ||
|
||||
(features->type >= INTUOS5S && features->type <= INTUOS5L))
|
||||
(features->type >= INTUOS5S && features->type <= INTUOS5L) ||
|
||||
(features->oVid && features->oPid))
|
||||
features->quirks |= WACOM_QUIRK_MULTI_INPUT;
|
||||
|
||||
/* quirk for bamboo touch with 2 low res touches */
|
||||
@@ -1575,6 +1644,15 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
|
||||
__set_bit(INPUT_PROP_POINTER, input_dev->propbit);
|
||||
break;
|
||||
|
||||
case WACOM_24HDT:
|
||||
if (features->device_type == BTN_TOOL_FINGER) {
|
||||
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, features->x_max, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, features->x_max, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_MT_WIDTH_MINOR, 0, features->y_max, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0);
|
||||
}
|
||||
/* fall through */
|
||||
|
||||
case MTSCREEN:
|
||||
if (features->device_type == BTN_TOOL_FINGER) {
|
||||
wacom_wac->slots = kmalloc(features->touch_max *
|
||||
@@ -1869,8 +1947,11 @@ static const struct wacom_features wacom_features_0xF4 =
|
||||
{ "Wacom Cintiq 24HD", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047,
|
||||
63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
|
||||
static const struct wacom_features wacom_features_0xF8 =
|
||||
{ "Wacom Cintiq 24HD touch", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047,
|
||||
63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
|
||||
{ "Wacom Cintiq 24HD touch", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047, /* Pen */
|
||||
63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf6 };
|
||||
static const struct wacom_features wacom_features_0xF6 =
|
||||
{ "Wacom Cintiq 24HD touch", .type = WACOM_24HDT, /* Touch */
|
||||
.oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf8, .touch_max = 10 };
|
||||
static const struct wacom_features wacom_features_0x3F =
|
||||
{ "Wacom Cintiq 21UX", WACOM_PKGLEN_INTUOS, 87200, 65600, 1023,
|
||||
63, CINTIQ, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
|
||||
@@ -2113,6 +2194,7 @@ const struct usb_device_id wacom_ids[] = {
|
||||
{ USB_DEVICE_WACOM(0x47) },
|
||||
{ USB_DEVICE_WACOM(0xF4) },
|
||||
{ USB_DEVICE_WACOM(0xF8) },
|
||||
{ USB_DEVICE_WACOM(0xF6) },
|
||||
{ USB_DEVICE_WACOM(0xFA) },
|
||||
{ USB_DEVICE_LENOVO(0x6004) },
|
||||
{ }
|
||||
|
@@ -29,6 +29,7 @@
|
||||
|
||||
/* wacom data size per MT contact */
|
||||
#define WACOM_BYTES_PER_MT_PACKET 11
|
||||
#define WACOM_BYTES_PER_24HDT_PACKET 14
|
||||
|
||||
/* device IDs */
|
||||
#define STYLUS_DEVICE_ID 0x02
|
||||
@@ -49,6 +50,7 @@
|
||||
#define WACOM_REPORT_TPCHID 15
|
||||
#define WACOM_REPORT_TPCST 16
|
||||
#define WACOM_REPORT_TPC1FGE 18
|
||||
#define WACOM_REPORT_24HDT 1
|
||||
|
||||
/* device quirks */
|
||||
#define WACOM_QUIRK_MULTI_INPUT 0x0001
|
||||
@@ -81,6 +83,7 @@ enum {
|
||||
WACOM_MO,
|
||||
WIRELESS,
|
||||
BAMBOO_PT,
|
||||
WACOM_24HDT,
|
||||
TABLETPC, /* add new TPC below */
|
||||
TABLETPCE,
|
||||
TABLETPC2FG,
|
||||
@@ -109,6 +112,8 @@ struct wacom_features {
|
||||
int distance_fuzz;
|
||||
unsigned quirks;
|
||||
unsigned touch_max;
|
||||
int oVid;
|
||||
int oPid;
|
||||
};
|
||||
|
||||
struct wacom_shared {
|
||||
|
@@ -10,6 +10,7 @@
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/input.h>
|
||||
@@ -113,14 +114,69 @@ static void pm860x_touch_close(struct input_dev *dev)
|
||||
pm860x_set_bits(touch->i2c, MEAS_EN3, data, 0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static int __devinit pm860x_touch_dt_init(struct platform_device *pdev,
|
||||
struct pm860x_chip *chip,
|
||||
int *res_x)
|
||||
{
|
||||
struct device_node *np = pdev->dev.parent->of_node;
|
||||
struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
|
||||
: chip->companion;
|
||||
int data, n, ret;
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
np = of_find_node_by_name(np, "touch");
|
||||
if (!np) {
|
||||
dev_err(&pdev->dev, "Can't find touch node\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
/* set GPADC MISC1 register */
|
||||
data = 0;
|
||||
if (!of_property_read_u32(np, "marvell,88pm860x-gpadc-prebias", &n))
|
||||
data |= (n << 1) & PM8607_GPADC_PREBIAS_MASK;
|
||||
if (!of_property_read_u32(np, "marvell,88pm860x-gpadc-slot-cycle", &n))
|
||||
data |= (n << 3) & PM8607_GPADC_SLOT_CYCLE_MASK;
|
||||
if (!of_property_read_u32(np, "marvell,88pm860x-gpadc-off-scale", &n))
|
||||
data |= (n << 5) & PM8607_GPADC_OFF_SCALE_MASK;
|
||||
if (!of_property_read_u32(np, "marvell,88pm860x-gpadc-sw-cal", &n))
|
||||
data |= (n << 7) & PM8607_GPADC_SW_CAL_MASK;
|
||||
if (data) {
|
||||
ret = pm860x_reg_write(i2c, PM8607_GPADC_MISC1, data);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
}
|
||||
/* set tsi prebias time */
|
||||
if (!of_property_read_u32(np, "marvell,88pm860x-tsi-prebias", &data)) {
|
||||
ret = pm860x_reg_write(i2c, PM8607_TSI_PREBIAS, data);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
}
|
||||
/* set prebias & prechg time of pen detect */
|
||||
data = 0;
|
||||
if (!of_property_read_u32(np, "marvell,88pm860x-pen-prebias", &n))
|
||||
data |= n & PM8607_PD_PREBIAS_MASK;
|
||||
if (!of_property_read_u32(np, "marvell,88pm860x-pen-prechg", &n))
|
||||
data |= n & PM8607_PD_PRECHG_MASK;
|
||||
if (data) {
|
||||
ret = pm860x_reg_write(i2c, PM8607_PD_PREBIAS, data);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
}
|
||||
of_property_read_u32(np, "marvell,88pm860x-resistor-X", res_x);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define pm860x_touch_dt_init(x, y, z) (-1)
|
||||
#endif
|
||||
|
||||
static int __devinit pm860x_touch_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
|
||||
struct pm860x_platform_data *pm860x_pdata = \
|
||||
pdev->dev.parent->platform_data;
|
||||
struct pm860x_touch_pdata *pdata = NULL;
|
||||
struct pm860x_touch_pdata *pdata = pdev->dev.platform_data;
|
||||
struct pm860x_touch *touch;
|
||||
int irq, ret;
|
||||
struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
|
||||
: chip->companion;
|
||||
int irq, ret, res_x = 0, data = 0;
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
@@ -128,16 +184,55 @@ static int __devinit pm860x_touch_probe(struct platform_device *pdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!pm860x_pdata) {
|
||||
dev_err(&pdev->dev, "platform data is missing\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pdata = pm860x_pdata->touch;
|
||||
if (!pdata) {
|
||||
dev_err(&pdev->dev, "touchscreen data is missing\n");
|
||||
return -EINVAL;
|
||||
if (pm860x_touch_dt_init(pdev, chip, &res_x)) {
|
||||
if (pdata) {
|
||||
/* set GPADC MISC1 register */
|
||||
data = 0;
|
||||
data |= (pdata->gpadc_prebias << 1)
|
||||
& PM8607_GPADC_PREBIAS_MASK;
|
||||
data |= (pdata->slot_cycle << 3)
|
||||
& PM8607_GPADC_SLOT_CYCLE_MASK;
|
||||
data |= (pdata->off_scale << 5)
|
||||
& PM8607_GPADC_OFF_SCALE_MASK;
|
||||
data |= (pdata->sw_cal << 7)
|
||||
& PM8607_GPADC_SW_CAL_MASK;
|
||||
if (data) {
|
||||
ret = pm860x_reg_write(i2c,
|
||||
PM8607_GPADC_MISC1, data);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
}
|
||||
/* set tsi prebias time */
|
||||
if (pdata->tsi_prebias) {
|
||||
data = pdata->tsi_prebias;
|
||||
ret = pm860x_reg_write(i2c,
|
||||
PM8607_TSI_PREBIAS, data);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
}
|
||||
/* set prebias & prechg time of pen detect */
|
||||
data = 0;
|
||||
data |= pdata->pen_prebias
|
||||
& PM8607_PD_PREBIAS_MASK;
|
||||
data |= (pdata->pen_prechg << 5)
|
||||
& PM8607_PD_PRECHG_MASK;
|
||||
if (data) {
|
||||
ret = pm860x_reg_write(i2c,
|
||||
PM8607_PD_PREBIAS, data);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
}
|
||||
res_x = pdata->res_x;
|
||||
} else {
|
||||
dev_err(&pdev->dev, "failed to get platform data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
/* enable GPADC */
|
||||
ret = pm860x_set_bits(i2c, PM8607_GPADC_MISC1, PM8607_GPADC_EN,
|
||||
PM8607_GPADC_EN);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
touch = kzalloc(sizeof(struct pm860x_touch), GFP_KERNEL);
|
||||
if (touch == NULL)
|
||||
@@ -158,9 +253,9 @@ static int __devinit pm860x_touch_probe(struct platform_device *pdev)
|
||||
touch->idev->open = pm860x_touch_open;
|
||||
touch->idev->close = pm860x_touch_close;
|
||||
touch->chip = chip;
|
||||
touch->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
|
||||
touch->irq = irq + chip->irq_base;
|
||||
touch->res_x = pdata->res_x;
|
||||
touch->i2c = i2c;
|
||||
touch->irq = irq;
|
||||
touch->res_x = res_x;
|
||||
input_set_drvdata(touch->idev, touch);
|
||||
|
||||
ret = request_threaded_irq(touch->irq, NULL, pm860x_touch_handler,
|
||||
|
@@ -558,9 +558,12 @@ static ssize_t edt_ft5x06_debugfs_raw_data_read(struct file *file,
|
||||
}
|
||||
|
||||
read = min_t(size_t, count, tsdata->raw_bufsize - *off);
|
||||
error = copy_to_user(buf, tsdata->raw_buffer + *off, read);
|
||||
if (!error)
|
||||
*off += read;
|
||||
if (copy_to_user(buf, tsdata->raw_buffer + *off, read)) {
|
||||
error = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
*off += read;
|
||||
out:
|
||||
mutex_unlock(&tsdata->mutex);
|
||||
return error ?: read;
|
||||
@@ -594,6 +597,7 @@ edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata)
|
||||
{
|
||||
if (tsdata->debug_dir)
|
||||
debugfs_remove_recursive(tsdata->debug_dir);
|
||||
kfree(tsdata->raw_buffer);
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -835,7 +839,6 @@ static int __devexit edt_ft5x06_ts_remove(struct i2c_client *client)
|
||||
if (gpio_is_valid(pdata->reset_pin))
|
||||
gpio_free(pdata->reset_pin);
|
||||
|
||||
kfree(tsdata->raw_buffer);
|
||||
kfree(tsdata);
|
||||
|
||||
return 0;
|
||||
|
@@ -37,7 +37,7 @@
|
||||
|
||||
#include <plat/adc.h>
|
||||
#include <plat/regs-adc.h>
|
||||
#include <plat/ts.h>
|
||||
#include <linux/platform_data/touchscreen-s3c2410.h>
|
||||
|
||||
#define TSC_SLEEP (S3C2410_ADCTSC_PULL_UP_DISABLE | S3C2410_ADCTSC_XY_PST(0))
|
||||
|
||||
|
@@ -304,6 +304,45 @@ static int e2i_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
|
||||
#define EGALAX_PKT_TYPE_REPT 0x80
|
||||
#define EGALAX_PKT_TYPE_DIAG 0x0A
|
||||
|
||||
static int egalax_init(struct usbtouch_usb *usbtouch)
|
||||
{
|
||||
int ret, i;
|
||||
unsigned char *buf;
|
||||
struct usb_device *udev = interface_to_usbdev(usbtouch->interface);
|
||||
|
||||
/*
|
||||
* An eGalax diagnostic packet kicks the device into using the right
|
||||
* protocol. We send a "check active" packet. The response will be
|
||||
* read later and ignored.
|
||||
*/
|
||||
|
||||
buf = kmalloc(3, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
buf[0] = EGALAX_PKT_TYPE_DIAG;
|
||||
buf[1] = 1; /* length */
|
||||
buf[2] = 'A'; /* command - check active */
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
|
||||
0,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||||
0, 0, buf, 3,
|
||||
USB_CTRL_SET_TIMEOUT);
|
||||
if (ret >= 0) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
if (ret != -EPIPE)
|
||||
break;
|
||||
}
|
||||
|
||||
kfree(buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int egalax_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
|
||||
{
|
||||
if ((pkt[0] & EGALAX_PKT_TYPE_MASK) != EGALAX_PKT_TYPE_REPT)
|
||||
@@ -1056,6 +1095,7 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
|
||||
.process_pkt = usbtouch_process_multi,
|
||||
.get_pkt_len = egalax_get_pkt_len,
|
||||
.read_data = egalax_read_data,
|
||||
.init = egalax_init,
|
||||
},
|
||||
#endif
|
||||
|
||||
|
@@ -221,7 +221,7 @@ static void wm831x_ts_input_close(struct input_dev *idev)
|
||||
synchronize_irq(wm831x_ts->pd_irq);
|
||||
|
||||
/* Make sure the IRQ completion work is quiesced */
|
||||
flush_work_sync(&wm831x_ts->pd_data_work);
|
||||
flush_work(&wm831x_ts->pd_data_work);
|
||||
|
||||
/* If we ended up with the pen down then make sure we revert back
|
||||
* to pen detection state for the next time we start up.
|
||||
|
Reference in New Issue
Block a user