Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input updates from Dmitry Torokhov: - a new GPIO bit-banging driver implementing PS/2 protocol - a new power key driver for Rockchip RK805 PMIC - bunch of patches constifying various device ID structures - Elan I2C touchpad driver now supports devices with 2 buttons - other assorted fixes * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (76 commits) Input: byd - make array seq static, reduces object code size Input: xilinx_ps2 - fix multiline comment style Input: pxa27x_keypad - handle return value of clk_prepare_enable Input: tegra-kbc - handle return value of clk_prepare_enable Input: PS/2 gpio bit banging driver for serio bus Input: xen-kbdfront - enable auto repeat for xen keyboard frontend driver Input: ambakmi - constify amba_id Input: atmel_mxt_ts - add support for reset line Input: atmel_mxt_ts - use more managed resources Input: wacom_w8001 - constify serio_device_id Input: tsc40 - constify serio_device_id Input: touchwin - constify serio_device_id Input: touchright - constify serio_device_id Input: touchit213 - constify serio_device_id Input: penmount - constify serio_device_id Input: mtouch - constify serio_device_id Input: inexio - constify serio_device_id Input: hampshire - constify serio_device_id Input: gunze - constify serio_device_id Input: fujitsu_ts - constify serio_device_id ...
This commit is contained in:
commit
9d71941d39
|
@ -22,6 +22,8 @@ Optional properties for main touchpad device:
|
|||
experiment to determine which bit corresponds to which input. Use
|
||||
KEY_RESERVED for unused padding values.
|
||||
|
||||
- reset-gpios: GPIO specifier for the touchscreen's reset pin (active low)
|
||||
|
||||
Example:
|
||||
|
||||
touch@4b {
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
Device-Tree binding for ps/2 gpio device
|
||||
|
||||
Required properties:
|
||||
- compatible = "ps2-gpio"
|
||||
- data-gpios: the data pin
|
||||
- clk-gpios: the clock pin
|
||||
- interrupts: Should trigger on the falling edge of the clock line.
|
||||
|
||||
Optional properties:
|
||||
- write-enable: Indicates whether write function is provided
|
||||
to serio device. Possibly providing the write fn will not work, because
|
||||
of the tough timing requirements.
|
||||
|
||||
Example nodes:
|
||||
|
||||
ps2@0 {
|
||||
compatible = "ps2-gpio";
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <23 IRQ_TYPE_EDGE_FALLING>;
|
||||
data-gpios = <&gpio 24 GPIO_ACTIVE_HIGH>;
|
||||
clk-gpios = <&gpio 23 GPIO_ACTIVE_HIGH>;
|
||||
write-enable;
|
||||
};
|
|
@ -84,6 +84,11 @@ hardware descriptions such as device tree or ACPI:
|
|||
NAND flash MTD subsystem and provides chip access and partition parsing like
|
||||
any other NAND driving hardware.
|
||||
|
||||
- ps2-gpio: drivers/input/serio/ps2-gpio.c is used to drive a PS/2 (IBM) serio
|
||||
bus, data and clock line, by bit banging two GPIO lines. It will appear as
|
||||
any other serio bus to the system and makes it possible to connect drivers
|
||||
for e.g. keyboards and other PS/2 protocol based devices.
|
||||
|
||||
Apart from this there are special GPIO drivers in subsystems like MMC/SD to
|
||||
read card detect and write protect GPIO lines, and in the TTY serial subsystem
|
||||
to emulate MCTRL (modem control) signals CTS/RTS by using two GPIO lines. The
|
||||
|
|
|
@ -377,7 +377,7 @@ static struct gpiod_lookup_table raumfeld_rotary_gpios_table = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct property_entry raumfeld_rotary_properties[] = {
|
||||
static const struct property_entry raumfeld_rotary_properties[] __initconst = {
|
||||
PROPERTY_ENTRY_INTEGER("rotary-encoder,steps-per-period", u32, 24),
|
||||
PROPERTY_ENTRY_INTEGER("linux,axis", u32, REL_X),
|
||||
PROPERTY_ENTRY_INTEGER("rotary-encoder,relative_axis", u32, 1),
|
||||
|
|
|
@ -1398,7 +1398,7 @@ static struct attribute *input_dev_attrs[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group input_dev_attr_group = {
|
||||
static const struct attribute_group input_dev_attr_group = {
|
||||
.attrs = input_dev_attrs,
|
||||
};
|
||||
|
||||
|
@ -1425,7 +1425,7 @@ static struct attribute *input_dev_id_attrs[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group input_dev_id_attr_group = {
|
||||
static const struct attribute_group input_dev_id_attr_group = {
|
||||
.name = "id",
|
||||
.attrs = input_dev_id_attrs,
|
||||
};
|
||||
|
@ -1495,7 +1495,7 @@ static struct attribute *input_dev_caps_attrs[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group input_dev_caps_attr_group = {
|
||||
static const struct attribute_group input_dev_caps_attr_group = {
|
||||
.name = "capabilities",
|
||||
.attrs = input_dev_caps_attrs,
|
||||
};
|
||||
|
|
|
@ -164,7 +164,7 @@ static void iforce_serio_disconnect(struct serio *serio)
|
|||
kfree(iforce);
|
||||
}
|
||||
|
||||
static struct serio_device_id iforce_serio_ids[] = {
|
||||
static const struct serio_device_id iforce_serio_ids[] = {
|
||||
{
|
||||
.type = SERIO_RS232,
|
||||
.proto = SERIO_IFORCE,
|
||||
|
|
|
@ -209,7 +209,7 @@ static void iforce_usb_disconnect(struct usb_interface *intf)
|
|||
kfree(iforce);
|
||||
}
|
||||
|
||||
static struct usb_device_id iforce_usb_ids [] = {
|
||||
static const struct usb_device_id iforce_usb_ids[] = {
|
||||
{ USB_DEVICE(0x044f, 0xa01c) }, /* Thrustmaster Motor Sport GT */
|
||||
{ USB_DEVICE(0x046d, 0xc281) }, /* Logitech WingMan Force */
|
||||
{ USB_DEVICE(0x046d, 0xc291) }, /* Logitech WingMan Formula Force */
|
||||
|
|
|
@ -198,7 +198,7 @@ static int magellan_connect(struct serio *serio, struct serio_driver *drv)
|
|||
* The serio driver structure.
|
||||
*/
|
||||
|
||||
static struct serio_device_id magellan_serio_ids[] = {
|
||||
static const struct serio_device_id magellan_serio_ids[] = {
|
||||
{
|
||||
.type = SERIO_RS232,
|
||||
.proto = SERIO_MAGELLAN,
|
||||
|
|
|
@ -272,7 +272,7 @@ static int spaceball_connect(struct serio *serio, struct serio_driver *drv)
|
|||
* The serio driver structure.
|
||||
*/
|
||||
|
||||
static struct serio_device_id spaceball_serio_ids[] = {
|
||||
static const struct serio_device_id spaceball_serio_ids[] = {
|
||||
{
|
||||
.type = SERIO_RS232,
|
||||
.proto = SERIO_SPACEBALL,
|
||||
|
|
|
@ -213,7 +213,7 @@ static int spaceorb_connect(struct serio *serio, struct serio_driver *drv)
|
|||
* The serio driver structure.
|
||||
*/
|
||||
|
||||
static struct serio_device_id spaceorb_serio_ids[] = {
|
||||
static const struct serio_device_id spaceorb_serio_ids[] = {
|
||||
{
|
||||
.type = SERIO_RS232,
|
||||
.proto = SERIO_SPACEORB,
|
||||
|
|
|
@ -184,7 +184,7 @@ static int stinger_connect(struct serio *serio, struct serio_driver *drv)
|
|||
* The serio driver structure.
|
||||
*/
|
||||
|
||||
static struct serio_device_id stinger_serio_ids[] = {
|
||||
static const struct serio_device_id stinger_serio_ids[] = {
|
||||
{
|
||||
.type = SERIO_RS232,
|
||||
.proto = SERIO_STINGER,
|
||||
|
|
|
@ -233,7 +233,7 @@ static int twidjoy_connect(struct serio *serio, struct serio_driver *drv)
|
|||
* The serio driver structure.
|
||||
*/
|
||||
|
||||
static struct serio_device_id twidjoy_serio_ids[] = {
|
||||
static const struct serio_device_id twidjoy_serio_ids[] = {
|
||||
{
|
||||
.type = SERIO_RS232,
|
||||
.proto = SERIO_TWIDJOY,
|
||||
|
|
|
@ -193,7 +193,7 @@ static int warrior_connect(struct serio *serio, struct serio_driver *drv)
|
|||
* The serio driver structure.
|
||||
*/
|
||||
|
||||
static struct serio_device_id warrior_serio_ids[] = {
|
||||
static const struct serio_device_id warrior_serio_ids[] = {
|
||||
{
|
||||
.type = SERIO_RS232,
|
||||
.proto = SERIO_WARRIOR,
|
||||
|
|
|
@ -408,7 +408,7 @@ static const signed short xpad_abs_triggers[] = {
|
|||
#define XPAD_XBOXONE_VENDOR(vend) \
|
||||
{ XPAD_XBOXONE_VENDOR_PROTOCOL(vend, 208) }
|
||||
|
||||
static struct usb_device_id xpad_table[] = {
|
||||
static const struct usb_device_id xpad_table[] = {
|
||||
{ USB_INTERFACE_INFO('X', 'B', 0) }, /* X-Box USB-IF not approved class */
|
||||
XPAD_XBOX360_VENDOR(0x044f), /* Thrustmaster X-Box 360 controllers */
|
||||
XPAD_XBOX360_VENDOR(0x045e), /* Microsoft X-Box 360 controllers */
|
||||
|
|
|
@ -192,7 +192,7 @@ static int zhenhua_connect(struct serio *serio, struct serio_driver *drv)
|
|||
* The serio driver structure.
|
||||
*/
|
||||
|
||||
static struct serio_device_id zhenhua_serio_ids[] = {
|
||||
static const struct serio_device_id zhenhua_serio_ids[] = {
|
||||
{
|
||||
.type = SERIO_RS232,
|
||||
.proto = SERIO_ZHENHUA,
|
||||
|
|
|
@ -1270,7 +1270,7 @@ static int atkbd_reconnect(struct serio *serio)
|
|||
return retval;
|
||||
}
|
||||
|
||||
static struct serio_device_id atkbd_serio_ids[] = {
|
||||
static const struct serio_device_id atkbd_serio_ids[] = {
|
||||
{
|
||||
.type = SERIO_8042,
|
||||
.proto = SERIO_ANY,
|
||||
|
|
|
@ -353,7 +353,7 @@ static struct attribute *gpio_keys_attrs[] = {
|
|||
NULL,
|
||||
};
|
||||
|
||||
static struct attribute_group gpio_keys_attr_group = {
|
||||
static const struct attribute_group gpio_keys_attr_group = {
|
||||
.attrs = gpio_keys_attrs,
|
||||
};
|
||||
|
||||
|
|
|
@ -559,7 +559,7 @@ static int hil_dev_connect(struct serio *serio, struct serio_driver *drv)
|
|||
return error;
|
||||
}
|
||||
|
||||
static struct serio_device_id hil_dev_ids[] = {
|
||||
static const struct serio_device_id hil_dev_ids[] = {
|
||||
{
|
||||
.type = SERIO_HIL_MLC,
|
||||
.proto = SERIO_HIL,
|
||||
|
|
|
@ -707,7 +707,7 @@ static void lkkbd_disconnect(struct serio *serio)
|
|||
kfree(lk);
|
||||
}
|
||||
|
||||
static struct serio_device_id lkkbd_serio_ids[] = {
|
||||
static const struct serio_device_id lkkbd_serio_ids[] = {
|
||||
{
|
||||
.type = SERIO_RS232,
|
||||
.proto = SERIO_LKKBD,
|
||||
|
|
|
@ -142,7 +142,7 @@ static void nkbd_disconnect(struct serio *serio)
|
|||
kfree(nkbd);
|
||||
}
|
||||
|
||||
static struct serio_device_id nkbd_serio_ids[] = {
|
||||
static const struct serio_device_id nkbd_serio_ids[] = {
|
||||
{
|
||||
.type = SERIO_RS232,
|
||||
.proto = SERIO_NEWTON,
|
||||
|
|
|
@ -644,9 +644,12 @@ static void pxa27x_keypad_config(struct pxa27x_keypad *keypad)
|
|||
static int pxa27x_keypad_open(struct input_dev *dev)
|
||||
{
|
||||
struct pxa27x_keypad *keypad = input_get_drvdata(dev);
|
||||
|
||||
int ret;
|
||||
/* Enable unit clock */
|
||||
clk_prepare_enable(keypad->clk);
|
||||
ret = clk_prepare_enable(keypad->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pxa27x_keypad_config(keypad);
|
||||
|
||||
return 0;
|
||||
|
@ -683,6 +686,7 @@ static int pxa27x_keypad_resume(struct device *dev)
|
|||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct pxa27x_keypad *keypad = platform_get_drvdata(pdev);
|
||||
struct input_dev *input_dev = keypad->input_dev;
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
* If the keypad is used as wake up source, the clock is not turned
|
||||
|
@ -695,14 +699,15 @@ static int pxa27x_keypad_resume(struct device *dev)
|
|||
|
||||
if (input_dev->users) {
|
||||
/* Enable unit clock */
|
||||
clk_prepare_enable(keypad->clk);
|
||||
pxa27x_keypad_config(keypad);
|
||||
ret = clk_prepare_enable(keypad->clk);
|
||||
if (!ret)
|
||||
pxa27x_keypad_config(keypad);
|
||||
}
|
||||
|
||||
mutex_unlock(&input_dev->mutex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -146,7 +146,7 @@ static void skbd_disconnect(struct serio *serio)
|
|||
kfree(skbd);
|
||||
}
|
||||
|
||||
static struct serio_device_id skbd_serio_ids[] = {
|
||||
static const struct serio_device_id skbd_serio_ids[] = {
|
||||
{
|
||||
.type = SERIO_RS232,
|
||||
.proto = SERIO_STOWAWAY,
|
||||
|
|
|
@ -339,7 +339,7 @@ static void sunkbd_disconnect(struct serio *serio)
|
|||
kfree(sunkbd);
|
||||
}
|
||||
|
||||
static struct serio_device_id sunkbd_serio_ids[] = {
|
||||
static const struct serio_device_id sunkbd_serio_ids[] = {
|
||||
{
|
||||
.type = SERIO_RS232,
|
||||
.proto = SERIO_SUNKBD,
|
||||
|
|
|
@ -370,8 +370,11 @@ static int tegra_kbc_start(struct tegra_kbc *kbc)
|
|||
{
|
||||
unsigned int debounce_cnt;
|
||||
u32 val = 0;
|
||||
int ret;
|
||||
|
||||
clk_prepare_enable(kbc->clk);
|
||||
ret = clk_prepare_enable(kbc->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Reset the KBC controller to clear all previous status.*/
|
||||
reset_control_assert(kbc->rst);
|
||||
|
|
|
@ -145,7 +145,7 @@ static void xtkbd_disconnect(struct serio *serio)
|
|||
kfree(xtkbd);
|
||||
}
|
||||
|
||||
static struct serio_device_id xtkbd_serio_ids[] = {
|
||||
static const struct serio_device_id xtkbd_serio_ids[] = {
|
||||
{
|
||||
.type = SERIO_XT,
|
||||
.proto = SERIO_ANY,
|
||||
|
|
|
@ -581,6 +581,17 @@ config INPUT_PWM_BEEPER
|
|||
To compile this driver as a module, choose M here: the module will be
|
||||
called pwm-beeper.
|
||||
|
||||
config INPUT_RK805_PWRKEY
|
||||
tristate "Rockchip RK805 PMIC power key support"
|
||||
depends on MFD_RK808
|
||||
help
|
||||
Select this option to enable power key driver for RK805.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
To compile this driver as a module, choose M here: the module will be
|
||||
called rk805_pwrkey.
|
||||
|
||||
config INPUT_GPIO_ROTARY_ENCODER
|
||||
tristate "Rotary encoders connected to GPIO pins"
|
||||
depends on GPIOLIB || COMPILE_TEST
|
||||
|
|
|
@ -64,6 +64,7 @@ obj-$(CONFIG_INPUT_REGULATOR_HAPTIC) += regulator-haptic.o
|
|||
obj-$(CONFIG_INPUT_RETU_PWRBUTTON) += retu-pwrbutton.o
|
||||
obj-$(CONFIG_INPUT_AXP20X_PEK) += axp20x-pek.o
|
||||
obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o
|
||||
obj-$(CONFIG_INPUT_RK805_PWRKEY) += rk805-pwrkey.o
|
||||
obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o
|
||||
obj-$(CONFIG_INPUT_SIRFSOC_ONKEY) += sirfsoc-onkey.o
|
||||
obj-$(CONFIG_INPUT_SOC_BUTTON_ARRAY) += soc_button_array.o
|
||||
|
|
|
@ -110,7 +110,7 @@ static const struct kernel_param_ops param_ops_mode_mask = {
|
|||
module_param(mode_mask, mode_mask, 0644);
|
||||
MODULE_PARM_DESC(mode_mask, "Bitmask of modes to accept <4:PC><3:AUX4><2:AUX3><1:AUX2><0:AUX1>");
|
||||
|
||||
static struct usb_device_id ati_remote2_id_table[] = {
|
||||
static const struct usb_device_id ati_remote2_id_table[] = {
|
||||
{ USB_DEVICE(0x0471, 0x0602) }, /* ATI Remote Wonder II */
|
||||
{ }
|
||||
};
|
||||
|
|
|
@ -29,9 +29,17 @@
|
|||
#define AXP20X_PEK_STARTUP_MASK (0xc0)
|
||||
#define AXP20X_PEK_SHUTDOWN_MASK (0x03)
|
||||
|
||||
struct axp20x_info {
|
||||
const struct axp20x_time *startup_time;
|
||||
unsigned int startup_mask;
|
||||
const struct axp20x_time *shutdown_time;
|
||||
unsigned int shutdown_mask;
|
||||
};
|
||||
|
||||
struct axp20x_pek {
|
||||
struct axp20x_dev *axp20x;
|
||||
struct input_dev *input;
|
||||
struct axp20x_info *info;
|
||||
int irq_dbr;
|
||||
int irq_dbf;
|
||||
};
|
||||
|
@ -48,6 +56,13 @@ static const struct axp20x_time startup_time[] = {
|
|||
{ .time = 2000, .idx = 3 },
|
||||
};
|
||||
|
||||
static const struct axp20x_time axp221_startup_time[] = {
|
||||
{ .time = 128, .idx = 0 },
|
||||
{ .time = 1000, .idx = 1 },
|
||||
{ .time = 2000, .idx = 2 },
|
||||
{ .time = 3000, .idx = 3 },
|
||||
};
|
||||
|
||||
static const struct axp20x_time shutdown_time[] = {
|
||||
{ .time = 4000, .idx = 0 },
|
||||
{ .time = 6000, .idx = 1 },
|
||||
|
@ -55,31 +70,25 @@ static const struct axp20x_time shutdown_time[] = {
|
|||
{ .time = 10000, .idx = 3 },
|
||||
};
|
||||
|
||||
struct axp20x_pek_ext_attr {
|
||||
const struct axp20x_time *p_time;
|
||||
unsigned int mask;
|
||||
static const struct axp20x_info axp20x_info = {
|
||||
.startup_time = startup_time,
|
||||
.startup_mask = AXP20X_PEK_STARTUP_MASK,
|
||||
.shutdown_time = shutdown_time,
|
||||
.shutdown_mask = AXP20X_PEK_SHUTDOWN_MASK,
|
||||
};
|
||||
|
||||
static struct axp20x_pek_ext_attr axp20x_pek_startup_ext_attr = {
|
||||
.p_time = startup_time,
|
||||
.mask = AXP20X_PEK_STARTUP_MASK,
|
||||
static const struct axp20x_info axp221_info = {
|
||||
.startup_time = axp221_startup_time,
|
||||
.startup_mask = AXP20X_PEK_STARTUP_MASK,
|
||||
.shutdown_time = shutdown_time,
|
||||
.shutdown_mask = AXP20X_PEK_SHUTDOWN_MASK,
|
||||
};
|
||||
|
||||
static struct axp20x_pek_ext_attr axp20x_pek_shutdown_ext_attr = {
|
||||
.p_time = shutdown_time,
|
||||
.mask = AXP20X_PEK_SHUTDOWN_MASK,
|
||||
};
|
||||
|
||||
static struct axp20x_pek_ext_attr *get_axp_ext_attr(struct device_attribute *attr)
|
||||
{
|
||||
return container_of(attr, struct dev_ext_attribute, attr)->var;
|
||||
}
|
||||
|
||||
static ssize_t axp20x_show_ext_attr(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t axp20x_show_attr(struct device *dev,
|
||||
const struct axp20x_time *time,
|
||||
unsigned int mask, char *buf)
|
||||
{
|
||||
struct axp20x_pek *axp20x_pek = dev_get_drvdata(dev);
|
||||
struct axp20x_pek_ext_attr *axp20x_ea = get_axp_ext_attr(attr);
|
||||
unsigned int val;
|
||||
int ret, i;
|
||||
|
||||
|
@ -87,22 +96,42 @@ static ssize_t axp20x_show_ext_attr(struct device *dev,
|
|||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
val &= axp20x_ea->mask;
|
||||
val >>= ffs(axp20x_ea->mask) - 1;
|
||||
val &= mask;
|
||||
val >>= ffs(mask) - 1;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
if (val == axp20x_ea->p_time[i].idx)
|
||||
val = axp20x_ea->p_time[i].time;
|
||||
if (val == time[i].idx)
|
||||
val = time[i].time;
|
||||
|
||||
return sprintf(buf, "%u\n", val);
|
||||
}
|
||||
|
||||
static ssize_t axp20x_store_ext_attr(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
static ssize_t axp20x_show_attr_startup(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct axp20x_pek *axp20x_pek = dev_get_drvdata(dev);
|
||||
|
||||
return axp20x_show_attr(dev, axp20x_pek->info->startup_time,
|
||||
axp20x_pek->info->startup_mask, buf);
|
||||
}
|
||||
|
||||
static ssize_t axp20x_show_attr_shutdown(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct axp20x_pek *axp20x_pek = dev_get_drvdata(dev);
|
||||
|
||||
return axp20x_show_attr(dev, axp20x_pek->info->shutdown_time,
|
||||
axp20x_pek->info->shutdown_mask, buf);
|
||||
}
|
||||
|
||||
static ssize_t axp20x_store_attr(struct device *dev,
|
||||
const struct axp20x_time *time,
|
||||
unsigned int mask, const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
struct axp20x_pek *axp20x_pek = dev_get_drvdata(dev);
|
||||
struct axp20x_pek_ext_attr *axp20x_ea = get_axp_ext_attr(attr);
|
||||
char val_str[20];
|
||||
size_t len;
|
||||
int ret, i;
|
||||
|
@ -123,39 +152,52 @@ static ssize_t axp20x_store_ext_attr(struct device *dev,
|
|||
for (i = 3; i >= 0; i--) {
|
||||
unsigned int err;
|
||||
|
||||
err = abs(axp20x_ea->p_time[i].time - val);
|
||||
err = abs(time[i].time - val);
|
||||
if (err < best_err) {
|
||||
best_err = err;
|
||||
idx = axp20x_ea->p_time[i].idx;
|
||||
idx = time[i].idx;
|
||||
}
|
||||
|
||||
if (!err)
|
||||
break;
|
||||
}
|
||||
|
||||
idx <<= ffs(axp20x_ea->mask) - 1;
|
||||
ret = regmap_update_bits(axp20x_pek->axp20x->regmap,
|
||||
AXP20X_PEK_KEY,
|
||||
axp20x_ea->mask, idx);
|
||||
idx <<= ffs(mask) - 1;
|
||||
ret = regmap_update_bits(axp20x_pek->axp20x->regmap, AXP20X_PEK_KEY,
|
||||
mask, idx);
|
||||
if (ret != 0)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static struct dev_ext_attribute axp20x_dev_attr_startup = {
|
||||
.attr = __ATTR(startup, 0644, axp20x_show_ext_attr, axp20x_store_ext_attr),
|
||||
.var = &axp20x_pek_startup_ext_attr,
|
||||
};
|
||||
static ssize_t axp20x_store_attr_startup(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct axp20x_pek *axp20x_pek = dev_get_drvdata(dev);
|
||||
|
||||
static struct dev_ext_attribute axp20x_dev_attr_shutdown = {
|
||||
.attr = __ATTR(shutdown, 0644, axp20x_show_ext_attr, axp20x_store_ext_attr),
|
||||
.var = &axp20x_pek_shutdown_ext_attr,
|
||||
};
|
||||
return axp20x_store_attr(dev, axp20x_pek->info->startup_time,
|
||||
axp20x_pek->info->startup_mask, buf, count);
|
||||
}
|
||||
|
||||
static ssize_t axp20x_store_attr_shutdown(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct axp20x_pek *axp20x_pek = dev_get_drvdata(dev);
|
||||
|
||||
return axp20x_store_attr(dev, axp20x_pek->info->shutdown_time,
|
||||
axp20x_pek->info->shutdown_mask, buf, count);
|
||||
}
|
||||
|
||||
DEVICE_ATTR(startup, 0644, axp20x_show_attr_startup, axp20x_store_attr_startup);
|
||||
DEVICE_ATTR(shutdown, 0644, axp20x_show_attr_shutdown,
|
||||
axp20x_store_attr_shutdown);
|
||||
|
||||
static struct attribute *axp20x_attributes[] = {
|
||||
&axp20x_dev_attr_startup.attr.attr,
|
||||
&axp20x_dev_attr_shutdown.attr.attr,
|
||||
&dev_attr_startup.attr,
|
||||
&dev_attr_shutdown.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
@ -291,8 +333,14 @@ static bool axp20x_pek_should_register_input(struct axp20x_pek *axp20x_pek,
|
|||
static int axp20x_pek_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct axp20x_pek *axp20x_pek;
|
||||
const struct platform_device_id *match = platform_get_device_id(pdev);
|
||||
int error;
|
||||
|
||||
if (!match) {
|
||||
dev_err(&pdev->dev, "Failed to get platform_device_id\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
axp20x_pek = devm_kzalloc(&pdev->dev, sizeof(struct axp20x_pek),
|
||||
GFP_KERNEL);
|
||||
if (!axp20x_pek)
|
||||
|
@ -306,6 +354,8 @@ static int axp20x_pek_probe(struct platform_device *pdev)
|
|||
return error;
|
||||
}
|
||||
|
||||
axp20x_pek->info = (struct axp20x_info *)match->driver_data;
|
||||
|
||||
error = devm_device_add_group(&pdev->dev, &axp20x_attribute_group);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "Failed to create sysfs attributes: %d\n",
|
||||
|
@ -342,8 +392,21 @@ static const struct dev_pm_ops axp20x_pek_pm_ops = {
|
|||
#endif
|
||||
};
|
||||
|
||||
static const struct platform_device_id axp_pek_id_match[] = {
|
||||
{
|
||||
.name = "axp20x-pek",
|
||||
.driver_data = (kernel_ulong_t)&axp20x_info,
|
||||
},
|
||||
{
|
||||
.name = "axp221-pek",
|
||||
.driver_data = (kernel_ulong_t)&axp221_info,
|
||||
},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static struct platform_driver axp20x_pek_driver = {
|
||||
.probe = axp20x_pek_probe,
|
||||
.id_table = axp_pek_id_match,
|
||||
.driver = {
|
||||
.name = "axp20x-pek",
|
||||
.pm = &axp20x_pek_pm_ops,
|
||||
|
|
|
@ -1261,7 +1261,7 @@ static umode_t ims_pcu_is_attr_visible(struct kobject *kobj,
|
|||
return mode;
|
||||
}
|
||||
|
||||
static struct attribute_group ims_pcu_attr_group = {
|
||||
static const struct attribute_group ims_pcu_attr_group = {
|
||||
.is_visible = ims_pcu_is_attr_visible,
|
||||
.attrs = ims_pcu_attrs,
|
||||
};
|
||||
|
@ -1480,7 +1480,7 @@ static struct attribute *ims_pcu_ofn_attrs[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group ims_pcu_ofn_attr_group = {
|
||||
static const struct attribute_group ims_pcu_ofn_attr_group = {
|
||||
.name = "ofn",
|
||||
.attrs = ims_pcu_ofn_attrs,
|
||||
};
|
||||
|
|
|
@ -85,7 +85,7 @@ static const unsigned short keyspan_key_table[] = {
|
|||
};
|
||||
|
||||
/* table of devices that work with this driver */
|
||||
static struct usb_device_id keyspan_table[] = {
|
||||
static const struct usb_device_id keyspan_table[] = {
|
||||
{ USB_DEVICE(USB_KEYSPAN_VENDOR_ID, USB_KEYSPAN_PRODUCT_UIA11) },
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
|
|
@ -18,25 +18,30 @@
|
|||
#include <linux/input.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/timex.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
|
||||
MODULE_DESCRIPTION("PC Speaker beeper driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:pcspkr");
|
||||
|
||||
static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
|
||||
static int pcspkr_event(struct input_dev *dev, unsigned int type,
|
||||
unsigned int code, int value)
|
||||
{
|
||||
unsigned int count = 0;
|
||||
unsigned long flags;
|
||||
|
||||
if (type != EV_SND)
|
||||
return -1;
|
||||
return -EINVAL;
|
||||
|
||||
switch (code) {
|
||||
case SND_BELL: if (value) value = 1000;
|
||||
case SND_TONE: break;
|
||||
default: return -1;
|
||||
case SND_BELL:
|
||||
if (value)
|
||||
value = 1000;
|
||||
case SND_TONE:
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (value > 20 && value < 32767)
|
||||
|
|
|
@ -432,7 +432,7 @@ static void powermate_disconnect(struct usb_interface *intf)
|
|||
}
|
||||
}
|
||||
|
||||
static struct usb_device_id powermate_devices [] = {
|
||||
static const struct usb_device_id powermate_devices[] = {
|
||||
{ USB_DEVICE(POWERMATE_VENDOR, POWERMATE_PRODUCT_NEW) },
|
||||
{ USB_DEVICE(POWERMATE_VENDOR, POWERMATE_PRODUCT_OLD) },
|
||||
{ USB_DEVICE(CONTOUR_VENDOR, CONTOUR_JOG) },
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Rockchip RK805 PMIC Power Key driver
|
||||
*
|
||||
* Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd
|
||||
*
|
||||
* Author: Joseph Chen <chenjh@rock-chips.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
static irqreturn_t pwrkey_fall_irq(int irq, void *_pwr)
|
||||
{
|
||||
struct input_dev *pwr = _pwr;
|
||||
|
||||
input_report_key(pwr, KEY_POWER, 1);
|
||||
input_sync(pwr);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t pwrkey_rise_irq(int irq, void *_pwr)
|
||||
{
|
||||
struct input_dev *pwr = _pwr;
|
||||
|
||||
input_report_key(pwr, KEY_POWER, 0);
|
||||
input_sync(pwr);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int rk805_pwrkey_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct input_dev *pwr;
|
||||
int fall_irq, rise_irq;
|
||||
int err;
|
||||
|
||||
pwr = devm_input_allocate_device(&pdev->dev);
|
||||
if (!pwr) {
|
||||
dev_err(&pdev->dev, "Can't allocate power button\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pwr->name = "rk805 pwrkey";
|
||||
pwr->phys = "rk805_pwrkey/input0";
|
||||
pwr->id.bustype = BUS_HOST;
|
||||
input_set_capability(pwr, EV_KEY, KEY_POWER);
|
||||
|
||||
fall_irq = platform_get_irq(pdev, 0);
|
||||
if (fall_irq < 0) {
|
||||
dev_err(&pdev->dev, "Can't get fall irq: %d\n", fall_irq);
|
||||
return fall_irq;
|
||||
}
|
||||
|
||||
rise_irq = platform_get_irq(pdev, 1);
|
||||
if (rise_irq < 0) {
|
||||
dev_err(&pdev->dev, "Can't get rise irq: %d\n", rise_irq);
|
||||
return rise_irq;
|
||||
}
|
||||
|
||||
err = devm_request_any_context_irq(&pwr->dev, fall_irq,
|
||||
pwrkey_fall_irq,
|
||||
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
||||
"rk805_pwrkey_fall", pwr);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev, "Can't register fall irq: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = devm_request_any_context_irq(&pwr->dev, rise_irq,
|
||||
pwrkey_rise_irq,
|
||||
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
|
||||
"rk805_pwrkey_rise", pwr);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev, "Can't register rise irq: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = input_register_device(pwr);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Can't register power button: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, pwr);
|
||||
device_init_wakeup(&pdev->dev, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver rk805_pwrkey_driver = {
|
||||
.probe = rk805_pwrkey_probe,
|
||||
.driver = {
|
||||
.name = "rk805-pwrkey",
|
||||
},
|
||||
};
|
||||
module_platform_driver(rk805_pwrkey_driver);
|
||||
|
||||
MODULE_AUTHOR("Joseph Chen <chenjh@rock-chips.com>");
|
||||
MODULE_DESCRIPTION("RK805 PMIC Power Key driver");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -84,17 +84,20 @@ static void xenkbd_handle_key_event(struct xenkbd_info *info,
|
|||
struct xenkbd_key *key)
|
||||
{
|
||||
struct input_dev *dev;
|
||||
int value = key->pressed;
|
||||
|
||||
if (test_bit(key->keycode, info->ptr->keybit)) {
|
||||
dev = info->ptr;
|
||||
} else if (test_bit(key->keycode, info->kbd->keybit)) {
|
||||
dev = info->kbd;
|
||||
if (key->pressed && test_bit(key->keycode, info->kbd->key))
|
||||
value = 2; /* Mark as autorepeat */
|
||||
} else {
|
||||
pr_warn("unhandled keycode 0x%x\n", key->keycode);
|
||||
return;
|
||||
}
|
||||
|
||||
input_report_key(dev, key->keycode, key->pressed);
|
||||
input_event(dev, EV_KEY, key->keycode, value);
|
||||
input_sync(dev);
|
||||
}
|
||||
|
||||
|
|
|
@ -798,7 +798,7 @@ static struct attribute *yld_attributes[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group yld_attr_group = {
|
||||
static const struct attribute_group yld_attr_group = {
|
||||
.attrs = yld_attributes
|
||||
};
|
||||
|
||||
|
|
|
@ -125,7 +125,7 @@ static const struct atp_info geyser4_info = {
|
|||
* According to Info.plist Geyser IV is the same as Geyser III.)
|
||||
*/
|
||||
|
||||
static struct usb_device_id atp_table[] = {
|
||||
static const struct usb_device_id atp_table[] = {
|
||||
/* PowerBooks Feb 2005, iBooks G4 */
|
||||
ATP_DEVICE(0x020e, fountain_info), /* FOUNTAIN ANSI */
|
||||
ATP_DEVICE(0x020f, fountain_info), /* FOUNTAIN ISO */
|
||||
|
|
|
@ -344,7 +344,7 @@ static int byd_reset_touchpad(struct psmouse *psmouse)
|
|||
u8 param[4];
|
||||
size_t i;
|
||||
|
||||
const struct {
|
||||
static const struct {
|
||||
u16 command;
|
||||
u8 arg;
|
||||
} seq[] = {
|
||||
|
|
|
@ -58,7 +58,7 @@ struct elan_transport_ops {
|
|||
|
||||
int (*get_version)(struct i2c_client *client, bool iap, u8 *version);
|
||||
int (*get_sm_version)(struct i2c_client *client,
|
||||
u16 *ic_type, u8 *version);
|
||||
u16 *ic_type, u8 *version, u8 *clickpad);
|
||||
int (*get_checksum)(struct i2c_client *client, bool iap, u16 *csum);
|
||||
int (*get_product_id)(struct i2c_client *client, u16 *id);
|
||||
|
||||
|
|
|
@ -95,6 +95,7 @@ struct elan_tp_data {
|
|||
u8 min_baseline;
|
||||
u8 max_baseline;
|
||||
bool baseline_ready;
|
||||
u8 clickpad;
|
||||
};
|
||||
|
||||
static int elan_get_fwinfo(u16 ic_type, u16 *validpage_count,
|
||||
|
@ -213,7 +214,7 @@ static int elan_query_product(struct elan_tp_data *data)
|
|||
return error;
|
||||
|
||||
error = data->ops->get_sm_version(data->client, &data->ic_type,
|
||||
&data->sm_version);
|
||||
&data->sm_version, &data->clickpad);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
|
@ -923,6 +924,7 @@ static void elan_report_absolute(struct elan_tp_data *data, u8 *packet)
|
|||
}
|
||||
|
||||
input_report_key(input, BTN_LEFT, tp_info & 0x01);
|
||||
input_report_key(input, BTN_RIGHT, tp_info & 0x02);
|
||||
input_report_abs(input, ABS_DISTANCE, hover_event != 0);
|
||||
input_mt_report_pointer_emulation(input, true);
|
||||
input_sync(input);
|
||||
|
@ -991,7 +993,10 @@ static int elan_setup_input_device(struct elan_tp_data *data)
|
|||
|
||||
__set_bit(EV_ABS, input->evbit);
|
||||
__set_bit(INPUT_PROP_POINTER, input->propbit);
|
||||
__set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
|
||||
if (data->clickpad)
|
||||
__set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
|
||||
else
|
||||
__set_bit(BTN_RIGHT, input->keybit);
|
||||
__set_bit(BTN_LEFT, input->keybit);
|
||||
|
||||
/* Set up ST parameters */
|
||||
|
|
|
@ -288,7 +288,8 @@ static int elan_i2c_get_version(struct i2c_client *client,
|
|||
}
|
||||
|
||||
static int elan_i2c_get_sm_version(struct i2c_client *client,
|
||||
u16 *ic_type, u8 *version)
|
||||
u16 *ic_type, u8 *version,
|
||||
u8 *clickpad)
|
||||
{
|
||||
int error;
|
||||
u8 pattern_ver;
|
||||
|
@ -317,6 +318,7 @@ static int elan_i2c_get_sm_version(struct i2c_client *client,
|
|||
return error;
|
||||
}
|
||||
*version = val[1];
|
||||
*clickpad = val[0] & 0x10;
|
||||
} else {
|
||||
error = elan_i2c_read_cmd(client, ETP_I2C_OSM_VERSION_CMD, val);
|
||||
if (error) {
|
||||
|
@ -326,6 +328,15 @@ static int elan_i2c_get_sm_version(struct i2c_client *client,
|
|||
}
|
||||
*version = val[0];
|
||||
*ic_type = val[1];
|
||||
|
||||
error = elan_i2c_read_cmd(client, ETP_I2C_NSM_VERSION_CMD,
|
||||
val);
|
||||
if (error) {
|
||||
dev_err(&client->dev, "failed to get SM version: %d\n",
|
||||
error);
|
||||
return error;
|
||||
}
|
||||
*clickpad = val[0] & 0x10;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -166,7 +166,8 @@ static int elan_smbus_get_version(struct i2c_client *client,
|
|||
}
|
||||
|
||||
static int elan_smbus_get_sm_version(struct i2c_client *client,
|
||||
u16 *ic_type, u8 *version)
|
||||
u16 *ic_type, u8 *version,
|
||||
u8 *clickpad)
|
||||
{
|
||||
int error;
|
||||
u8 val[3];
|
||||
|
@ -180,6 +181,7 @@ static int elan_smbus_get_sm_version(struct i2c_client *client,
|
|||
|
||||
*version = val[0];
|
||||
*ic_type = val[1];
|
||||
*clickpad = val[0] & 0x10;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1377,7 +1377,7 @@ static struct attribute *elantech_attrs[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group elantech_attr_group = {
|
||||
static const struct attribute_group elantech_attr_group = {
|
||||
.attrs = elantech_attrs,
|
||||
};
|
||||
|
||||
|
|
|
@ -101,7 +101,7 @@ static struct attribute *psmouse_attributes[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group psmouse_attribute_group = {
|
||||
static const struct attribute_group psmouse_attribute_group = {
|
||||
.attrs = psmouse_attributes,
|
||||
};
|
||||
|
||||
|
|
|
@ -525,7 +525,7 @@ static int synusb_reset_resume(struct usb_interface *intf)
|
|||
return synusb_resume(intf);
|
||||
}
|
||||
|
||||
static struct usb_device_id synusb_idtable[] = {
|
||||
static const struct usb_device_id synusb_idtable[] = {
|
||||
{ USB_DEVICE_SYNAPTICS(TP, SYNUSB_TOUCHPAD) },
|
||||
{ USB_DEVICE_SYNAPTICS(INT_TP, SYNUSB_TOUCHPAD) },
|
||||
{ USB_DEVICE_SYNAPTICS(CPAD,
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#define MOUSEDEV_MINORS 31
|
||||
#define MOUSEDEV_MIX 63
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/poll.h>
|
||||
|
@ -103,7 +104,7 @@ struct mousedev_client {
|
|||
spinlock_t packet_lock;
|
||||
int pos_x, pos_y;
|
||||
|
||||
signed char ps2[6];
|
||||
u8 ps2[6];
|
||||
unsigned char ready, buffer, bufsiz;
|
||||
unsigned char imexseq, impsseq;
|
||||
enum mousedev_emul mode;
|
||||
|
@ -291,11 +292,10 @@ static void mousedev_notify_readers(struct mousedev *mousedev,
|
|||
}
|
||||
|
||||
client->pos_x += packet->dx;
|
||||
client->pos_x = client->pos_x < 0 ?
|
||||
0 : (client->pos_x >= xres ? xres : client->pos_x);
|
||||
client->pos_x = clamp_val(client->pos_x, 0, xres);
|
||||
|
||||
client->pos_y += packet->dy;
|
||||
client->pos_y = client->pos_y < 0 ?
|
||||
0 : (client->pos_y >= yres ? yres : client->pos_y);
|
||||
client->pos_y = clamp_val(client->pos_y, 0, yres);
|
||||
|
||||
p->dx += packet->dx;
|
||||
p->dy += packet->dy;
|
||||
|
@ -571,44 +571,50 @@ static int mousedev_open(struct inode *inode, struct file *file)
|
|||
return error;
|
||||
}
|
||||
|
||||
static inline int mousedev_limit_delta(int delta, int limit)
|
||||
{
|
||||
return delta > limit ? limit : (delta < -limit ? -limit : delta);
|
||||
}
|
||||
|
||||
static void mousedev_packet(struct mousedev_client *client,
|
||||
signed char *ps2_data)
|
||||
static void mousedev_packet(struct mousedev_client *client, u8 *ps2_data)
|
||||
{
|
||||
struct mousedev_motion *p = &client->packets[client->tail];
|
||||
s8 dx, dy, dz;
|
||||
|
||||
ps2_data[0] = 0x08 |
|
||||
((p->dx < 0) << 4) | ((p->dy < 0) << 5) | (p->buttons & 0x07);
|
||||
ps2_data[1] = mousedev_limit_delta(p->dx, 127);
|
||||
ps2_data[2] = mousedev_limit_delta(p->dy, 127);
|
||||
p->dx -= ps2_data[1];
|
||||
p->dy -= ps2_data[2];
|
||||
dx = clamp_val(p->dx, -127, 127);
|
||||
p->dx -= dx;
|
||||
|
||||
dy = clamp_val(p->dy, -127, 127);
|
||||
p->dy -= dy;
|
||||
|
||||
ps2_data[0] = BIT(3);
|
||||
ps2_data[0] |= ((dx & BIT(7)) >> 3) | ((dy & BIT(7)) >> 2);
|
||||
ps2_data[0] |= p->buttons & 0x07;
|
||||
ps2_data[1] = dx;
|
||||
ps2_data[2] = dy;
|
||||
|
||||
switch (client->mode) {
|
||||
case MOUSEDEV_EMUL_EXPS:
|
||||
ps2_data[3] = mousedev_limit_delta(p->dz, 7);
|
||||
p->dz -= ps2_data[3];
|
||||
ps2_data[3] = (ps2_data[3] & 0x0f) | ((p->buttons & 0x18) << 1);
|
||||
dz = clamp_val(p->dz, -7, 7);
|
||||
p->dz -= dz;
|
||||
|
||||
ps2_data[3] = (dz & 0x0f) | ((p->buttons & 0x18) << 1);
|
||||
client->bufsiz = 4;
|
||||
break;
|
||||
|
||||
case MOUSEDEV_EMUL_IMPS:
|
||||
ps2_data[0] |=
|
||||
((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1);
|
||||
ps2_data[3] = mousedev_limit_delta(p->dz, 127);
|
||||
p->dz -= ps2_data[3];
|
||||
dz = clamp_val(p->dz, -127, 127);
|
||||
p->dz -= dz;
|
||||
|
||||
ps2_data[0] |= ((p->buttons & 0x10) >> 3) |
|
||||
((p->buttons & 0x08) >> 1);
|
||||
ps2_data[3] = dz;
|
||||
|
||||
client->bufsiz = 4;
|
||||
break;
|
||||
|
||||
case MOUSEDEV_EMUL_PS2:
|
||||
default:
|
||||
ps2_data[0] |=
|
||||
((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1);
|
||||
p->dz = 0;
|
||||
|
||||
ps2_data[0] |= ((p->buttons & 0x10) >> 3) |
|
||||
((p->buttons & 0x08) >> 1);
|
||||
|
||||
client->bufsiz = 3;
|
||||
break;
|
||||
}
|
||||
|
@ -714,7 +720,7 @@ static ssize_t mousedev_read(struct file *file, char __user *buffer,
|
|||
{
|
||||
struct mousedev_client *client = file->private_data;
|
||||
struct mousedev *mousedev = client->mousedev;
|
||||
signed char data[sizeof(client->ps2)];
|
||||
u8 data[sizeof(client->ps2)];
|
||||
int retval = 0;
|
||||
|
||||
if (!client->ready && !client->buffer && mousedev->exist &&
|
||||
|
|
|
@ -334,7 +334,7 @@ static struct attribute *rmi_f01_attrs[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group rmi_f01_attr_group = {
|
||||
static const struct attribute_group rmi_f01_attr_group = {
|
||||
.attrs = rmi_f01_attrs,
|
||||
};
|
||||
|
||||
|
|
|
@ -516,7 +516,7 @@ static struct attribute *rmi_firmware_attrs[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group rmi_firmware_attr_group = {
|
||||
static const struct attribute_group rmi_firmware_attr_group = {
|
||||
.attrs = rmi_firmware_attrs,
|
||||
};
|
||||
|
||||
|
|
|
@ -292,6 +292,17 @@ config SERIO_SUN4I_PS2
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called sun4i-ps2.
|
||||
|
||||
config SERIO_GPIO_PS2
|
||||
tristate "GPIO PS/2 bit banging driver"
|
||||
depends on GPIOLIB
|
||||
help
|
||||
Say Y here if you want PS/2 bit banging support via GPIO.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ps2-gpio.
|
||||
|
||||
If you are unsure, say N.
|
||||
|
||||
config USERIO
|
||||
tristate "User space serio port driver support"
|
||||
help
|
||||
|
|
|
@ -30,4 +30,5 @@ obj-$(CONFIG_SERIO_APBPS2) += apbps2.o
|
|||
obj-$(CONFIG_SERIO_OLPC_APSP) += olpc_apsp.o
|
||||
obj-$(CONFIG_HYPERV_KEYBOARD) += hyperv-keyboard.o
|
||||
obj-$(CONFIG_SERIO_SUN4I_PS2) += sun4i-ps2.o
|
||||
obj-$(CONFIG_SERIO_GPIO_PS2) += ps2-gpio.o
|
||||
obj-$(CONFIG_USERIO) += userio.o
|
||||
|
|
|
@ -187,7 +187,7 @@ static int __maybe_unused amba_kmi_resume(struct device *dev)
|
|||
|
||||
static SIMPLE_DEV_PM_OPS(amba_kmi_dev_pm_ops, NULL, amba_kmi_resume);
|
||||
|
||||
static struct amba_id amba_kmi_idtable[] = {
|
||||
static const struct amba_id amba_kmi_idtable[] = {
|
||||
{
|
||||
.id = 0x00041050,
|
||||
.mask = 0x000fffff,
|
||||
|
|
|
@ -927,7 +927,7 @@ static int i8042_pnp_aux_probe(struct pnp_dev *dev, const struct pnp_device_id *
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct pnp_device_id pnp_kbd_devids[] = {
|
||||
static const struct pnp_device_id pnp_kbd_devids[] = {
|
||||
{ .id = "PNP0300", .driver_data = 0 },
|
||||
{ .id = "PNP0301", .driver_data = 0 },
|
||||
{ .id = "PNP0302", .driver_data = 0 },
|
||||
|
@ -957,7 +957,7 @@ static struct pnp_driver i8042_pnp_kbd_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct pnp_device_id pnp_aux_devids[] = {
|
||||
static const struct pnp_device_id pnp_aux_devids[] = {
|
||||
{ .id = "AUI0200", .driver_data = 0 },
|
||||
{ .id = "FJC6000", .driver_data = 0 },
|
||||
{ .id = "FJC6001", .driver_data = 0 },
|
||||
|
|
|
@ -0,0 +1,453 @@
|
|||
/*
|
||||
* GPIO based serio bus driver for bit banging the PS/2 protocol
|
||||
*
|
||||
* Author: Danilo Krummrich <danilokrummrich@dk-develop.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/serio.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/preempt.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#define DRIVER_NAME "ps2-gpio"
|
||||
|
||||
#define PS2_MODE_RX 0
|
||||
#define PS2_MODE_TX 1
|
||||
|
||||
#define PS2_START_BIT 0
|
||||
#define PS2_DATA_BIT0 1
|
||||
#define PS2_DATA_BIT1 2
|
||||
#define PS2_DATA_BIT2 3
|
||||
#define PS2_DATA_BIT3 4
|
||||
#define PS2_DATA_BIT4 5
|
||||
#define PS2_DATA_BIT5 6
|
||||
#define PS2_DATA_BIT6 7
|
||||
#define PS2_DATA_BIT7 8
|
||||
#define PS2_PARITY_BIT 9
|
||||
#define PS2_STOP_BIT 10
|
||||
#define PS2_TX_TIMEOUT 11
|
||||
#define PS2_ACK_BIT 12
|
||||
|
||||
#define PS2_DEV_RET_ACK 0xfa
|
||||
#define PS2_DEV_RET_NACK 0xfe
|
||||
|
||||
#define PS2_CMD_RESEND 0xfe
|
||||
|
||||
struct ps2_gpio_data {
|
||||
struct device *dev;
|
||||
struct serio *serio;
|
||||
unsigned char mode;
|
||||
struct gpio_desc *gpio_clk;
|
||||
struct gpio_desc *gpio_data;
|
||||
bool write_enable;
|
||||
int irq;
|
||||
unsigned char rx_cnt;
|
||||
unsigned char rx_byte;
|
||||
unsigned char tx_cnt;
|
||||
unsigned char tx_byte;
|
||||
struct completion tx_done;
|
||||
struct mutex tx_mutex;
|
||||
struct delayed_work tx_work;
|
||||
};
|
||||
|
||||
static int ps2_gpio_open(struct serio *serio)
|
||||
{
|
||||
struct ps2_gpio_data *drvdata = serio->port_data;
|
||||
|
||||
enable_irq(drvdata->irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ps2_gpio_close(struct serio *serio)
|
||||
{
|
||||
struct ps2_gpio_data *drvdata = serio->port_data;
|
||||
|
||||
disable_irq(drvdata->irq);
|
||||
}
|
||||
|
||||
static int __ps2_gpio_write(struct serio *serio, unsigned char val)
|
||||
{
|
||||
struct ps2_gpio_data *drvdata = serio->port_data;
|
||||
|
||||
disable_irq_nosync(drvdata->irq);
|
||||
gpiod_direction_output(drvdata->gpio_clk, 0);
|
||||
|
||||
drvdata->mode = PS2_MODE_TX;
|
||||
drvdata->tx_byte = val;
|
||||
|
||||
schedule_delayed_work(&drvdata->tx_work, usecs_to_jiffies(200));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ps2_gpio_write(struct serio *serio, unsigned char val)
|
||||
{
|
||||
struct ps2_gpio_data *drvdata = serio->port_data;
|
||||
int ret = 0;
|
||||
|
||||
if (in_task()) {
|
||||
mutex_lock(&drvdata->tx_mutex);
|
||||
__ps2_gpio_write(serio, val);
|
||||
if (!wait_for_completion_timeout(&drvdata->tx_done,
|
||||
msecs_to_jiffies(10000)))
|
||||
ret = SERIO_TIMEOUT;
|
||||
mutex_unlock(&drvdata->tx_mutex);
|
||||
} else {
|
||||
__ps2_gpio_write(serio, val);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ps2_gpio_tx_work_fn(struct work_struct *work)
|
||||
{
|
||||
struct delayed_work *dwork = to_delayed_work(work);
|
||||
struct ps2_gpio_data *drvdata = container_of(dwork,
|
||||
struct ps2_gpio_data,
|
||||
tx_work);
|
||||
|
||||
enable_irq(drvdata->irq);
|
||||
gpiod_direction_output(drvdata->gpio_data, 0);
|
||||
gpiod_direction_input(drvdata->gpio_clk);
|
||||
}
|
||||
|
||||
static irqreturn_t ps2_gpio_irq_rx(struct ps2_gpio_data *drvdata)
|
||||
{
|
||||
unsigned char byte, cnt;
|
||||
int data;
|
||||
int rxflags = 0;
|
||||
static unsigned long old_jiffies;
|
||||
|
||||
byte = drvdata->rx_byte;
|
||||
cnt = drvdata->rx_cnt;
|
||||
|
||||
if (old_jiffies == 0)
|
||||
old_jiffies = jiffies;
|
||||
|
||||
if ((jiffies - old_jiffies) > usecs_to_jiffies(100)) {
|
||||
dev_err(drvdata->dev,
|
||||
"RX: timeout, probably we missed an interrupt\n");
|
||||
goto err;
|
||||
}
|
||||
old_jiffies = jiffies;
|
||||
|
||||
data = gpiod_get_value(drvdata->gpio_data);
|
||||
if (unlikely(data < 0)) {
|
||||
dev_err(drvdata->dev, "RX: failed to get data gpio val: %d\n",
|
||||
data);
|
||||
goto err;
|
||||
}
|
||||
|
||||
switch (cnt) {
|
||||
case PS2_START_BIT:
|
||||
/* start bit should be low */
|
||||
if (unlikely(data)) {
|
||||
dev_err(drvdata->dev, "RX: start bit should be low\n");
|
||||
goto err;
|
||||
}
|
||||
break;
|
||||
case PS2_DATA_BIT0:
|
||||
case PS2_DATA_BIT1:
|
||||
case PS2_DATA_BIT2:
|
||||
case PS2_DATA_BIT3:
|
||||
case PS2_DATA_BIT4:
|
||||
case PS2_DATA_BIT5:
|
||||
case PS2_DATA_BIT6:
|
||||
case PS2_DATA_BIT7:
|
||||
/* processing data bits */
|
||||
if (data)
|
||||
byte |= (data << (cnt - 1));
|
||||
break;
|
||||
case PS2_PARITY_BIT:
|
||||
/* check odd parity */
|
||||
if (!((hweight8(byte) & 1) ^ data)) {
|
||||
rxflags |= SERIO_PARITY;
|
||||
dev_warn(drvdata->dev, "RX: parity error\n");
|
||||
if (!drvdata->write_enable)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Do not send spurious ACK's and NACK's when write fn is
|
||||
* not provided.
|
||||
*/
|
||||
if (!drvdata->write_enable) {
|
||||
if (byte == PS2_DEV_RET_NACK)
|
||||
goto err;
|
||||
else if (byte == PS2_DEV_RET_ACK)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Let's send the data without waiting for the stop bit to be
|
||||
* sent. It may happen that we miss the stop bit. When this
|
||||
* happens we have no way to recover from this, certainly
|
||||
* missing the parity bit would be recognized when processing
|
||||
* the stop bit. When missing both, data is lost.
|
||||
*/
|
||||
serio_interrupt(drvdata->serio, byte, rxflags);
|
||||
dev_dbg(drvdata->dev, "RX: sending byte 0x%x\n", byte);
|
||||
break;
|
||||
case PS2_STOP_BIT:
|
||||
/* stop bit should be high */
|
||||
if (unlikely(!data)) {
|
||||
dev_err(drvdata->dev, "RX: stop bit should be high\n");
|
||||
goto err;
|
||||
}
|
||||
cnt = byte = 0;
|
||||
old_jiffies = 0;
|
||||
goto end; /* success */
|
||||
default:
|
||||
dev_err(drvdata->dev, "RX: got out of sync with the device\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
cnt++;
|
||||
goto end; /* success */
|
||||
|
||||
err:
|
||||
cnt = byte = 0;
|
||||
old_jiffies = 0;
|
||||
__ps2_gpio_write(drvdata->serio, PS2_CMD_RESEND);
|
||||
end:
|
||||
drvdata->rx_cnt = cnt;
|
||||
drvdata->rx_byte = byte;
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t ps2_gpio_irq_tx(struct ps2_gpio_data *drvdata)
|
||||
{
|
||||
unsigned char byte, cnt;
|
||||
int data;
|
||||
static unsigned long old_jiffies;
|
||||
|
||||
cnt = drvdata->tx_cnt;
|
||||
byte = drvdata->tx_byte;
|
||||
|
||||
if (old_jiffies == 0)
|
||||
old_jiffies = jiffies;
|
||||
|
||||
if ((jiffies - old_jiffies) > usecs_to_jiffies(100)) {
|
||||
dev_err(drvdata->dev,
|
||||
"TX: timeout, probably we missed an interrupt\n");
|
||||
goto err;
|
||||
}
|
||||
old_jiffies = jiffies;
|
||||
|
||||
switch (cnt) {
|
||||
case PS2_START_BIT:
|
||||
/* should never happen */
|
||||
dev_err(drvdata->dev,
|
||||
"TX: start bit should have been sent already\n");
|
||||
goto err;
|
||||
case PS2_DATA_BIT0:
|
||||
case PS2_DATA_BIT1:
|
||||
case PS2_DATA_BIT2:
|
||||
case PS2_DATA_BIT3:
|
||||
case PS2_DATA_BIT4:
|
||||
case PS2_DATA_BIT5:
|
||||
case PS2_DATA_BIT6:
|
||||
case PS2_DATA_BIT7:
|
||||
data = byte & BIT(cnt - 1);
|
||||
gpiod_set_value(drvdata->gpio_data, data);
|
||||
break;
|
||||
case PS2_PARITY_BIT:
|
||||
/* do odd parity */
|
||||
data = !(hweight8(byte) & 1);
|
||||
gpiod_set_value(drvdata->gpio_data, data);
|
||||
break;
|
||||
case PS2_STOP_BIT:
|
||||
/* release data line to generate stop bit */
|
||||
gpiod_direction_input(drvdata->gpio_data);
|
||||
break;
|
||||
case PS2_TX_TIMEOUT:
|
||||
/* Devices generate one extra clock pulse before sending the
|
||||
* acknowledgment.
|
||||
*/
|
||||
break;
|
||||
case PS2_ACK_BIT:
|
||||
gpiod_direction_input(drvdata->gpio_data);
|
||||
data = gpiod_get_value(drvdata->gpio_data);
|
||||
if (data) {
|
||||
dev_warn(drvdata->dev, "TX: received NACK, retry\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
drvdata->mode = PS2_MODE_RX;
|
||||
complete(&drvdata->tx_done);
|
||||
|
||||
cnt = 1;
|
||||
old_jiffies = 0;
|
||||
goto end; /* success */
|
||||
default:
|
||||
/* Probably we missed the stop bit. Therefore we release data
|
||||
* line and try again.
|
||||
*/
|
||||
gpiod_direction_input(drvdata->gpio_data);
|
||||
dev_err(drvdata->dev, "TX: got out of sync with the device\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
cnt++;
|
||||
goto end; /* success */
|
||||
|
||||
err:
|
||||
cnt = 1;
|
||||
old_jiffies = 0;
|
||||
gpiod_direction_input(drvdata->gpio_data);
|
||||
__ps2_gpio_write(drvdata->serio, drvdata->tx_byte);
|
||||
end:
|
||||
drvdata->tx_cnt = cnt;
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t ps2_gpio_irq(int irq, void *dev_id)
|
||||
{
|
||||
struct ps2_gpio_data *drvdata = dev_id;
|
||||
|
||||
return drvdata->mode ? ps2_gpio_irq_tx(drvdata) :
|
||||
ps2_gpio_irq_rx(drvdata);
|
||||
}
|
||||
|
||||
static int ps2_gpio_get_props(struct device *dev,
|
||||
struct ps2_gpio_data *drvdata)
|
||||
{
|
||||
drvdata->gpio_data = devm_gpiod_get(dev, "data", GPIOD_IN);
|
||||
if (IS_ERR(drvdata->gpio_data)) {
|
||||
dev_err(dev, "failed to request data gpio: %ld",
|
||||
PTR_ERR(drvdata->gpio_data));
|
||||
return PTR_ERR(drvdata->gpio_data);
|
||||
}
|
||||
|
||||
drvdata->gpio_clk = devm_gpiod_get(dev, "clk", GPIOD_IN);
|
||||
if (IS_ERR(drvdata->gpio_clk)) {
|
||||
dev_err(dev, "failed to request clock gpio: %ld",
|
||||
PTR_ERR(drvdata->gpio_clk));
|
||||
return PTR_ERR(drvdata->gpio_clk);
|
||||
}
|
||||
|
||||
drvdata->write_enable = device_property_read_bool(dev,
|
||||
"write-enable");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ps2_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct ps2_gpio_data *drvdata;
|
||||
struct serio *serio;
|
||||
struct device *dev = &pdev->dev;
|
||||
int error;
|
||||
|
||||
drvdata = devm_kzalloc(dev, sizeof(struct ps2_gpio_data), GFP_KERNEL);
|
||||
serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
|
||||
if (!drvdata || !serio) {
|
||||
error = -ENOMEM;
|
||||
goto err_free_serio;
|
||||
}
|
||||
|
||||
error = ps2_gpio_get_props(dev, drvdata);
|
||||
if (error)
|
||||
goto err_free_serio;
|
||||
|
||||
if (gpiod_cansleep(drvdata->gpio_data) ||
|
||||
gpiod_cansleep(drvdata->gpio_clk)) {
|
||||
dev_err(dev, "GPIO data or clk are connected via slow bus\n");
|
||||
error = -EINVAL;
|
||||
}
|
||||
|
||||
drvdata->irq = platform_get_irq(pdev, 0);
|
||||
if (drvdata->irq < 0) {
|
||||
dev_err(dev, "failed to get irq from platform resource: %d\n",
|
||||
drvdata->irq);
|
||||
error = drvdata->irq;
|
||||
goto err_free_serio;
|
||||
}
|
||||
|
||||
error = devm_request_irq(dev, drvdata->irq, ps2_gpio_irq,
|
||||
IRQF_NO_THREAD, DRIVER_NAME, drvdata);
|
||||
if (error) {
|
||||
dev_err(dev, "failed to request irq %d: %d\n",
|
||||
drvdata->irq, error);
|
||||
goto err_free_serio;
|
||||
}
|
||||
|
||||
/* Keep irq disabled until serio->open is called. */
|
||||
disable_irq(drvdata->irq);
|
||||
|
||||
serio->id.type = SERIO_8042;
|
||||
serio->open = ps2_gpio_open;
|
||||
serio->close = ps2_gpio_close;
|
||||
/* Write can be enabled in platform/dt data, but possibly it will not
|
||||
* work because of the tough timings.
|
||||
*/
|
||||
serio->write = drvdata->write_enable ? ps2_gpio_write : NULL;
|
||||
serio->port_data = drvdata;
|
||||
serio->dev.parent = dev;
|
||||
strlcpy(serio->name, dev_name(dev), sizeof(serio->name));
|
||||
strlcpy(serio->phys, dev_name(dev), sizeof(serio->phys));
|
||||
|
||||
drvdata->serio = serio;
|
||||
drvdata->dev = dev;
|
||||
drvdata->mode = PS2_MODE_RX;
|
||||
|
||||
/* Tx count always starts at 1, as the start bit is sent implicitly by
|
||||
* host-to-device communication initialization.
|
||||
*/
|
||||
drvdata->tx_cnt = 1;
|
||||
|
||||
INIT_DELAYED_WORK(&drvdata->tx_work, ps2_gpio_tx_work_fn);
|
||||
init_completion(&drvdata->tx_done);
|
||||
mutex_init(&drvdata->tx_mutex);
|
||||
|
||||
serio_register_port(serio);
|
||||
platform_set_drvdata(pdev, drvdata);
|
||||
|
||||
return 0; /* success */
|
||||
|
||||
err_free_serio:
|
||||
kfree(serio);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int ps2_gpio_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct ps2_gpio_data *drvdata = platform_get_drvdata(pdev);
|
||||
|
||||
serio_unregister_port(drvdata->serio);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_OF)
|
||||
static const struct of_device_id ps2_gpio_match[] = {
|
||||
{ .compatible = "ps2-gpio", },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ps2_gpio_match);
|
||||
#endif
|
||||
|
||||
static struct platform_driver ps2_gpio_driver = {
|
||||
.probe = ps2_gpio_probe,
|
||||
.remove = ps2_gpio_remove,
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.of_match_table = of_match_ptr(ps2_gpio_match),
|
||||
},
|
||||
};
|
||||
module_platform_driver(ps2_gpio_driver);
|
||||
|
||||
MODULE_AUTHOR("Danilo Krummrich <danilokrummrich@dk-develop.de>");
|
||||
MODULE_DESCRIPTION("GPIO PS2 driver");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -469,7 +469,7 @@ static struct attribute *serio_device_id_attrs[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group serio_id_attr_group = {
|
||||
static const struct attribute_group serio_id_attr_group = {
|
||||
.name = "id",
|
||||
.attrs = serio_device_id_attrs,
|
||||
};
|
||||
|
@ -489,7 +489,7 @@ static struct attribute *serio_device_attrs[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group serio_device_attr_group = {
|
||||
static const struct attribute_group serio_device_attr_group = {
|
||||
.attrs = serio_device_attrs,
|
||||
};
|
||||
|
||||
|
|
|
@ -410,7 +410,7 @@ static void serio_raw_disconnect(struct serio *serio)
|
|||
serio_set_drvdata(serio, NULL);
|
||||
}
|
||||
|
||||
static struct serio_device_id serio_raw_serio_ids[] = {
|
||||
static const struct serio_device_id serio_raw_serio_ids[] = {
|
||||
{
|
||||
.type = SERIO_8042,
|
||||
.proto = SERIO_ANY,
|
||||
|
|
|
@ -45,8 +45,10 @@
|
|||
#define XPS2_STATUS_RX_FULL 0x00000001 /* Receive Full */
|
||||
#define XPS2_STATUS_TX_FULL 0x00000002 /* Transmit Full */
|
||||
|
||||
/* Bit definitions for ISR/IER registers. Both the registers have the same bit
|
||||
* definitions and are only defined once. */
|
||||
/*
|
||||
* Bit definitions for ISR/IER registers. Both the registers have the same bit
|
||||
* definitions and are only defined once.
|
||||
*/
|
||||
#define XPS2_IPIXR_WDT_TOUT 0x00000001 /* Watchdog Timeout Interrupt */
|
||||
#define XPS2_IPIXR_TX_NOACK 0x00000002 /* Transmit No ACK Interrupt */
|
||||
#define XPS2_IPIXR_TX_ACK 0x00000004 /* Transmit ACK (Data) Interrupt */
|
||||
|
@ -292,8 +294,10 @@ static int xps2_of_probe(struct platform_device *ofdev)
|
|||
/* Disable all the interrupts, just in case */
|
||||
out_be32(drvdata->base_address + XPS2_IPIER_OFFSET, 0);
|
||||
|
||||
/* Reset the PS2 device and abort any current transaction, to make sure
|
||||
* we have the PS2 in a good state */
|
||||
/*
|
||||
* Reset the PS2 device and abort any current transaction,
|
||||
* to make sure we have the PS2 in a good state.
|
||||
*/
|
||||
out_be32(drvdata->base_address + XPS2_SRST_OFFSET, XPS2_SRST_RESET);
|
||||
|
||||
dev_info(dev, "Xilinx PS2 at 0x%08llX mapped to 0x%p, irq=%d\n",
|
||||
|
|
|
@ -260,7 +260,7 @@ static void usb_acecad_disconnect(struct usb_interface *intf)
|
|||
kfree(acecad);
|
||||
}
|
||||
|
||||
static struct usb_device_id usb_acecad_id_table [] = {
|
||||
static const struct usb_device_id usb_acecad_id_table[] = {
|
||||
{ USB_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_FLAIR), .driver_info = 0 },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_302), .driver_info = 1 },
|
||||
{ }
|
||||
|
|
|
@ -1676,7 +1676,7 @@ static struct attribute *aiptek_attributes[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group aiptek_attribute_group = {
|
||||
static const struct attribute_group aiptek_attribute_group = {
|
||||
.attrs = aiptek_attributes,
|
||||
};
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ static void kbtab_irq(struct urb *urb)
|
|||
__func__, retval);
|
||||
}
|
||||
|
||||
static struct usb_device_id kbtab_ids[] = {
|
||||
static const struct usb_device_id kbtab_ids[] = {
|
||||
{ USB_DEVICE(USB_VENDOR_ID_KBGEAR, 0x1001), .driver_info = 0 },
|
||||
{ }
|
||||
};
|
||||
|
|
|
@ -594,7 +594,7 @@ static int wacom_connect(struct serio *serio, struct serio_driver *drv)
|
|||
return err;
|
||||
}
|
||||
|
||||
static struct serio_device_id wacom_serio_ids[] = {
|
||||
static const struct serio_device_id wacom_serio_ids[] = {
|
||||
{
|
||||
.type = SERIO_RS232,
|
||||
.proto = SERIO_WACOM_IV,
|
||||
|
|
|
@ -499,7 +499,7 @@ static struct attribute *ads7846_attributes[] = {
|
|||
NULL,
|
||||
};
|
||||
|
||||
static struct attribute_group ads7846_attr_group = {
|
||||
static const struct attribute_group ads7846_attr_group = {
|
||||
.attrs = ads7846_attributes,
|
||||
.is_visible = ads7846_is_visible,
|
||||
};
|
||||
|
@ -599,7 +599,7 @@ static struct attribute *ads784x_attributes[] = {
|
|||
NULL,
|
||||
};
|
||||
|
||||
static struct attribute_group ads784x_attr_group = {
|
||||
static const struct attribute_group ads784x_attr_group = {
|
||||
.attrs = ads784x_attributes,
|
||||
};
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-ioctl.h>
|
||||
|
@ -300,6 +301,7 @@ struct mxt_data {
|
|||
u8 multitouch;
|
||||
struct t7_config t7_cfg;
|
||||
struct mxt_dbg dbg;
|
||||
struct gpio_desc *reset_gpio;
|
||||
|
||||
/* Cached parameters from object table */
|
||||
u16 T5_address;
|
||||
|
@ -3117,11 +3119,9 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||
if (IS_ERR(pdata))
|
||||
return PTR_ERR(pdata);
|
||||
|
||||
data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
|
||||
if (!data) {
|
||||
dev_err(&client->dev, "Failed to allocate memory\n");
|
||||
data = devm_kzalloc(&client->dev, sizeof(struct mxt_data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
snprintf(data->phys, sizeof(data->phys), "i2c-%u-%04x/input0",
|
||||
client->adapter->nr, client->addr);
|
||||
|
@ -3135,19 +3135,40 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||
init_completion(&data->reset_completion);
|
||||
init_completion(&data->crc_completion);
|
||||
|
||||
error = request_threaded_irq(client->irq, NULL, mxt_interrupt,
|
||||
pdata->irqflags | IRQF_ONESHOT,
|
||||
client->name, data);
|
||||
data->reset_gpio = devm_gpiod_get_optional(&client->dev,
|
||||
"reset", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(data->reset_gpio)) {
|
||||
error = PTR_ERR(data->reset_gpio);
|
||||
dev_err(&client->dev, "Failed to get reset gpio: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
error = devm_request_threaded_irq(&client->dev, client->irq,
|
||||
NULL, mxt_interrupt,
|
||||
pdata->irqflags | IRQF_ONESHOT,
|
||||
client->name, data);
|
||||
if (error) {
|
||||
dev_err(&client->dev, "Failed to register interrupt\n");
|
||||
goto err_free_mem;
|
||||
return error;
|
||||
}
|
||||
|
||||
if (data->reset_gpio) {
|
||||
data->in_bootloader = true;
|
||||
msleep(MXT_RESET_TIME);
|
||||
reinit_completion(&data->bl_completion);
|
||||
gpiod_set_value(data->reset_gpio, 1);
|
||||
error = mxt_wait_for_completion(data, &data->bl_completion,
|
||||
MXT_RESET_TIMEOUT);
|
||||
if (error)
|
||||
return error;
|
||||
data->in_bootloader = false;
|
||||
}
|
||||
|
||||
disable_irq(client->irq);
|
||||
|
||||
error = mxt_initialize(data);
|
||||
if (error)
|
||||
goto err_free_irq;
|
||||
return error;
|
||||
|
||||
error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group);
|
||||
if (error) {
|
||||
|
@ -3161,10 +3182,6 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||
err_free_object:
|
||||
mxt_free_input_device(data);
|
||||
mxt_free_object_table(data);
|
||||
err_free_irq:
|
||||
free_irq(client->irq, data);
|
||||
err_free_mem:
|
||||
kfree(data);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -3172,11 +3189,10 @@ static int mxt_remove(struct i2c_client *client)
|
|||
{
|
||||
struct mxt_data *data = i2c_get_clientdata(client);
|
||||
|
||||
disable_irq(data->irq);
|
||||
sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
|
||||
free_irq(data->irq, data);
|
||||
mxt_free_input_device(data);
|
||||
mxt_free_object_table(data);
|
||||
kfree(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -164,7 +164,7 @@ static int dynapro_connect(struct serio *serio, struct serio_driver *drv)
|
|||
* The serio driver structure.
|
||||
*/
|
||||
|
||||
static struct serio_device_id dynapro_serio_ids[] = {
|
||||
static const struct serio_device_id dynapro_serio_ids[] = {
|
||||
{
|
||||
.type = SERIO_RS232,
|
||||
.proto = SERIO_DYNAPRO,
|
||||
|
|
|
@ -1066,7 +1066,7 @@ static struct attribute *elants_attributes[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group elants_attribute_group = {
|
||||
static const struct attribute_group elants_attribute_group = {
|
||||
.attrs = elants_attributes,
|
||||
};
|
||||
|
||||
|
|
|
@ -381,7 +381,7 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv)
|
|||
* The serio driver structure.
|
||||
*/
|
||||
|
||||
static struct serio_device_id elo_serio_ids[] = {
|
||||
static const struct serio_device_id elo_serio_ids[] = {
|
||||
{
|
||||
.type = SERIO_RS232,
|
||||
.proto = SERIO_ELO,
|
||||
|
|
|
@ -151,7 +151,7 @@ static int fujitsu_connect(struct serio *serio, struct serio_driver *drv)
|
|||
/*
|
||||
* The serio driver structure.
|
||||
*/
|
||||
static struct serio_device_id fujitsu_serio_ids[] = {
|
||||
static const struct serio_device_id fujitsu_serio_ids[] = {
|
||||
{
|
||||
.type = SERIO_RS232,
|
||||
.proto = SERIO_FUJITSU,
|
||||
|
|
|
@ -162,7 +162,7 @@ static int gunze_connect(struct serio *serio, struct serio_driver *drv)
|
|||
* The serio driver structure.
|
||||
*/
|
||||
|
||||
static struct serio_device_id gunze_serio_ids[] = {
|
||||
static const struct serio_device_id gunze_serio_ids[] = {
|
||||
{
|
||||
.type = SERIO_RS232,
|
||||
.proto = SERIO_GUNZE,
|
||||
|
|
|
@ -163,7 +163,7 @@ static int hampshire_connect(struct serio *serio, struct serio_driver *drv)
|
|||
* The serio driver structure.
|
||||
*/
|
||||
|
||||
static struct serio_device_id hampshire_serio_ids[] = {
|
||||
static const struct serio_device_id hampshire_serio_ids[] = {
|
||||
{
|
||||
.type = SERIO_RS232,
|
||||
.proto = SERIO_HAMPSHIRE,
|
||||
|
|
|
@ -165,7 +165,7 @@ static int inexio_connect(struct serio *serio, struct serio_driver *drv)
|
|||
* The serio driver structure.
|
||||
*/
|
||||
|
||||
static struct serio_device_id inexio_serio_ids[] = {
|
||||
static const struct serio_device_id inexio_serio_ids[] = {
|
||||
{
|
||||
.type = SERIO_RS232,
|
||||
.proto = SERIO_INEXIO,
|
||||
|
|
|
@ -178,7 +178,7 @@ static int mtouch_connect(struct serio *serio, struct serio_driver *drv)
|
|||
* The serio driver structure.
|
||||
*/
|
||||
|
||||
static struct serio_device_id mtouch_serio_ids[] = {
|
||||
static const struct serio_device_id mtouch_serio_ids[] = {
|
||||
{
|
||||
.type = SERIO_RS232,
|
||||
.proto = SERIO_MICROTOUCH,
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include <linux/of_irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
const char *mxs_lradc_ts_irq_names[] = {
|
||||
static const char * const mxs_lradc_ts_irq_names[] = {
|
||||
"mxs-lradc-touchscreen",
|
||||
"mxs-lradc-channel6",
|
||||
"mxs-lradc-channel7",
|
||||
|
@ -630,9 +630,11 @@ static int mxs_lradc_ts_probe(struct platform_device *pdev)
|
|||
spin_lock_init(&ts->lock);
|
||||
|
||||
iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!iores)
|
||||
return -EINVAL;
|
||||
ts->base = devm_ioremap(dev, iores->start, resource_size(iores));
|
||||
if (IS_ERR(ts->base))
|
||||
return PTR_ERR(ts->base);
|
||||
if (!ts->base)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = of_property_read_u32(node, "fsl,lradc-touchscreen-wires",
|
||||
&ts_wires);
|
||||
|
|
|
@ -293,7 +293,7 @@ static int pm_connect(struct serio *serio, struct serio_driver *drv)
|
|||
* The serio driver structure.
|
||||
*/
|
||||
|
||||
static struct serio_device_id pm_serio_ids[] = {
|
||||
static const struct serio_device_id pm_serio_ids[] = {
|
||||
{
|
||||
.type = SERIO_RS232,
|
||||
.proto = SERIO_PENMOUNT,
|
||||
|
|
|
@ -939,7 +939,7 @@ static struct attribute *raydium_i2c_attributes[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group raydium_i2c_attribute_group = {
|
||||
static const struct attribute_group raydium_i2c_attribute_group = {
|
||||
.attrs = raydium_i2c_attributes,
|
||||
};
|
||||
|
||||
|
|
|
@ -206,7 +206,7 @@ static int sun4i_get_tz_temp(void *data, int *temp)
|
|||
return sun4i_get_temp(data, temp);
|
||||
}
|
||||
|
||||
static struct thermal_zone_of_device_ops sun4i_ts_tz_ops = {
|
||||
static const struct thermal_zone_of_device_ops sun4i_ts_tz_ops = {
|
||||
.get_temp = sun4i_get_tz_temp,
|
||||
};
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ struct sur40_blob {
|
|||
__le16 blob_id;
|
||||
|
||||
u8 action; /* 0x02 = enter/exit, 0x03 = update (?) */
|
||||
u8 unknown; /* always 0x01 or 0x02 (no idea what this is?) */
|
||||
u8 type; /* bitmask (0x01 blob, 0x02 touch, 0x04 tag) */
|
||||
|
||||
__le16 bb_pos_x; /* upper left corner of bounding box */
|
||||
__le16 bb_pos_y;
|
||||
|
@ -133,12 +133,19 @@ struct sur40_image_header {
|
|||
|
||||
/* control commands */
|
||||
#define SUR40_GET_VERSION 0xb0 /* 12 bytes string */
|
||||
#define SUR40_UNKNOWN1 0xb3 /* 5 bytes */
|
||||
#define SUR40_UNKNOWN2 0xc1 /* 24 bytes */
|
||||
#define SUR40_ACCEL_CAPS 0xb3 /* 5 bytes */
|
||||
#define SUR40_SENSOR_CAPS 0xc1 /* 24 bytes */
|
||||
|
||||
#define SUR40_POKE 0xc5 /* poke register byte */
|
||||
#define SUR40_PEEK 0xc4 /* 48 bytes registers */
|
||||
|
||||
#define SUR40_GET_STATE 0xc5 /* 4 bytes state (?) */
|
||||
#define SUR40_GET_SENSORS 0xb1 /* 8 bytes sensors */
|
||||
|
||||
#define SUR40_BLOB 0x01
|
||||
#define SUR40_TOUCH 0x02
|
||||
#define SUR40_TAG 0x04
|
||||
|
||||
static const struct v4l2_pix_format sur40_pix_format[] = {
|
||||
{
|
||||
.pixelformat = V4L2_TCH_FMT_TU08,
|
||||
|
@ -238,11 +245,11 @@ static int sur40_init(struct sur40_state *dev)
|
|||
if (result < 0)
|
||||
goto error;
|
||||
|
||||
result = sur40_command(dev, SUR40_UNKNOWN2, 0x00, buffer, 24);
|
||||
result = sur40_command(dev, SUR40_SENSOR_CAPS, 0x00, buffer, 24);
|
||||
if (result < 0)
|
||||
goto error;
|
||||
|
||||
result = sur40_command(dev, SUR40_UNKNOWN1, 0x00, buffer, 5);
|
||||
result = sur40_command(dev, SUR40_ACCEL_CAPS, 0x00, buffer, 5);
|
||||
if (result < 0)
|
||||
goto error;
|
||||
|
||||
|
@ -289,20 +296,24 @@ static void sur40_close(struct input_polled_dev *polldev)
|
|||
static void sur40_report_blob(struct sur40_blob *blob, struct input_dev *input)
|
||||
{
|
||||
int wide, major, minor;
|
||||
int bb_size_x, bb_size_y, pos_x, pos_y, ctr_x, ctr_y, slotnum;
|
||||
|
||||
int bb_size_x = le16_to_cpu(blob->bb_size_x);
|
||||
int bb_size_y = le16_to_cpu(blob->bb_size_y);
|
||||
if (blob->type != SUR40_TOUCH)
|
||||
return;
|
||||
|
||||
int pos_x = le16_to_cpu(blob->pos_x);
|
||||
int pos_y = le16_to_cpu(blob->pos_y);
|
||||
|
||||
int ctr_x = le16_to_cpu(blob->ctr_x);
|
||||
int ctr_y = le16_to_cpu(blob->ctr_y);
|
||||
|
||||
int slotnum = input_mt_get_slot_by_key(input, blob->blob_id);
|
||||
slotnum = input_mt_get_slot_by_key(input, blob->blob_id);
|
||||
if (slotnum < 0 || slotnum >= MAX_CONTACTS)
|
||||
return;
|
||||
|
||||
bb_size_x = le16_to_cpu(blob->bb_size_x);
|
||||
bb_size_y = le16_to_cpu(blob->bb_size_y);
|
||||
|
||||
pos_x = le16_to_cpu(blob->pos_x);
|
||||
pos_y = le16_to_cpu(blob->pos_y);
|
||||
|
||||
ctr_x = le16_to_cpu(blob->ctr_x);
|
||||
ctr_y = le16_to_cpu(blob->ctr_y);
|
||||
|
||||
input_mt_slot(input, slotnum);
|
||||
input_mt_report_slot_state(input, MT_TOOL_FINGER, 1);
|
||||
wide = (bb_size_x > bb_size_y);
|
||||
|
@ -367,10 +378,13 @@ static void sur40_poll(struct input_polled_dev *polldev)
|
|||
/*
|
||||
* Sanity check. when video data is also being retrieved, the
|
||||
* packet ID will usually increase in the middle of a series
|
||||
* instead of at the end.
|
||||
*/
|
||||
* instead of at the end. However, the data is still consistent,
|
||||
* so the packet ID is probably just valid for the first packet
|
||||
* in a series.
|
||||
|
||||
if (packet_id != le32_to_cpu(header->packet_id))
|
||||
dev_dbg(sur40->dev, "packet ID mismatch\n");
|
||||
*/
|
||||
|
||||
packet_blobs = result / sizeof(struct sur40_blob);
|
||||
dev_dbg(sur40->dev, "received %d blobs\n", packet_blobs);
|
||||
|
|
|
@ -192,7 +192,7 @@ static int touchit213_connect(struct serio *serio, struct serio_driver *drv)
|
|||
* The serio driver structure.
|
||||
*/
|
||||
|
||||
static struct serio_device_id touchit213_serio_ids[] = {
|
||||
static const struct serio_device_id touchit213_serio_ids[] = {
|
||||
{
|
||||
.type = SERIO_RS232,
|
||||
.proto = SERIO_TOUCHIT213,
|
||||
|
|
|
@ -152,7 +152,7 @@ static int tr_connect(struct serio *serio, struct serio_driver *drv)
|
|||
* The serio driver structure.
|
||||
*/
|
||||
|
||||
static struct serio_device_id tr_serio_ids[] = {
|
||||
static const struct serio_device_id tr_serio_ids[] = {
|
||||
{
|
||||
.type = SERIO_RS232,
|
||||
.proto = SERIO_TOUCHRIGHT,
|
||||
|
|
|
@ -159,7 +159,7 @@ static int tw_connect(struct serio *serio, struct serio_driver *drv)
|
|||
* The serio driver structure.
|
||||
*/
|
||||
|
||||
static struct serio_device_id tw_serio_ids[] = {
|
||||
static const struct serio_device_id tw_serio_ids[] = {
|
||||
{
|
||||
.type = SERIO_RS232,
|
||||
.proto = SERIO_TOUCHWIN,
|
||||
|
|
|
@ -141,7 +141,7 @@ static void tsc_disconnect(struct serio *serio)
|
|||
serio_set_drvdata(serio, NULL);
|
||||
}
|
||||
|
||||
static struct serio_device_id tsc_serio_ids[] = {
|
||||
static const struct serio_device_id tsc_serio_ids[] = {
|
||||
{
|
||||
.type = SERIO_RS232,
|
||||
.proto = SERIO_TSC40,
|
||||
|
|
|
@ -681,7 +681,7 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv)
|
|||
return err;
|
||||
}
|
||||
|
||||
static struct serio_device_id w8001_serio_ids[] = {
|
||||
static const struct serio_device_id w8001_serio_ids[] = {
|
||||
{
|
||||
.type = SERIO_RS232,
|
||||
.proto = SERIO_W8001,
|
||||
|
|
Loading…
Reference in New Issue