diff options
Diffstat (limited to 'drivers/input/misc')
52 files changed, 1107 insertions, 519 deletions
diff --git a/drivers/input/misc/88pm860x_onkey.c b/drivers/input/misc/88pm860x_onkey.c index abd8453e521..220ce0fa15d 100644 --- a/drivers/input/misc/88pm860x_onkey.c +++ b/drivers/input/misc/88pm860x_onkey.c @@ -26,6 +26,7 @@  #include <linux/interrupt.h>  #include <linux/mfd/88pm860x.h>  #include <linux/slab.h> +#include <linux/device.h>  #define PM8607_WAKEUP		0x0b @@ -68,7 +69,8 @@ static int pm860x_onkey_probe(struct platform_device *pdev)  		return -EINVAL;  	} -	info = kzalloc(sizeof(struct pm860x_onkey_info), GFP_KERNEL); +	info = devm_kzalloc(&pdev->dev, sizeof(struct pm860x_onkey_info), +			    GFP_KERNEL);  	if (!info)  		return -ENOMEM;  	info->chip = chip; @@ -76,11 +78,10 @@ static int pm860x_onkey_probe(struct platform_device *pdev)  	info->dev = &pdev->dev;  	info->irq = irq; -	info->idev = input_allocate_device(); +	info->idev = devm_input_allocate_device(&pdev->dev);  	if (!info->idev) {  		dev_err(chip->dev, "Failed to allocate input dev\n"); -		ret = -ENOMEM; -		goto out; +		return -ENOMEM;  	}  	info->idev->name = "88pm860x_on"; @@ -93,42 +94,22 @@ static int pm860x_onkey_probe(struct platform_device *pdev)  	ret = input_register_device(info->idev);  	if (ret) {  		dev_err(chip->dev, "Can't register input device: %d\n", ret); -		goto out_reg; +		return ret;  	} -	ret = request_threaded_irq(info->irq, NULL, pm860x_onkey_handler, -				   IRQF_ONESHOT, "onkey", info); +	ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL, +					pm860x_onkey_handler, IRQF_ONESHOT, +					"onkey", info);  	if (ret < 0) {  		dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n",  			info->irq, ret); -		goto out_irq; +		return ret;  	}  	platform_set_drvdata(pdev, info);  	device_init_wakeup(&pdev->dev, 1);  	return 0; - -out_irq: -	input_unregister_device(info->idev); -	kfree(info); -	return ret; - -out_reg: -	input_free_device(info->idev); -out: -	kfree(info); -	return ret; -} - -static int pm860x_onkey_remove(struct platform_device *pdev) -{ -	struct pm860x_onkey_info *info = platform_get_drvdata(pdev); - -	free_irq(info->irq, info); -	input_unregister_device(info->idev); -	kfree(info); -	return 0;  }  #ifdef CONFIG_PM_SLEEP @@ -161,7 +142,6 @@ static struct platform_driver pm860x_onkey_driver = {  		.pm	= &pm860x_onkey_pm_ops,  	},  	.probe		= pm860x_onkey_probe, -	.remove		= pm860x_onkey_remove,  };  module_platform_driver(pm860x_onkey_driver); diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index aa51baaa9b1..2ff4425a893 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -156,7 +156,7 @@ config INPUT_MAX8925_ONKEY  config INPUT_MAX8997_HAPTIC  	tristate "MAXIM MAX8997 haptic controller support" -	depends on HAVE_PWM && MFD_MAX8997 +	depends on PWM && MFD_MAX8997  	select INPUT_FF_MEMLESS  	help  	  This option enables device driver support for the haptic controller @@ -168,7 +168,7 @@ config INPUT_MAX8997_HAPTIC  config INPUT_MC13783_PWRBUTTON  	tristate "MC13783 ON buttons" -	depends on MFD_MC13783 +	depends on MFD_MC13XXX  	help  	  Support the ON buttons of MC13783 PMIC as an input device  	  reporting power button status. @@ -222,6 +222,15 @@ config INPUT_GP2A  	  To compile this driver as a module, choose M here: the  	  module will be called gp2ap002a00f. +config INPUT_GPIO_BEEPER +	tristate "Generic GPIO Beeper support" +	depends on GPIOLIB +	help +	  Say Y here if you have a beeper connected to a GPIO pin. + +	  To compile this driver as a module, choose M here: the +	  module will be called gpio-beeper. +  config INPUT_GPIO_TILT_POLLED  	tristate "Polled GPIO tilt switch"  	depends on GPIOLIB @@ -260,7 +269,7 @@ config INPUT_COBALT_BTNS  config INPUT_WISTRON_BTNS  	tristate "x86 Wistron laptop button interface" -	depends on X86 && !X86_64 +	depends on X86_32  	select INPUT_POLLDEV  	select INPUT_SPARSEKMAP  	select NEW_LEDS @@ -461,7 +470,7 @@ config INPUT_PCF8574  config INPUT_PWM_BEEPER  	tristate "PWM beeper support" -	depends on HAVE_PWM || PWM +	depends on PWM  	help  	  Say Y here to get support for PWM based beeper devices. @@ -657,4 +666,14 @@ config INPUT_IDEAPAD_SLIDEBAR  	  To compile this driver as a module, choose M here: the  	  module will be called ideapad_slidebar. +config INPUT_SOC_BUTTON_ARRAY +	tristate "Windows-compatible SoC Button Array" +	depends on KEYBOARD_GPIO +	help +	  Say Y here if you have a SoC-based tablet that originally +	  runs Windows 8. + +	  To compile this driver as a module, choose M here: the +	  module will be called soc_button_array. +  endif diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 0ebfb6dbf0f..4955ad322a0 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_INPUT_DA9052_ONKEY)	+= da9052_onkey.o  obj-$(CONFIG_INPUT_DA9055_ONKEY)	+= da9055_onkey.o  obj-$(CONFIG_INPUT_DM355EVM)		+= dm355evm_keys.o  obj-$(CONFIG_INPUT_GP2A)		+= gp2ap002a00f.o +obj-$(CONFIG_INPUT_GPIO_BEEPER)		+= gpio-beeper.o  obj-$(CONFIG_INPUT_GPIO_TILT_POLLED)	+= gpio_tilt_polled.o  obj-$(CONFIG_HP_SDC_RTC)		+= hp_sdc_rtc.o  obj-$(CONFIG_INPUT_IMS_PCU)		+= ims-pcu.o @@ -52,6 +53,7 @@ obj-$(CONFIG_INPUT_RETU_PWRBUTTON)	+= retu-pwrbutton.o  obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER)	+= rotary_encoder.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  obj-$(CONFIG_INPUT_SPARCSPKR)		+= sparcspkr.o  obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON)	+= twl4030-pwrbutton.o  obj-$(CONFIG_INPUT_TWL4030_VIBRA)	+= twl4030-vibra.o diff --git a/drivers/input/misc/ab8500-ponkey.c b/drivers/input/misc/ab8500-ponkey.c index f2fbdd88ed2..95ef7dd6442 100644 --- a/drivers/input/misc/ab8500-ponkey.c +++ b/drivers/input/misc/ab8500-ponkey.c @@ -7,6 +7,7 @@   * AB8500 Power-On Key handler   */ +#include <linux/device.h>  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/platform_device.h> @@ -65,12 +66,14 @@ static int ab8500_ponkey_probe(struct platform_device *pdev)  		return irq_dbr;  	} -	ponkey = kzalloc(sizeof(struct ab8500_ponkey), GFP_KERNEL); -	input = input_allocate_device(); -	if (!ponkey || !input) { -		error = -ENOMEM; -		goto err_free_mem; -	} +	ponkey = devm_kzalloc(&pdev->dev, sizeof(struct ab8500_ponkey), +			      GFP_KERNEL); +	if (!ponkey) +		return -ENOMEM; + +	input = devm_input_allocate_device(&pdev->dev); +	if (!input) +		return -ENOMEM;  	ponkey->idev = input;  	ponkey->ab8500 = ab8500; @@ -82,52 +85,32 @@ static int ab8500_ponkey_probe(struct platform_device *pdev)  	input_set_capability(input, EV_KEY, KEY_POWER); -	error = request_any_context_irq(ponkey->irq_dbf, ab8500_ponkey_handler, -					0, "ab8500-ponkey-dbf", ponkey); +	error = devm_request_any_context_irq(&pdev->dev, ponkey->irq_dbf, +					     ab8500_ponkey_handler, 0, +					     "ab8500-ponkey-dbf", ponkey);  	if (error < 0) {  		dev_err(ab8500->dev, "Failed to request dbf IRQ#%d: %d\n",  			ponkey->irq_dbf, error); -		goto err_free_mem; +		return error;  	} -	error = request_any_context_irq(ponkey->irq_dbr, ab8500_ponkey_handler, -					0, "ab8500-ponkey-dbr", ponkey); +	error = devm_request_any_context_irq(&pdev->dev, ponkey->irq_dbr, +					     ab8500_ponkey_handler, 0, +					     "ab8500-ponkey-dbr", ponkey);  	if (error < 0) {  		dev_err(ab8500->dev, "Failed to request dbr IRQ#%d: %d\n",  			ponkey->irq_dbr, error); -		goto err_free_dbf_irq; +		return error;  	}  	error = input_register_device(ponkey->idev);  	if (error) {  		dev_err(ab8500->dev, "Can't register input device: %d\n", error); -		goto err_free_dbr_irq; +		return error;  	}  	platform_set_drvdata(pdev, ponkey);  	return 0; - -err_free_dbr_irq: -	free_irq(ponkey->irq_dbr, ponkey); -err_free_dbf_irq: -	free_irq(ponkey->irq_dbf, ponkey); -err_free_mem: -	input_free_device(input); -	kfree(ponkey); - -	return error; -} - -static int ab8500_ponkey_remove(struct platform_device *pdev) -{ -	struct ab8500_ponkey *ponkey = platform_get_drvdata(pdev); - -	free_irq(ponkey->irq_dbf, ponkey); -	free_irq(ponkey->irq_dbr, ponkey); -	input_unregister_device(ponkey->idev); -	kfree(ponkey); - -	return 0;  }  #ifdef CONFIG_OF @@ -144,7 +127,6 @@ static struct platform_driver ab8500_ponkey_driver = {  		.of_match_table = of_match_ptr(ab8500_ponkey_match),  	},  	.probe		= ab8500_ponkey_probe, -	.remove		= ab8500_ponkey_remove,  };  module_platform_driver(ab8500_ponkey_driver); diff --git a/drivers/input/misc/ad714x-spi.c b/drivers/input/misc/ad714x-spi.c index 61891486067..3a90b710e30 100644 --- a/drivers/input/misc/ad714x-spi.c +++ b/drivers/input/misc/ad714x-spi.c @@ -108,7 +108,6 @@ static int ad714x_spi_remove(struct spi_device *spi)  	struct ad714x_chip *chip = spi_get_drvdata(spi);  	ad714x_remove(chip); -	spi_set_drvdata(spi, NULL);  	return 0;  } diff --git a/drivers/input/misc/ad714x.c b/drivers/input/misc/ad714x.c index 2e5d5e1de64..7a61e9ee682 100644 --- a/drivers/input/misc/ad714x.c +++ b/drivers/input/misc/ad714x.c @@ -7,7 +7,6 @@   */  #include <linux/device.h> -#include <linux/init.h>  #include <linux/input.h>  #include <linux/interrupt.h>  #include <linux/slab.h> @@ -969,7 +968,7 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,  	int error;  	struct input_dev *input[MAX_DEVICE_NUM]; -	struct ad714x_platform_data *plat_data = dev->platform_data; +	struct ad714x_platform_data *plat_data = dev_get_platdata(dev);  	struct ad714x_chip *ad714x;  	void *drv_mem;  	unsigned long irqflags; @@ -986,7 +985,7 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,  		goto err_out;  	} -	if (dev->platform_data == NULL) { +	if (dev_get_platdata(dev) == NULL) {  		dev_err(dev, "platform data for ad714x doesn't exist\n");  		error = -EINVAL;  		goto err_out; diff --git a/drivers/input/misc/adxl34x.c b/drivers/input/misc/adxl34x.c index 0735de3a646..2b2d02f408b 100644 --- a/drivers/input/misc/adxl34x.c +++ b/drivers/input/misc/adxl34x.c @@ -8,7 +8,6 @@   */  #include <linux/device.h> -#include <linux/init.h>  #include <linux/delay.h>  #include <linux/input.h>  #include <linux/interrupt.h> @@ -158,7 +157,7 @@  /* ORIENT ADXL346 only */  #define ADXL346_2D_VALID		(1 << 6) -#define ADXL346_2D_ORIENT(x)		(((x) & 0x3) >> 4) +#define ADXL346_2D_ORIENT(x)		(((x) & 0x30) >> 4)  #define ADXL346_3D_VALID		(1 << 3)  #define ADXL346_3D_ORIENT(x)		((x) & 0x7)  #define ADXL346_2D_PORTRAIT_POS		0	/* +X */ @@ -714,7 +713,7 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq,  	ac->fifo_delay = fifo_delay_default; -	pdata = dev->platform_data; +	pdata = dev_get_platdata(dev);  	if (!pdata) {  		dev_dbg(dev,  			"No platform data: Using default initialization\n"); diff --git a/drivers/input/misc/arizona-haptics.c b/drivers/input/misc/arizona-haptics.c index 7a04f54ef96..ef2e281b0a4 100644 --- a/drivers/input/misc/arizona-haptics.c +++ b/drivers/input/misc/arizona-haptics.c @@ -37,7 +37,6 @@ static void arizona_haptics_work(struct work_struct *work)  						       struct arizona_haptics,  						       work);  	struct arizona *arizona = haptics->arizona; -	struct mutex *dapm_mutex = &arizona->dapm->card->dapm_mutex;  	int ret;  	if (!haptics->arizona->dapm) { @@ -67,13 +66,10 @@ static void arizona_haptics_work(struct work_struct *work)  			return;  		} -		mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); -  		ret = snd_soc_dapm_enable_pin(arizona->dapm, "HAPTICS");  		if (ret != 0) {  			dev_err(arizona->dev, "Failed to start HAPTICS: %d\n",  				ret); -			mutex_unlock(dapm_mutex);  			return;  		} @@ -81,21 +77,14 @@ static void arizona_haptics_work(struct work_struct *work)  		if (ret != 0) {  			dev_err(arizona->dev, "Failed to sync DAPM: %d\n",  				ret); -			mutex_unlock(dapm_mutex);  			return;  		} - -		mutex_unlock(dapm_mutex); -  	} else {  		/* This disable sequence will be a noop if already enabled */ -		mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); -  		ret = snd_soc_dapm_disable_pin(arizona->dapm, "HAPTICS");  		if (ret != 0) {  			dev_err(arizona->dev, "Failed to disable HAPTICS: %d\n",  				ret); -			mutex_unlock(dapm_mutex);  			return;  		} @@ -103,12 +92,9 @@ static void arizona_haptics_work(struct work_struct *work)  		if (ret != 0) {  			dev_err(arizona->dev, "Failed to sync DAPM: %d\n",  				ret); -			mutex_unlock(dapm_mutex);  			return;  		} -		mutex_unlock(dapm_mutex); -  		ret = regmap_update_bits(arizona->regmap,  					 ARIZONA_HAPTICS_CONTROL_1,  					 ARIZONA_HAP_CTRL_MASK, @@ -155,16 +141,11 @@ static int arizona_haptics_play(struct input_dev *input, void *data,  static void arizona_haptics_close(struct input_dev *input)  {  	struct arizona_haptics *haptics = input_get_drvdata(input); -	struct mutex *dapm_mutex = &haptics->arizona->dapm->card->dapm_mutex;  	cancel_work_sync(&haptics->work); -	mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); -  	if (haptics->arizona->dapm)  		snd_soc_dapm_disable_pin(haptics->arizona->dapm, "HAPTICS"); - -	mutex_unlock(dapm_mutex);  }  static int arizona_haptics_probe(struct platform_device *pdev) diff --git a/drivers/input/misc/atlas_btns.c b/drivers/input/misc/atlas_btns.c index 5d4402365a5..638165c78e7 100644 --- a/drivers/input/misc/atlas_btns.c +++ b/drivers/input/misc/atlas_btns.c @@ -25,11 +25,10 @@  #include <linux/kernel.h>  #include <linux/module.h> -#include <linux/init.h>  #include <linux/input.h>  #include <linux/types.h> +#include <linux/acpi.h>  #include <asm/uaccess.h> -#include <acpi/acpi_drivers.h>  #define ACPI_ATLAS_NAME		"Atlas ACPI"  #define ACPI_ATLAS_CLASS	"Atlas" diff --git a/drivers/input/misc/bfin_rotary.c b/drivers/input/misc/bfin_rotary.c index cd139cb17e3..e69d9bcb37e 100644 --- a/drivers/input/misc/bfin_rotary.c +++ b/drivers/input/misc/bfin_rotary.c @@ -6,7 +6,6 @@   */  #include <linux/module.h> -#include <linux/init.h>  #include <linux/interrupt.h>  #include <linux/irq.h>  #include <linux/pm.h> @@ -92,7 +91,7 @@ static irqreturn_t bfin_rotary_isr(int irq, void *dev_id)  static int bfin_rotary_probe(struct platform_device *pdev)  { -	struct bfin_rotary_platform_data *pdata = pdev->dev.platform_data; +	struct bfin_rotary_platform_data *pdata = dev_get_platdata(&pdev->dev);  	struct bfin_rot *rotary;  	struct input_dev *input;  	int error; diff --git a/drivers/input/misc/bma150.c b/drivers/input/misc/bma150.c index 865c2f9d25b..b36831c828d 100644 --- a/drivers/input/misc/bma150.c +++ b/drivers/input/misc/bma150.c @@ -70,6 +70,7 @@  #define BMA150_CFG_5_REG	0x11  #define BMA150_CHIP_ID		2 +#define BMA180_CHIP_ID		3  #define BMA150_CHIP_ID_REG	BMA150_DATA_0_REG  #define BMA150_ACC_X_LSB_REG	BMA150_DATA_2_REG @@ -526,7 +527,8 @@ static int bma150_register_polled_device(struct bma150_data *bma150)  static int bma150_probe(struct i2c_client *client,  				  const struct i2c_device_id *id)  { -	const struct bma150_platform_data *pdata = client->dev.platform_data; +	const struct bma150_platform_data *pdata = +			dev_get_platdata(&client->dev);  	const struct bma150_cfg *cfg;  	struct bma150_data *bma150;  	int chip_id; @@ -538,7 +540,7 @@ static int bma150_probe(struct i2c_client *client,  	}  	chip_id = i2c_smbus_read_byte_data(client, BMA150_CHIP_ID_REG); -	if (chip_id != BMA150_CHIP_ID) { +	if (chip_id != BMA150_CHIP_ID && chip_id != BMA180_CHIP_ID) {  		dev_err(&client->dev, "BMA150 chip id error: %d\n", chip_id);  		return -EINVAL;  	} @@ -642,6 +644,7 @@ static UNIVERSAL_DEV_PM_OPS(bma150_pm, bma150_suspend, bma150_resume, NULL);  static const struct i2c_device_id bma150_id[] = {  	{ "bma150", 0 }, +	{ "bma180", 0 },  	{ "smb380", 0 },  	{ "bma023", 0 },  	{ } diff --git a/drivers/input/misc/cm109.c b/drivers/input/misc/cm109.c index 082684e7f39..9365535ba7f 100644 --- a/drivers/input/misc/cm109.c +++ b/drivers/input/misc/cm109.c @@ -351,7 +351,9 @@ static void cm109_urb_irq_callback(struct urb *urb)  	if (status) {  		if (status == -ESHUTDOWN)  			return; -		dev_err(&dev->intf->dev, "%s: urb status %d\n", __func__, status); +		dev_err_ratelimited(&dev->intf->dev, "%s: urb status %d\n", +				    __func__, status); +		goto out;  	}  	/* Special keys */ @@ -418,8 +420,12 @@ static void cm109_urb_ctl_callback(struct urb *urb)  	     dev->ctl_data->byte[2],  	     dev->ctl_data->byte[3]); -	if (status) -		dev_err(&dev->intf->dev, "%s: urb status %d\n", __func__, status); +	if (status) { +		if (status == -ESHUTDOWN) +			return; +		dev_err_ratelimited(&dev->intf->dev, "%s: urb status %d\n", +				    __func__, status); +	}  	spin_lock(&dev->ctl_submit_lock); @@ -427,7 +433,7 @@ static void cm109_urb_ctl_callback(struct urb *urb)  	if (likely(!dev->shutdown)) { -		if (dev->buzzer_pending) { +		if (dev->buzzer_pending || status) {  			dev->buzzer_pending = 0;  			dev->ctl_urb_pending = 1;  			cm109_submit_buzz_toggle(dev); diff --git a/drivers/input/misc/cma3000_d0x.c b/drivers/input/misc/cma3000_d0x.c index df9b756594f..c7d00748277 100644 --- a/drivers/input/misc/cma3000_d0x.c +++ b/drivers/input/misc/cma3000_d0x.c @@ -284,7 +284,7 @@ EXPORT_SYMBOL(cma3000_resume);  struct cma3000_accl_data *cma3000_init(struct device *dev, int irq,  				       const struct cma3000_bus_ops *bops)  { -	const struct cma3000_platform_data *pdata = dev->platform_data; +	const struct cma3000_platform_data *pdata = dev_get_platdata(dev);  	struct cma3000_accl_data *data;  	struct input_dev *input_dev;  	int rev; diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c index 4f77f87847e..3e11510ff82 100644 --- a/drivers/input/misc/cobalt_btns.c +++ b/drivers/input/misc/cobalt_btns.c @@ -17,7 +17,6 @@   *  along with this program; if not, write to the Free Software   *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA   */ -#include <linux/init.h>  #include <linux/input-polldev.h>  #include <linux/ioport.h>  #include <linux/module.h> @@ -131,7 +130,6 @@ static int cobalt_buttons_probe(struct platform_device *pdev)   err_free_mem:  	input_free_polled_device(poll_dev);  	kfree(bdev); -	dev_set_drvdata(&pdev->dev, NULL);  	return error;  } @@ -144,7 +142,6 @@ static int cobalt_buttons_remove(struct platform_device *pdev)  	input_free_polled_device(bdev->poll_dev);  	iounmap(bdev->reg);  	kfree(bdev); -	dev_set_drvdata(dev, NULL);  	return 0;  } diff --git a/drivers/input/misc/da9052_onkey.c b/drivers/input/misc/da9052_onkey.c index 020569a499f..184c8f21ab5 100644 --- a/drivers/input/misc/da9052_onkey.c +++ b/drivers/input/misc/da9052_onkey.c @@ -11,7 +11,6 @@   * option) any later version.   */ -#include <linux/init.h>  #include <linux/input.h>  #include <linux/module.h>  #include <linux/platform_device.h> @@ -28,29 +27,32 @@ struct da9052_onkey {  static void da9052_onkey_query(struct da9052_onkey *onkey)  { -	int key_stat; +	int ret; -	key_stat = da9052_reg_read(onkey->da9052, DA9052_EVENT_B_REG); -	if (key_stat < 0) { +	ret = da9052_reg_read(onkey->da9052, DA9052_STATUS_A_REG); +	if (ret < 0) {  		dev_err(onkey->da9052->dev, -			"Failed to read onkey event %d\n", key_stat); +			"Failed to read onkey event err=%d\n", ret);  	} else {  		/*  		 * Since interrupt for deassertion of ONKEY pin is not  		 * generated, onkey event state determines the onkey  		 * button state.  		 */ -		key_stat &= DA9052_EVENTB_ENONKEY; -		input_report_key(onkey->input, KEY_POWER, key_stat); +		bool pressed = !(ret & DA9052_STATUSA_NONKEY); + +		input_report_key(onkey->input, KEY_POWER, pressed);  		input_sync(onkey->input); -	} -	/* -	 * Interrupt is generated only when the ONKEY pin is asserted. -	 * Hence the deassertion of the pin is simulated through work queue. -	 */ -	if (key_stat) -		schedule_delayed_work(&onkey->work, msecs_to_jiffies(50)); +		/* +		 * Interrupt is generated only when the ONKEY pin +		 * is asserted.  Hence the deassertion of the pin +		 * is simulated through work queue. +		 */ +		if (pressed) +			schedule_delayed_work(&onkey->work, +						msecs_to_jiffies(50)); +	}  }  static void da9052_onkey_work(struct work_struct *work) diff --git a/drivers/input/misc/da9055_onkey.c b/drivers/input/misc/da9055_onkey.c index a0af8b2506c..4765799fef7 100644 --- a/drivers/input/misc/da9055_onkey.c +++ b/drivers/input/misc/da9055_onkey.c @@ -11,7 +11,6 @@   * option) any later version.   */ -#include <linux/init.h>  #include <linux/input.h>  #include <linux/module.h>  #include <linux/platform_device.h> @@ -110,7 +109,6 @@ static int da9055_onkey_probe(struct platform_device *pdev)  	INIT_DELAYED_WORK(&onkey->work, da9055_onkey_work); -	irq = regmap_irq_get_virq(da9055->irq_data, irq);  	err = request_threaded_irq(irq, NULL, da9055_onkey_irq,  				   IRQF_TRIGGER_HIGH | IRQF_ONESHOT,  				   "ONKEY", onkey); diff --git a/drivers/input/misc/dm355evm_keys.c b/drivers/input/misc/dm355evm_keys.c index a309a5c0899..0eba94f581d 100644 --- a/drivers/input/misc/dm355evm_keys.c +++ b/drivers/input/misc/dm355evm_keys.c @@ -9,7 +9,6 @@   * 2 of the License, or (at your option) any later version.   */  #include <linux/kernel.h> -#include <linux/init.h>  #include <linux/slab.h>  #include <linux/input.h>  #include <linux/input/sparse-keymap.h> diff --git a/drivers/input/misc/gp2ap002a00f.c b/drivers/input/misc/gp2ap002a00f.c index fe30bd0fe4b..de21e317da3 100644 --- a/drivers/input/misc/gp2ap002a00f.c +++ b/drivers/input/misc/gp2ap002a00f.c @@ -125,7 +125,7 @@ static int gp2a_initialize(struct gp2a_data *dt)  static int gp2a_probe(struct i2c_client *client,  				const struct i2c_device_id *id)  { -	const struct gp2a_platform_data *pdata = client->dev.platform_data; +	const struct gp2a_platform_data *pdata = dev_get_platdata(&client->dev);  	struct gp2a_data *dt;  	int error; diff --git a/drivers/input/misc/gpio-beeper.c b/drivers/input/misc/gpio-beeper.c new file mode 100644 index 00000000000..8886af63eae --- /dev/null +++ b/drivers/input/misc/gpio-beeper.c @@ -0,0 +1,124 @@ +/* + * Generic GPIO beeper driver + * + * Copyright (C) 2013-2014 Alexander Shiyan <shc_work@mail.ru> + * + * 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/input.h> +#include <linux/module.h> +#include <linux/gpio/consumer.h> +#include <linux/of.h> +#include <linux/workqueue.h> +#include <linux/platform_device.h> + +#define BEEPER_MODNAME		"gpio-beeper" + +struct gpio_beeper { +	struct work_struct	work; +	struct gpio_desc	*desc; +	bool			beeping; +}; + +static void gpio_beeper_toggle(struct gpio_beeper *beep, bool on) +{ +	gpiod_set_value_cansleep(beep->desc, on); +} + +static void gpio_beeper_work(struct work_struct *work) +{ +	struct gpio_beeper *beep = container_of(work, struct gpio_beeper, work); + +	gpio_beeper_toggle(beep, beep->beeping); +} + +static int gpio_beeper_event(struct input_dev *dev, unsigned int type, +			     unsigned int code, int value) +{ +	struct gpio_beeper *beep = input_get_drvdata(dev); + +	if (type != EV_SND || code != SND_BELL) +		return -ENOTSUPP; + +	if (value < 0) +		return -EINVAL; + +	beep->beeping = value; +	/* Schedule work to actually turn the beeper on or off */ +	schedule_work(&beep->work); + +	return 0; +} + +static void gpio_beeper_close(struct input_dev *input) +{ +	struct gpio_beeper *beep = input_get_drvdata(input); + +	cancel_work_sync(&beep->work); +	gpio_beeper_toggle(beep, false); +} + +static int gpio_beeper_probe(struct platform_device *pdev) +{ +	struct gpio_beeper *beep; +	struct input_dev *input; +	int err; + +	beep = devm_kzalloc(&pdev->dev, sizeof(*beep), GFP_KERNEL); +	if (!beep) +		return -ENOMEM; + +	beep->desc = devm_gpiod_get(&pdev->dev, NULL); +	if (IS_ERR(beep->desc)) +		return PTR_ERR(beep->desc); + +	input = devm_input_allocate_device(&pdev->dev); +	if (!input) +		return -ENOMEM; + +	INIT_WORK(&beep->work, gpio_beeper_work); + +	input->name		= pdev->name; +	input->id.bustype	= BUS_HOST; +	input->id.vendor	= 0x0001; +	input->id.product	= 0x0001; +	input->id.version	= 0x0100; +	input->close		= gpio_beeper_close; +	input->event		= gpio_beeper_event; + +	input_set_capability(input, EV_SND, SND_BELL); + +	err = gpiod_direction_output(beep->desc, 0); +	if (err) +		return err; + +	input_set_drvdata(input, beep); + +	return input_register_device(input); +} + +#ifdef CONFIG_OF +static const struct of_device_id gpio_beeper_of_match[] = { +	{ .compatible = BEEPER_MODNAME, }, +	{ } +}; +MODULE_DEVICE_TABLE(of, gpio_beeper_of_match); +#endif + +static struct platform_driver gpio_beeper_platform_driver = { +	.driver	= { +		.name		= BEEPER_MODNAME, +		.owner		= THIS_MODULE, +		.of_match_table	= of_match_ptr(gpio_beeper_of_match), +	}, +	.probe	= gpio_beeper_probe, +}; +module_platform_driver(gpio_beeper_platform_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>"); +MODULE_DESCRIPTION("Generic GPIO beeper driver"); diff --git a/drivers/input/misc/gpio_tilt_polled.c b/drivers/input/misc/gpio_tilt_polled.c index 714c6836913..1a81d911522 100644 --- a/drivers/input/misc/gpio_tilt_polled.c +++ b/drivers/input/misc/gpio_tilt_polled.c @@ -16,7 +16,6 @@  #include <linux/kernel.h>  #include <linux/module.h> -#include <linux/init.h>  #include <linux/slab.h>  #include <linux/input.h>  #include <linux/input-polldev.h> @@ -98,7 +97,8 @@ static void gpio_tilt_polled_close(struct input_polled_dev *dev)  static int gpio_tilt_polled_probe(struct platform_device *pdev)  { -	const struct gpio_tilt_platform_data *pdata = pdev->dev.platform_data; +	const struct gpio_tilt_platform_data *pdata = +			dev_get_platdata(&pdev->dev);  	struct device *dev = &pdev->dev;  	struct gpio_tilt_polled_dev *tdev;  	struct input_polled_dev *poll_dev; diff --git a/drivers/input/misc/hp_sdc_rtc.c b/drivers/input/misc/hp_sdc_rtc.c index 86b822806e9..45e0e3e55de 100644 --- a/drivers/input/misc/hp_sdc_rtc.c +++ b/drivers/input/misc/hp_sdc_rtc.c @@ -180,7 +180,10 @@ static int64_t hp_sdc_rtc_read_i8042timer (uint8_t loadcmd, int numreg)  	if (WARN_ON(down_interruptible(&i8042tregs)))  		return -1; -	if (hp_sdc_enqueue_transaction(&t)) return -1; +	if (hp_sdc_enqueue_transaction(&t)) { +		up(&i8042tregs); +		return -1; +	}  	/* Sleep until results come back. */  	if (WARN_ON(down_interruptible(&i8042tregs))) diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c index e204f26b001..719410feb84 100644 --- a/drivers/input/misc/ims-pcu.c +++ b/drivers/input/misc/ims-pcu.c @@ -51,6 +51,8 @@ struct ims_pcu_backlight {  #define IMS_PCU_BL_VERSION_LEN		(9 + 1)  #define IMS_PCU_BL_RESET_REASON_LEN	(2 + 1) +#define IMS_PCU_PCU_B_DEVICE_ID		5 +  #define IMS_PCU_BUF_SIZE		128  struct ims_pcu { @@ -68,6 +70,9 @@ struct ims_pcu {  	char bl_version[IMS_PCU_BL_VERSION_LEN];  	char reset_reason[IMS_PCU_BL_RESET_REASON_LEN];  	int update_firmware_status; +	u8 device_id; + +	u8 ofn_reg_addr;  	struct usb_interface *ctrl_intf; @@ -371,6 +376,8 @@ static void ims_pcu_destroy_gamepad(struct ims_pcu *pcu)  #define IMS_PCU_CMD_GET_DEVICE_ID	0xae  #define IMS_PCU_CMD_SPECIAL_INFO	0xb0  #define IMS_PCU_CMD_BOOTLOADER		0xb1	/* Pass data to bootloader */ +#define IMS_PCU_CMD_OFN_SET_CONFIG	0xb3 +#define IMS_PCU_CMD_OFN_GET_CONFIG	0xb4  /* PCU responses */  #define IMS_PCU_RSP_STATUS		0xc0 @@ -389,6 +396,9 @@ static void ims_pcu_destroy_gamepad(struct ims_pcu *pcu)  #define IMS_PCU_RSP_GET_DEVICE_ID	0xce  #define IMS_PCU_RSP_SPECIAL_INFO	0xd0  #define IMS_PCU_RSP_BOOTLOADER		0xd1	/* Bootloader response */ +#define IMS_PCU_RSP_OFN_SET_CONFIG	0xd2 +#define IMS_PCU_RSP_OFN_GET_CONFIG	0xd3 +  #define IMS_PCU_RSP_EVNT_BUTTONS	0xe0	/* Unsolicited, button state */  #define IMS_PCU_GAMEPAD_MASK		0x0001ff80UL	/* Bits 7 through 16 */ @@ -1256,6 +1266,225 @@ static struct attribute_group ims_pcu_attr_group = {  	.attrs		= ims_pcu_attrs,  }; +/* Support for a separate OFN attribute group */ + +#define OFN_REG_RESULT_OFFSET	2 + +static int ims_pcu_read_ofn_config(struct ims_pcu *pcu, u8 addr, u8 *data) +{ +	int error; +	s16 result; + +	error = ims_pcu_execute_command(pcu, OFN_GET_CONFIG, +					&addr, sizeof(addr)); +	if (error) +		return error; + +	result = (s16)get_unaligned_le16(pcu->cmd_buf + OFN_REG_RESULT_OFFSET); +	if (result < 0) +		return -EIO; + +	/* We only need LSB */ +	*data = pcu->cmd_buf[OFN_REG_RESULT_OFFSET]; +	return 0; +} + +static int ims_pcu_write_ofn_config(struct ims_pcu *pcu, u8 addr, u8 data) +{ +	u8 buffer[] = { addr, data }; +	int error; +	s16 result; + +	error = ims_pcu_execute_command(pcu, OFN_SET_CONFIG, +					&buffer, sizeof(buffer)); +	if (error) +		return error; + +	result = (s16)get_unaligned_le16(pcu->cmd_buf + OFN_REG_RESULT_OFFSET); +	if (result < 0) +		return -EIO; + +	return 0; +} + +static ssize_t ims_pcu_ofn_reg_data_show(struct device *dev, +					 struct device_attribute *dattr, +					 char *buf) +{ +	struct usb_interface *intf = to_usb_interface(dev); +	struct ims_pcu *pcu = usb_get_intfdata(intf); +	int error; +	u8 data; + +	mutex_lock(&pcu->cmd_mutex); +	error = ims_pcu_read_ofn_config(pcu, pcu->ofn_reg_addr, &data); +	mutex_unlock(&pcu->cmd_mutex); + +	if (error) +		return error; + +	return scnprintf(buf, PAGE_SIZE, "%x\n", data); +} + +static ssize_t ims_pcu_ofn_reg_data_store(struct device *dev, +					  struct device_attribute *dattr, +					  const char *buf, size_t count) +{ +	struct usb_interface *intf = to_usb_interface(dev); +	struct ims_pcu *pcu = usb_get_intfdata(intf); +	int error; +	u8 value; + +	error = kstrtou8(buf, 0, &value); +	if (error) +		return error; + +	mutex_lock(&pcu->cmd_mutex); +	error = ims_pcu_write_ofn_config(pcu, pcu->ofn_reg_addr, value); +	mutex_unlock(&pcu->cmd_mutex); + +	return error ?: count; +} + +static DEVICE_ATTR(reg_data, S_IRUGO | S_IWUSR, +		   ims_pcu_ofn_reg_data_show, ims_pcu_ofn_reg_data_store); + +static ssize_t ims_pcu_ofn_reg_addr_show(struct device *dev, +					 struct device_attribute *dattr, +					 char *buf) +{ +	struct usb_interface *intf = to_usb_interface(dev); +	struct ims_pcu *pcu = usb_get_intfdata(intf); +	int error; + +	mutex_lock(&pcu->cmd_mutex); +	error = scnprintf(buf, PAGE_SIZE, "%x\n", pcu->ofn_reg_addr); +	mutex_unlock(&pcu->cmd_mutex); + +	return error; +} + +static ssize_t ims_pcu_ofn_reg_addr_store(struct device *dev, +					  struct device_attribute *dattr, +					  const char *buf, size_t count) +{ +	struct usb_interface *intf = to_usb_interface(dev); +	struct ims_pcu *pcu = usb_get_intfdata(intf); +	int error; +	u8 value; + +	error = kstrtou8(buf, 0, &value); +	if (error) +		return error; + +	mutex_lock(&pcu->cmd_mutex); +	pcu->ofn_reg_addr = value; +	mutex_unlock(&pcu->cmd_mutex); + +	return error ?: count; +} + +static DEVICE_ATTR(reg_addr, S_IRUGO | S_IWUSR, +		   ims_pcu_ofn_reg_addr_show, ims_pcu_ofn_reg_addr_store); + +struct ims_pcu_ofn_bit_attribute { +	struct device_attribute dattr; +	u8 addr; +	u8 nr; +}; + +static ssize_t ims_pcu_ofn_bit_show(struct device *dev, +				    struct device_attribute *dattr, +				    char *buf) +{ +	struct usb_interface *intf = to_usb_interface(dev); +	struct ims_pcu *pcu = usb_get_intfdata(intf); +	struct ims_pcu_ofn_bit_attribute *attr = +		container_of(dattr, struct ims_pcu_ofn_bit_attribute, dattr); +	int error; +	u8 data; + +	mutex_lock(&pcu->cmd_mutex); +	error = ims_pcu_read_ofn_config(pcu, attr->addr, &data); +	mutex_unlock(&pcu->cmd_mutex); + +	if (error) +		return error; + +	return scnprintf(buf, PAGE_SIZE, "%d\n", !!(data & (1 << attr->nr))); +} + +static ssize_t ims_pcu_ofn_bit_store(struct device *dev, +				     struct device_attribute *dattr, +				     const char *buf, size_t count) +{ +	struct usb_interface *intf = to_usb_interface(dev); +	struct ims_pcu *pcu = usb_get_intfdata(intf); +	struct ims_pcu_ofn_bit_attribute *attr = +		container_of(dattr, struct ims_pcu_ofn_bit_attribute, dattr); +	int error; +	int value; +	u8 data; + +	error = kstrtoint(buf, 0, &value); +	if (error) +		return error; + +	if (value > 1) +		return -EINVAL; + +	mutex_lock(&pcu->cmd_mutex); + +	error = ims_pcu_read_ofn_config(pcu, attr->addr, &data); +	if (!error) { +		if (value) +			data |= 1U << attr->nr; +		else +			data &= ~(1U << attr->nr); + +		error = ims_pcu_write_ofn_config(pcu, attr->addr, data); +	} + +	mutex_unlock(&pcu->cmd_mutex); + +	return error ?: count; +} + +#define IMS_PCU_OFN_BIT_ATTR(_field, _addr, _nr)			\ +struct ims_pcu_ofn_bit_attribute ims_pcu_ofn_attr_##_field = {		\ +	.dattr = __ATTR(_field, S_IWUSR | S_IRUGO,			\ +			ims_pcu_ofn_bit_show, ims_pcu_ofn_bit_store),	\ +	.addr = _addr,							\ +	.nr = _nr,							\ +} + +static IMS_PCU_OFN_BIT_ATTR(engine_enable,   0x60, 7); +static IMS_PCU_OFN_BIT_ATTR(speed_enable,    0x60, 6); +static IMS_PCU_OFN_BIT_ATTR(assert_enable,   0x60, 5); +static IMS_PCU_OFN_BIT_ATTR(xyquant_enable,  0x60, 4); +static IMS_PCU_OFN_BIT_ATTR(xyscale_enable,  0x60, 1); + +static IMS_PCU_OFN_BIT_ATTR(scale_x2,        0x63, 6); +static IMS_PCU_OFN_BIT_ATTR(scale_y2,        0x63, 7); + +static struct attribute *ims_pcu_ofn_attrs[] = { +	&dev_attr_reg_data.attr, +	&dev_attr_reg_addr.attr, +	&ims_pcu_ofn_attr_engine_enable.dattr.attr, +	&ims_pcu_ofn_attr_speed_enable.dattr.attr, +	&ims_pcu_ofn_attr_assert_enable.dattr.attr, +	&ims_pcu_ofn_attr_xyquant_enable.dattr.attr, +	&ims_pcu_ofn_attr_xyscale_enable.dattr.attr, +	&ims_pcu_ofn_attr_scale_x2.dattr.attr, +	&ims_pcu_ofn_attr_scale_y2.dattr.attr, +	NULL +}; + +static struct attribute_group ims_pcu_ofn_attr_group = { +	.name	= "ofn", +	.attrs	= ims_pcu_ofn_attrs, +}; +  static void ims_pcu_irq(struct urb *urb)  {  	struct ims_pcu *pcu = urb->context; @@ -1337,6 +1566,7 @@ static int ims_pcu_buffers_alloc(struct ims_pcu *pcu)  	if (!pcu->urb_ctrl_buf) {  		dev_err(pcu->dev,  			"Failed to allocate memory for read buffer\n"); +		error = -ENOMEM;  		goto err_free_urb_out_buf;  	} @@ -1624,7 +1854,6 @@ static int ims_pcu_init_application_mode(struct ims_pcu *pcu)  	static atomic_t device_no = ATOMIC_INIT(0);  	const struct ims_pcu_device_info *info; -	u8 device_id;  	int error;  	error = ims_pcu_get_device_info(pcu); @@ -1633,7 +1862,7 @@ static int ims_pcu_init_application_mode(struct ims_pcu *pcu)  		return error;  	} -	error = ims_pcu_identify_type(pcu, &device_id); +	error = ims_pcu_identify_type(pcu, &pcu->device_id);  	if (error) {  		dev_err(pcu->dev,  			"Failed to identify device, error: %d\n", error); @@ -1645,9 +1874,9 @@ static int ims_pcu_init_application_mode(struct ims_pcu *pcu)  		return 0;  	} -	if (device_id >= ARRAY_SIZE(ims_pcu_device_info) || -	    !ims_pcu_device_info[device_id].keymap) { -		dev_err(pcu->dev, "Device ID %d is not valid\n", device_id); +	if (pcu->device_id >= ARRAY_SIZE(ims_pcu_device_info) || +	    !ims_pcu_device_info[pcu->device_id].keymap) { +		dev_err(pcu->dev, "Device ID %d is not valid\n", pcu->device_id);  		/* Same as above, punt to userspace */  		return 0;  	} @@ -1655,11 +1884,21 @@ static int ims_pcu_init_application_mode(struct ims_pcu *pcu)  	/* Device appears to be operable, complete initialization */  	pcu->device_no = atomic_inc_return(&device_no) - 1; +	/* +	 * PCU-B devices, both GEN_1 and GEN_2 do not have OFN sensor +	 */ +	if (pcu->device_id != IMS_PCU_PCU_B_DEVICE_ID) { +		error = sysfs_create_group(&pcu->dev->kobj, +					   &ims_pcu_ofn_attr_group); +		if (error) +			return error; +	} +  	error = ims_pcu_setup_backlight(pcu);  	if (error)  		return error; -	info = &ims_pcu_device_info[device_id]; +	info = &ims_pcu_device_info[pcu->device_id];  	error = ims_pcu_setup_buttons(pcu, info->keymap, info->keymap_len);  	if (error)  		goto err_destroy_backlight; @@ -1674,10 +1913,10 @@ static int ims_pcu_init_application_mode(struct ims_pcu *pcu)  	return 0; -err_destroy_backlight: -	ims_pcu_destroy_backlight(pcu);  err_destroy_buttons:  	ims_pcu_destroy_buttons(pcu); +err_destroy_backlight: +	ims_pcu_destroy_backlight(pcu);  	return error;  } @@ -1691,6 +1930,10 @@ static void ims_pcu_destroy_application_mode(struct ims_pcu *pcu)  			ims_pcu_destroy_gamepad(pcu);  		ims_pcu_destroy_buttons(pcu);  		ims_pcu_destroy_backlight(pcu); + +		if (pcu->device_id != IMS_PCU_PCU_B_DEVICE_ID) +			sysfs_remove_group(&pcu->dev->kobj, +					   &ims_pcu_ofn_attr_group);  	}  } diff --git a/drivers/input/misc/ixp4xx-beeper.c b/drivers/input/misc/ixp4xx-beeper.c index f34beb228d3..ed8e5e8449d 100644 --- a/drivers/input/misc/ixp4xx-beeper.c +++ b/drivers/input/misc/ixp4xx-beeper.c @@ -20,6 +20,7 @@  #include <linux/delay.h>  #include <linux/platform_device.h>  #include <linux/interrupt.h> +#include <linux/gpio.h>  #include <mach/hardware.h>  MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); @@ -35,15 +36,12 @@ static void ixp4xx_spkr_control(unsigned int pin, unsigned int count)  	spin_lock_irqsave(&beep_lock, flags); -	 if (count) { -		gpio_line_config(pin, IXP4XX_GPIO_OUT); -		gpio_line_set(pin, IXP4XX_GPIO_LOW); - +	if (count) { +		gpio_direction_output(pin, 0);  		*IXP4XX_OSRT2 = (count & ~IXP4XX_OST_RELOAD_MASK) | IXP4XX_OST_ENABLE;  	} else { -		gpio_line_config(pin, IXP4XX_GPIO_IN); -		gpio_line_set(pin, IXP4XX_GPIO_HIGH); - +		gpio_direction_output(pin, 1); +		gpio_direction_input(pin);  		*IXP4XX_OSRT2 = 0;  	} @@ -69,7 +67,7 @@ static int ixp4xx_spkr_event(struct input_dev *dev, unsigned int type, unsigned  	}  	if (value > 20 && value < 32767) -		count = (IXP4XX_TIMER_FREQ / (value * 4)) - 1; +		count = (ixp4xx_timer_freq / (value * 4)) - 1;  	ixp4xx_spkr_control(pin, count); @@ -78,11 +76,13 @@ static int ixp4xx_spkr_event(struct input_dev *dev, unsigned int type, unsigned  static irqreturn_t ixp4xx_spkr_interrupt(int irq, void *dev_id)  { +	unsigned int pin = (unsigned int) dev_id; +  	/* clear interrupt */  	*IXP4XX_OSST = IXP4XX_OSST_TIMER_2_PEND;  	/* flip the beeper output */ -	*IXP4XX_GPIO_GPOUTR ^= (1 << (unsigned int) dev_id); +	gpio_set_value(pin, !gpio_get_value(pin));  	return IRQ_HANDLED;  } @@ -110,11 +110,15 @@ static int ixp4xx_spkr_probe(struct platform_device *dev)  	input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE);  	input_dev->event = ixp4xx_spkr_event; +	err = gpio_request(dev->id, "ixp4-beeper"); +	if (err) +		goto err_free_device; +  	err = request_irq(IRQ_IXP4XX_TIMER2, &ixp4xx_spkr_interrupt,  			  IRQF_NO_SUSPEND, "ixp4xx-beeper",  			  (void *) dev->id);  	if (err) -		goto err_free_device; +		goto err_free_gpio;  	err = input_register_device(input_dev);  	if (err) @@ -126,6 +130,8 @@ static int ixp4xx_spkr_probe(struct platform_device *dev)   err_free_irq:  	free_irq(IRQ_IXP4XX_TIMER2, (void *)dev->id); + err_free_gpio: +	gpio_free(dev->id);   err_free_device:  	input_free_device(input_dev); @@ -144,6 +150,7 @@ static int ixp4xx_spkr_remove(struct platform_device *dev)  	ixp4xx_spkr_control(pin, 0);  	free_irq(IRQ_IXP4XX_TIMER2, (void *)dev->id); +	gpio_free(dev->id);  	return 0;  } diff --git a/drivers/input/misc/keyspan_remote.c b/drivers/input/misc/keyspan_remote.c index 290fa5f97de..01f3b5b300f 100644 --- a/drivers/input/misc/keyspan_remote.c +++ b/drivers/input/misc/keyspan_remote.c @@ -13,7 +13,6 @@  #include <linux/kernel.h>  #include <linux/errno.h> -#include <linux/init.h>  #include <linux/slab.h>  #include <linux/module.h>  #include <linux/usb/input.h> diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c index a993b67a8a5..d708478bc5b 100644 --- a/drivers/input/misc/kxtj9.c +++ b/drivers/input/misc/kxtj9.c @@ -509,7 +509,8 @@ out:  static int kxtj9_probe(struct i2c_client *client,  				 const struct i2c_device_id *id)  { -	const struct kxtj9_platform_data *pdata = client->dev.platform_data; +	const struct kxtj9_platform_data *pdata = +			dev_get_platdata(&client->dev);  	struct kxtj9_data *tj9;  	int err; diff --git a/drivers/input/misc/max8925_onkey.c b/drivers/input/misc/max8925_onkey.c index eef41cfc054..3809618e6a5 100644 --- a/drivers/input/misc/max8925_onkey.c +++ b/drivers/input/misc/max8925_onkey.c @@ -26,6 +26,7 @@  #include <linux/interrupt.h>  #include <linux/mfd/max8925.h>  #include <linux/slab.h> +#include <linux/device.h>  #define SW_INPUT		(1 << 7)	/* 0/1 -- up/down */  #define HARDRESET_EN		(1 << 7) @@ -81,12 +82,14 @@ static int max8925_onkey_probe(struct platform_device *pdev)  		return -EINVAL;  	} -	info = kzalloc(sizeof(struct max8925_onkey_info), GFP_KERNEL); -	input = input_allocate_device(); -	if (!info || !input) { -		error = -ENOMEM; -		goto err_free_mem; -	} +	info = devm_kzalloc(&pdev->dev, sizeof(struct max8925_onkey_info), +			    GFP_KERNEL); +	if (!info) +		return -ENOMEM; + +	input = devm_input_allocate_device(&pdev->dev); +	if (!input) +		return -ENOMEM;  	info->idev = input;  	info->i2c = chip->i2c; @@ -100,55 +103,34 @@ static int max8925_onkey_probe(struct platform_device *pdev)  	input->dev.parent = &pdev->dev;  	input_set_capability(input, EV_KEY, KEY_POWER); -	error = request_threaded_irq(irq[0], NULL, max8925_onkey_handler, -				     IRQF_ONESHOT, "onkey-down", info); +	error = devm_request_threaded_irq(&pdev->dev, irq[0], NULL, +					  max8925_onkey_handler, IRQF_ONESHOT, +					  "onkey-down", info);  	if (error < 0) {  		dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n",  			irq[0], error); -		goto err_free_mem; +		return error;  	} -	error = request_threaded_irq(irq[1], NULL, max8925_onkey_handler, -				     IRQF_ONESHOT, "onkey-up", info); +	error = devm_request_threaded_irq(&pdev->dev, irq[1], NULL, +					  max8925_onkey_handler, IRQF_ONESHOT, +					  "onkey-up", info);  	if (error < 0) {  		dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n",  			irq[1], error); -		goto err_free_irq0; +		return error;  	}  	error = input_register_device(info->idev);  	if (error) {  		dev_err(chip->dev, "Can't register input device: %d\n", error); -		goto err_free_irq1; +		return error;  	}  	platform_set_drvdata(pdev, info);  	device_init_wakeup(&pdev->dev, 1);  	return 0; - -err_free_irq1: -	free_irq(irq[1], info); -err_free_irq0: -	free_irq(irq[0], info); -err_free_mem: -	input_free_device(input); -	kfree(info); - -	return error; -} - -static int max8925_onkey_remove(struct platform_device *pdev) -{ -	struct max8925_onkey_info *info = platform_get_drvdata(pdev); -	struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); - -	free_irq(info->irq[0] + chip->irq_base, info); -	free_irq(info->irq[1] + chip->irq_base, info); -	input_unregister_device(info->idev); -	kfree(info); - -	return 0;  }  #ifdef CONFIG_PM_SLEEP @@ -190,7 +172,6 @@ static struct platform_driver max8925_onkey_driver = {  		.pm	= &max8925_onkey_pm_ops,  	},  	.probe		= max8925_onkey_probe, -	.remove		= max8925_onkey_remove,  };  module_platform_driver(max8925_onkey_driver); diff --git a/drivers/input/misc/max8997_haptic.c b/drivers/input/misc/max8997_haptic.c index e973133212a..a363ebbd9cc 100644 --- a/drivers/input/misc/max8997_haptic.c +++ b/drivers/input/misc/max8997_haptic.c @@ -23,7 +23,6 @@   */  #include <linux/module.h> -#include <linux/init.h>  #include <linux/slab.h>  #include <linux/platform_device.h>  #include <linux/err.h> @@ -182,11 +181,21 @@ static void max8997_haptic_enable(struct max8997_haptic *chip)  	}  	if (!chip->enabled) { -		chip->enabled = true; -		regulator_enable(chip->regulator); +		error = regulator_enable(chip->regulator); +		if (error) { +			dev_err(chip->dev, "Failed to enable regulator\n"); +			goto out; +		}  		max8997_haptic_configure(chip); -		if (chip->mode == MAX8997_EXTERNAL_MODE) -			pwm_enable(chip->pwm); +		if (chip->mode == MAX8997_EXTERNAL_MODE) { +			error = pwm_enable(chip->pwm); +			if (error) { +				dev_err(chip->dev, "Failed to enable PWM\n"); +				regulator_disable(chip->regulator); +				goto out; +			} +		} +		chip->enabled = true;  	}  out: diff --git a/drivers/input/misc/mc13783-pwrbutton.c b/drivers/input/misc/mc13783-pwrbutton.c index d0277a7b157..0df6e8d8bd0 100644 --- a/drivers/input/misc/mc13783-pwrbutton.c +++ b/drivers/input/misc/mc13783-pwrbutton.c @@ -20,7 +20,6 @@   */  #include <linux/module.h> -#include <linux/init.h>  #include <linux/kernel.h>  #include <linux/errno.h>  #include <linux/input.h> diff --git a/drivers/input/misc/mma8450.c b/drivers/input/misc/mma8450.c index f3309696d05..59d4dcddf6d 100644 --- a/drivers/input/misc/mma8450.c +++ b/drivers/input/misc/mma8450.c @@ -168,7 +168,7 @@ static void mma8450_close(struct input_polled_dev *dev)   * I2C init/probing/exit functions   */  static int mma8450_probe(struct i2c_client *c, -				   const struct i2c_device_id *id) +			 const struct i2c_device_id *id)  {  	struct input_polled_dev *idev;  	struct mma8450 *m; @@ -204,6 +204,8 @@ static int mma8450_probe(struct i2c_client *c,  		goto err_free_mem;  	} +	i2c_set_clientdata(c, m); +  	return 0;  err_free_mem: diff --git a/drivers/input/misc/mpu3050.c b/drivers/input/misc/mpu3050.c index dce0d95943c..5e5051351c3 100644 --- a/drivers/input/misc/mpu3050.c +++ b/drivers/input/misc/mpu3050.c @@ -30,7 +30,6 @@   */  #include <linux/module.h> -#include <linux/init.h>  #include <linux/interrupt.h>  #include <linux/platform_device.h>  #include <linux/mutex.h> @@ -383,6 +382,7 @@ static int mpu3050_probe(struct i2c_client *client,  	pm_runtime_enable(&client->dev);  	pm_runtime_set_autosuspend_delay(&client->dev, MPU3050_AUTO_DELAY); +	i2c_set_clientdata(client, sensor);  	return 0; diff --git a/drivers/input/misc/pcap_keys.c b/drivers/input/misc/pcap_keys.c index 40ac9a5adf8..cd230365166 100644 --- a/drivers/input/misc/pcap_keys.c +++ b/drivers/input/misc/pcap_keys.c @@ -12,7 +12,6 @@   */  #include <linux/module.h> -#include <linux/init.h>  #include <linux/interrupt.h>  #include <linux/platform_device.h>  #include <linux/input.h> diff --git a/drivers/input/misc/pcf50633-input.c b/drivers/input/misc/pcf50633-input.c index 73b13ebabe5..db92f4f3c99 100644 --- a/drivers/input/misc/pcf50633-input.c +++ b/drivers/input/misc/pcf50633-input.c @@ -16,7 +16,6 @@  #include <linux/kernel.h>  #include <linux/module.h> -#include <linux/init.h>  #include <linux/device.h>  #include <linux/platform_device.h>  #include <linux/input.h> diff --git a/drivers/input/misc/pcf8574_keypad.c b/drivers/input/misc/pcf8574_keypad.c index e37392976fd..97f711a7bd2 100644 --- a/drivers/input/misc/pcf8574_keypad.c +++ b/drivers/input/misc/pcf8574_keypad.c @@ -7,7 +7,6 @@   */  #include <linux/module.h> -#include <linux/init.h>  #include <linux/input.h>  #include <linux/interrupt.h>  #include <linux/i2c.h> @@ -113,9 +112,12 @@ static int pcf8574_kp_probe(struct i2c_client *client, const struct i2c_device_i  	idev->keycodemax = ARRAY_SIZE(lp->btncode);  	for (i = 0; i < ARRAY_SIZE(pcf8574_kp_btncode); i++) { -		lp->btncode[i] = pcf8574_kp_btncode[i]; -		__set_bit(lp->btncode[i] & KEY_MAX, idev->keybit); +		if (lp->btncode[i] <= KEY_MAX) { +			lp->btncode[i] = pcf8574_kp_btncode[i]; +			__set_bit(lp->btncode[i], idev->keybit); +		}  	} +	__clear_bit(KEY_RESERVED, idev->keybit);  	sprintf(lp->name, DRV_NAME);  	sprintf(lp->phys, "kp_data/input0"); diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c index 7288b267613..674a2cfc3c0 100644 --- a/drivers/input/misc/pcspkr.c +++ b/drivers/input/misc/pcspkr.c @@ -15,7 +15,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/i8253.h> -#include <linux/init.h>  #include <linux/input.h>  #include <linux/platform_device.h>  #include <linux/timex.h> diff --git a/drivers/input/misc/pm8xxx-vibrator.c b/drivers/input/misc/pm8xxx-vibrator.c index ec086f6f3cc..6a915ba31bb 100644 --- a/drivers/input/misc/pm8xxx-vibrator.c +++ b/drivers/input/misc/pm8xxx-vibrator.c @@ -11,13 +11,12 @@   */  #include <linux/module.h> -#include <linux/init.h>  #include <linux/kernel.h>  #include <linux/errno.h>  #include <linux/platform_device.h>  #include <linux/input.h>  #include <linux/slab.h> -#include <linux/mfd/pm8xxx/core.h> +#include <linux/regmap.h>  #define VIB_DRV			0x4A @@ -35,7 +34,7 @@   * struct pm8xxx_vib - structure to hold vibrator data   * @vib_input_dev: input device supporting force feedback   * @work: work structure to set the vibration parameters - * @dev: device supporting force feedback + * @regmap: regmap for register read/write   * @speed: speed of vibration set from userland   * @active: state of vibrator   * @level: level of vibration to set in the chip @@ -44,7 +43,7 @@  struct pm8xxx_vib {  	struct input_dev *vib_input_dev;  	struct work_struct work; -	struct device *dev; +	struct regmap *regmap;  	int speed;  	int level;  	bool active; @@ -52,42 +51,6 @@ struct pm8xxx_vib {  };  /** - * pm8xxx_vib_read_u8 - helper to read a byte from pmic chip - * @vib: pointer to vibrator structure - * @data: placeholder for data to be read - * @reg: register address - */ -static int pm8xxx_vib_read_u8(struct pm8xxx_vib *vib, -				 u8 *data, u16 reg) -{ -	int rc; - -	rc = pm8xxx_readb(vib->dev->parent, reg, data); -	if (rc < 0) -		dev_warn(vib->dev, "Error reading pm8xxx reg 0x%x(0x%x)\n", -				reg, rc); -	return rc; -} - -/** - * pm8xxx_vib_write_u8 - helper to write a byte to pmic chip - * @vib: pointer to vibrator structure - * @data: data to write - * @reg: register address - */ -static int pm8xxx_vib_write_u8(struct pm8xxx_vib *vib, -				 u8 data, u16 reg) -{ -	int rc; - -	rc = pm8xxx_writeb(vib->dev->parent, reg, data); -	if (rc < 0) -		dev_warn(vib->dev, "Error writing pm8xxx reg 0x%x(0x%x)\n", -				reg, rc); -	return rc; -} - -/**   * pm8xxx_vib_set - handler to start/stop vibration   * @vib: pointer to vibrator structure   * @on: state to set @@ -95,14 +58,14 @@ static int pm8xxx_vib_write_u8(struct pm8xxx_vib *vib,  static int pm8xxx_vib_set(struct pm8xxx_vib *vib, bool on)  {  	int rc; -	u8 val = vib->reg_vib_drv; +	unsigned int val = vib->reg_vib_drv;  	if (on)  		val |= ((vib->level << VIB_DRV_SEL_SHIFT) & VIB_DRV_SEL_MASK);  	else  		val &= ~VIB_DRV_SEL_MASK; -	rc = pm8xxx_vib_write_u8(vib, val, VIB_DRV); +	rc = regmap_write(vib->regmap, VIB_DRV, val);  	if (rc < 0)  		return rc; @@ -118,9 +81,9 @@ static void pm8xxx_work_handler(struct work_struct *work)  {  	struct pm8xxx_vib *vib = container_of(work, struct pm8xxx_vib, work);  	int rc; -	u8 val; +	unsigned int val; -	rc = pm8xxx_vib_read_u8(vib, &val, VIB_DRV); +	rc = regmap_read(vib->regmap, VIB_DRV, &val);  	if (rc < 0)  		return; @@ -179,39 +142,41 @@ static int pm8xxx_vib_play_effect(struct input_dev *dev, void *data,  }  static int pm8xxx_vib_probe(struct platform_device *pdev) -  {  	struct pm8xxx_vib *vib;  	struct input_dev *input_dev;  	int error; -	u8 val; - -	vib = kzalloc(sizeof(*vib), GFP_KERNEL); -	input_dev = input_allocate_device(); -	if (!vib || !input_dev) { -		dev_err(&pdev->dev, "couldn't allocate memory\n"); -		error = -ENOMEM; -		goto err_free_mem; -	} +	unsigned int val; + +	vib = devm_kzalloc(&pdev->dev, sizeof(*vib), GFP_KERNEL); +	if (!vib) +		return -ENOMEM; + +	vib->regmap = dev_get_regmap(pdev->dev.parent, NULL); +	if (!vib->regmap) +		return -ENODEV; + +	input_dev = devm_input_allocate_device(&pdev->dev); +	if (!input_dev) +		return -ENOMEM;  	INIT_WORK(&vib->work, pm8xxx_work_handler); -	vib->dev = &pdev->dev;  	vib->vib_input_dev = input_dev;  	/* operate in manual mode */ -	error = pm8xxx_vib_read_u8(vib, &val, VIB_DRV); +	error = regmap_read(vib->regmap, VIB_DRV, &val);  	if (error < 0) -		goto err_free_mem; +		return error; +  	val &= ~VIB_DRV_EN_MANUAL_MASK; -	error = pm8xxx_vib_write_u8(vib, val, VIB_DRV); +	error = regmap_write(vib->regmap, VIB_DRV, val);  	if (error < 0) -		goto err_free_mem; +		return error;  	vib->reg_vib_drv = val;  	input_dev->name = "pm8xxx_vib_ffmemless";  	input_dev->id.version = 1; -	input_dev->dev.parent = &pdev->dev;  	input_dev->close = pm8xxx_vib_close;  	input_set_drvdata(input_dev, vib);  	input_set_capability(vib->vib_input_dev, EV_FF, FF_RUMBLE); @@ -221,35 +186,17 @@ static int pm8xxx_vib_probe(struct platform_device *pdev)  	if (error) {  		dev_err(&pdev->dev,  			"couldn't register vibrator as FF device\n"); -		goto err_free_mem; +		return error;  	}  	error = input_register_device(input_dev);  	if (error) {  		dev_err(&pdev->dev, "couldn't register input device\n"); -		goto err_destroy_memless; +		return error;  	}  	platform_set_drvdata(pdev, vib);  	return 0; - -err_destroy_memless: -	input_ff_destroy(input_dev); -err_free_mem: -	input_free_device(input_dev); -	kfree(vib); - -	return error; -} - -static int pm8xxx_vib_remove(struct platform_device *pdev) -{ -	struct pm8xxx_vib *vib = platform_get_drvdata(pdev); - -	input_unregister_device(vib->vib_input_dev); -	kfree(vib); - -	return 0;  }  #ifdef CONFIG_PM_SLEEP @@ -266,13 +213,20 @@ static int pm8xxx_vib_suspend(struct device *dev)  static SIMPLE_DEV_PM_OPS(pm8xxx_vib_pm_ops, pm8xxx_vib_suspend, NULL); +static const struct of_device_id pm8xxx_vib_id_table[] = { +	{ .compatible = "qcom,pm8058-vib" }, +	{ .compatible = "qcom,pm8921-vib" }, +	{ } +}; +MODULE_DEVICE_TABLE(of, pm8xxx_vib_id_table); +  static struct platform_driver pm8xxx_vib_driver = {  	.probe		= pm8xxx_vib_probe, -	.remove		= pm8xxx_vib_remove,  	.driver		= {  		.name	= "pm8xxx-vib",  		.owner	= THIS_MODULE,  		.pm	= &pm8xxx_vib_pm_ops, +		.of_match_table = pm8xxx_vib_id_table,  	},  };  module_platform_driver(pm8xxx_vib_driver); diff --git a/drivers/input/misc/pmic8xxx-pwrkey.c b/drivers/input/misc/pmic8xxx-pwrkey.c index b49b738aa9c..c91e3d33aea 100644 --- a/drivers/input/misc/pmic8xxx-pwrkey.c +++ b/drivers/input/misc/pmic8xxx-pwrkey.c @@ -11,17 +11,15 @@   */  #include <linux/module.h> -#include <linux/init.h>  #include <linux/kernel.h>  #include <linux/errno.h>  #include <linux/slab.h>  #include <linux/input.h>  #include <linux/interrupt.h>  #include <linux/platform_device.h> +#include <linux/regmap.h>  #include <linux/log2.h> - -#include <linux/mfd/pm8xxx/core.h> -#include <linux/input/pmic8xxx-pwrkey.h> +#include <linux/of.h>  #define PON_CNTL_1 0x1C  #define PON_CNTL_PULL_UP BIT(7) @@ -32,26 +30,25 @@   * @key_press_irq: key press irq number   */  struct pmic8xxx_pwrkey { -	struct input_dev *pwr;  	int key_press_irq;  }; -static irqreturn_t pwrkey_press_irq(int irq, void *_pwrkey) +static irqreturn_t pwrkey_press_irq(int irq, void *_pwr)  { -	struct pmic8xxx_pwrkey *pwrkey = _pwrkey; +	struct input_dev *pwr = _pwr; -	input_report_key(pwrkey->pwr, KEY_POWER, 1); -	input_sync(pwrkey->pwr); +	input_report_key(pwr, KEY_POWER, 1); +	input_sync(pwr);  	return IRQ_HANDLED;  } -static irqreturn_t pwrkey_release_irq(int irq, void *_pwrkey) +static irqreturn_t pwrkey_release_irq(int irq, void *_pwr)  { -	struct pmic8xxx_pwrkey *pwrkey = _pwrkey; +	struct input_dev *pwr = _pwr; -	input_report_key(pwrkey->pwr, KEY_POWER, 0); -	input_sync(pwrkey->pwr); +	input_report_key(pwr, KEY_POWER, 0); +	input_sync(pwr);  	return IRQ_HANDLED;  } @@ -88,127 +85,119 @@ static int pmic8xxx_pwrkey_probe(struct platform_device *pdev)  	int key_press_irq = platform_get_irq(pdev, 1);  	int err;  	unsigned int delay; -	u8 pon_cntl; +	unsigned int pon_cntl; +	struct regmap *regmap;  	struct pmic8xxx_pwrkey *pwrkey; -	const struct pm8xxx_pwrkey_platform_data *pdata = -					dev_get_platdata(&pdev->dev); +	u32 kpd_delay; +	bool pull_up; -	if (!pdata) { -		dev_err(&pdev->dev, "power key platform data not supplied\n"); -		return -EINVAL; -	} +	if (of_property_read_u32(pdev->dev.of_node, "debounce", &kpd_delay)) +		kpd_delay = 15625; -	if (pdata->kpd_trigger_delay_us > 62500) { +	if (kpd_delay > 62500 || kpd_delay == 0) {  		dev_err(&pdev->dev, "invalid power key trigger delay\n");  		return -EINVAL;  	} -	pwrkey = kzalloc(sizeof(*pwrkey), GFP_KERNEL); +	pull_up = of_property_read_bool(pdev->dev.of_node, "pull-up"); + +	regmap = dev_get_regmap(pdev->dev.parent, NULL); +	if (!regmap) { +		dev_err(&pdev->dev, "failed to locate regmap for the device\n"); +		return -ENODEV; +	} + +	pwrkey = devm_kzalloc(&pdev->dev, sizeof(*pwrkey), GFP_KERNEL);  	if (!pwrkey)  		return -ENOMEM; -	pwr = input_allocate_device(); +	pwrkey->key_press_irq = key_press_irq; + +	pwr = devm_input_allocate_device(&pdev->dev);  	if (!pwr) {  		dev_dbg(&pdev->dev, "Can't allocate power button\n"); -		err = -ENOMEM; -		goto free_pwrkey; +		return -ENOMEM;  	}  	input_set_capability(pwr, EV_KEY, KEY_POWER);  	pwr->name = "pmic8xxx_pwrkey";  	pwr->phys = "pmic8xxx_pwrkey/input0"; -	pwr->dev.parent = &pdev->dev; -	delay = (pdata->kpd_trigger_delay_us << 10) / USEC_PER_SEC; +	delay = (kpd_delay << 10) / USEC_PER_SEC;  	delay = 1 + ilog2(delay); -	err = pm8xxx_readb(pdev->dev.parent, PON_CNTL_1, &pon_cntl); +	err = regmap_read(regmap, PON_CNTL_1, &pon_cntl);  	if (err < 0) {  		dev_err(&pdev->dev, "failed reading PON_CNTL_1 err=%d\n", err); -		goto free_input_dev; +		return err;  	}  	pon_cntl &= ~PON_CNTL_TRIG_DELAY_MASK;  	pon_cntl |= (delay & PON_CNTL_TRIG_DELAY_MASK); -	if (pdata->pull_up) +	if (pull_up)  		pon_cntl |= PON_CNTL_PULL_UP;  	else  		pon_cntl &= ~PON_CNTL_PULL_UP; -	err = pm8xxx_writeb(pdev->dev.parent, PON_CNTL_1, pon_cntl); +	err = regmap_write(regmap, PON_CNTL_1, pon_cntl);  	if (err < 0) {  		dev_err(&pdev->dev, "failed writing PON_CNTL_1 err=%d\n", err); -		goto free_input_dev; +		return err;  	} -	err = input_register_device(pwr); +	err = devm_request_irq(&pdev->dev, key_press_irq, pwrkey_press_irq, +			       IRQF_TRIGGER_RISING, +			       "pmic8xxx_pwrkey_press", pwr);  	if (err) { -		dev_dbg(&pdev->dev, "Can't register power key: %d\n", err); -		goto free_input_dev; +		dev_err(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n", +			key_press_irq, err); +		return err;  	} -	pwrkey->key_press_irq = key_press_irq; -	pwrkey->pwr = pwr; - -	platform_set_drvdata(pdev, pwrkey); - -	err = request_irq(key_press_irq, pwrkey_press_irq, -		IRQF_TRIGGER_RISING, "pmic8xxx_pwrkey_press", pwrkey); -	if (err < 0) { -		dev_dbg(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n", -				 key_press_irq, err); -		goto unreg_input_dev; +	err = devm_request_irq(&pdev->dev, key_release_irq, pwrkey_release_irq, +			       IRQF_TRIGGER_RISING, +			       "pmic8xxx_pwrkey_release", pwr); +	if (err) { +		dev_err(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n", +			key_release_irq, err); +		return err;  	} -	err = request_irq(key_release_irq, pwrkey_release_irq, -		 IRQF_TRIGGER_RISING, "pmic8xxx_pwrkey_release", pwrkey); -	if (err < 0) { -		dev_dbg(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n", -				 key_release_irq, err); - -		goto free_press_irq; +	err = input_register_device(pwr); +	if (err) { +		dev_err(&pdev->dev, "Can't register power key: %d\n", err); +		return err;  	} -	device_init_wakeup(&pdev->dev, pdata->wakeup); +	platform_set_drvdata(pdev, pwrkey); +	device_init_wakeup(&pdev->dev, 1);  	return 0; - -free_press_irq: -	free_irq(key_press_irq, pwrkey); -unreg_input_dev: -	input_unregister_device(pwr); -	pwr = NULL; -free_input_dev: -	input_free_device(pwr); -free_pwrkey: -	kfree(pwrkey); -	return err;  }  static int pmic8xxx_pwrkey_remove(struct platform_device *pdev)  { -	struct pmic8xxx_pwrkey *pwrkey = platform_get_drvdata(pdev); -	int key_release_irq = platform_get_irq(pdev, 0); -	int key_press_irq = platform_get_irq(pdev, 1); -  	device_init_wakeup(&pdev->dev, 0); -	free_irq(key_press_irq, pwrkey); -	free_irq(key_release_irq, pwrkey); -	input_unregister_device(pwrkey->pwr); -	kfree(pwrkey); -  	return 0;  } +static const struct of_device_id pm8xxx_pwr_key_id_table[] = { +	{ .compatible = "qcom,pm8058-pwrkey" }, +	{ .compatible = "qcom,pm8921-pwrkey" }, +	{ } +}; +MODULE_DEVICE_TABLE(of, pm8xxx_pwr_key_id_table); +  static struct platform_driver pmic8xxx_pwrkey_driver = {  	.probe		= pmic8xxx_pwrkey_probe,  	.remove		= pmic8xxx_pwrkey_remove,  	.driver		= { -		.name	= PM8XXX_PWRKEY_DEV_NAME, +		.name	= "pm8xxx-pwrkey",  		.owner	= THIS_MODULE,  		.pm	= &pm8xxx_pwr_key_pm_ops, +		.of_match_table = pm8xxx_pwr_key_id_table,  	},  };  module_platform_driver(pmic8xxx_pwrkey_driver); diff --git a/drivers/input/misc/powermate.c b/drivers/input/misc/powermate.c index 49c0c3ebd32..63b539d3dab 100644 --- a/drivers/input/misc/powermate.c +++ b/drivers/input/misc/powermate.c @@ -31,7 +31,6 @@  #include <linux/kernel.h>  #include <linux/slab.h>  #include <linux/module.h> -#include <linux/init.h>  #include <linux/spinlock.h>  #include <linux/usb/input.h> diff --git a/drivers/input/misc/pwm-beeper.c b/drivers/input/misc/pwm-beeper.c index 2ff4d1c78ab..8ef288e7c97 100644 --- a/drivers/input/misc/pwm-beeper.c +++ b/drivers/input/misc/pwm-beeper.c @@ -16,6 +16,7 @@  #include <linux/input.h>  #include <linux/module.h>  #include <linux/kernel.h> +#include <linux/of.h>  #include <linux/platform_device.h>  #include <linux/pwm.h>  #include <linux/slab.h> @@ -67,7 +68,7 @@ static int pwm_beeper_event(struct input_dev *input,  static int pwm_beeper_probe(struct platform_device *pdev)  { -	unsigned long pwm_id = (unsigned long)pdev->dev.platform_data; +	unsigned long pwm_id = (unsigned long)dev_get_platdata(&pdev->dev);  	struct pwm_beeper *beeper;  	int error; diff --git a/drivers/input/misc/rb532_button.c b/drivers/input/misc/rb532_button.c index fb4f8ac3343..83fff38b86b 100644 --- a/drivers/input/misc/rb532_button.c +++ b/drivers/input/misc/rb532_button.c @@ -87,7 +87,6 @@ static int rb532_button_remove(struct platform_device *pdev)  	input_unregister_polled_device(poll_dev);  	input_free_polled_device(poll_dev); -	dev_set_drvdata(&pdev->dev, NULL);  	return 0;  } diff --git a/drivers/input/misc/retu-pwrbutton.c b/drivers/input/misc/retu-pwrbutton.c index 7ca09baa001..4bff1aa9b0d 100644 --- a/drivers/input/misc/retu-pwrbutton.c +++ b/drivers/input/misc/retu-pwrbutton.c @@ -17,7 +17,6 @@   */  #include <linux/irq.h> -#include <linux/init.h>  #include <linux/slab.h>  #include <linux/errno.h>  #include <linux/input.h> diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c index 5b1aff82513..93558a1c7f7 100644 --- a/drivers/input/misc/rotary_encoder.c +++ b/drivers/input/misc/rotary_encoder.c @@ -16,7 +16,6 @@  #include <linux/kernel.h>  #include <linux/module.h> -#include <linux/init.h>  #include <linux/interrupt.h>  #include <linux/input.h>  #include <linux/device.h> @@ -24,6 +23,7 @@  #include <linux/gpio.h>  #include <linux/rotary_encoder.h>  #include <linux/slab.h> +#include <linux/of.h>  #include <linux/of_platform.h>  #include <linux/of_gpio.h> @@ -143,7 +143,7 @@ static irqreturn_t rotary_encoder_half_period_irq(int irq, void *dev_id)  }  #ifdef CONFIG_OF -static struct of_device_id rotary_encoder_of_match[] = { +static const struct of_device_id rotary_encoder_of_match[] = {  	{ .compatible = "rotary-encoder", },  	{ },  }; diff --git a/drivers/input/misc/sgi_btns.c b/drivers/input/misc/sgi_btns.c index 95cf299ef9a..f10474937a6 100644 --- a/drivers/input/misc/sgi_btns.c +++ b/drivers/input/misc/sgi_btns.c @@ -17,7 +17,6 @@   *  along with this program; if not, write to the Free Software   *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA   */ -#include <linux/init.h>  #include <linux/input-polldev.h>  #include <linux/ioport.h>  #include <linux/module.h> diff --git a/drivers/input/misc/sirfsoc-onkey.c b/drivers/input/misc/sirfsoc-onkey.c index 0621c367049..fed5102e180 100644 --- a/drivers/input/misc/sirfsoc-onkey.c +++ b/drivers/input/misc/sirfsoc-onkey.c @@ -1,29 +1,54 @@  /*   * Power key driver for SiRF PrimaII   * - * Copyright (c) 2013 Cambridge Silicon Radio Limited, a CSR plc group company. + * Copyright (c) 2013 - 2014 Cambridge Silicon Radio Limited, a CSR plc group + * company.   *   * Licensed under GPLv2 or later.   */  #include <linux/module.h> -#include <linux/init.h>  #include <linux/interrupt.h>  #include <linux/delay.h>  #include <linux/platform_device.h>  #include <linux/input.h>  #include <linux/rtc/sirfsoc_rtciobrg.h>  #include <linux/of.h> +#include <linux/workqueue.h>  struct sirfsoc_pwrc_drvdata {  	u32			pwrc_base;  	struct input_dev	*input; +	struct delayed_work	work;  };  #define PWRC_ON_KEY_BIT			(1 << 0)  #define PWRC_INT_STATUS			0xc  #define PWRC_INT_MASK			0x10 +#define PWRC_PIN_STATUS			0x14 +#define PWRC_KEY_DETECT_UP_TIME		20	/* ms*/ + +static int sirfsoc_pwrc_is_on_key_down(struct sirfsoc_pwrc_drvdata *pwrcdrv) +{ +	u32 state = sirfsoc_rtc_iobrg_readl(pwrcdrv->pwrc_base + +							PWRC_PIN_STATUS); +	return !(state & PWRC_ON_KEY_BIT); /* ON_KEY is active low */ +} + +static void sirfsoc_pwrc_report_event(struct work_struct *work) +{ +	struct sirfsoc_pwrc_drvdata *pwrcdrv = +		container_of(work, struct sirfsoc_pwrc_drvdata, work.work); + +	if (sirfsoc_pwrc_is_on_key_down(pwrcdrv)) { +		schedule_delayed_work(&pwrcdrv->work, +			msecs_to_jiffies(PWRC_KEY_DETECT_UP_TIME)); +	} else { +		input_event(pwrcdrv->input, EV_KEY, KEY_POWER, 0); +		input_sync(pwrcdrv->input); +	} +}  static irqreturn_t sirfsoc_pwrc_isr(int irq, void *dev_id)  { @@ -35,21 +60,44 @@ static irqreturn_t sirfsoc_pwrc_isr(int irq, void *dev_id)  	sirfsoc_rtc_iobrg_writel(int_status & ~PWRC_ON_KEY_BIT,  				 pwrcdrv->pwrc_base + PWRC_INT_STATUS); -	/* -	 * For a typical Linux system, we report KEY_SUSPEND to trigger apm-power.c -	 * to queue a SUSPEND APM event -	 */ -	input_event(pwrcdrv->input, EV_PWR, KEY_SUSPEND, 1); +	input_event(pwrcdrv->input, EV_KEY, KEY_POWER, 1);  	input_sync(pwrcdrv->input); - -	/* -	 * Todo: report KEY_POWER event for Android platforms, Android PowerManager -	 * will handle the suspend and powerdown/hibernation -	 */ +	schedule_delayed_work(&pwrcdrv->work, +			      msecs_to_jiffies(PWRC_KEY_DETECT_UP_TIME));  	return IRQ_HANDLED;  } +static void sirfsoc_pwrc_toggle_interrupts(struct sirfsoc_pwrc_drvdata *pwrcdrv, +					   bool enable) +{ +	u32 int_mask; + +	int_mask = sirfsoc_rtc_iobrg_readl(pwrcdrv->pwrc_base + PWRC_INT_MASK); +	if (enable) +		int_mask |= PWRC_ON_KEY_BIT; +	else +		int_mask &= ~PWRC_ON_KEY_BIT; +	sirfsoc_rtc_iobrg_writel(int_mask, pwrcdrv->pwrc_base + PWRC_INT_MASK); +} + +static int sirfsoc_pwrc_open(struct input_dev *input) +{ +	struct sirfsoc_pwrc_drvdata *pwrcdrv = input_get_drvdata(input); + +	sirfsoc_pwrc_toggle_interrupts(pwrcdrv, true); + +	return 0; +} + +static void sirfsoc_pwrc_close(struct input_dev *input) +{ +	struct sirfsoc_pwrc_drvdata *pwrcdrv = input_get_drvdata(input); + +	sirfsoc_pwrc_toggle_interrupts(pwrcdrv, false); +	cancel_delayed_work_sync(&pwrcdrv->work); +} +  static const struct of_device_id sirfsoc_pwrc_of_match[] = {  	{ .compatible = "sirf,prima2-pwrc" },  	{}, @@ -71,7 +119,7 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev)  	}  	/* -	 * we can't use of_iomap because pwrc is not mapped in memory, +	 * We can't use of_iomap because pwrc is not mapped in memory,  	 * the so-called base address is only offset in rtciobrg  	 */  	error = of_property_read_u32(np, "reg", &pwrcdrv->pwrc_base); @@ -87,11 +135,22 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev)  	pwrcdrv->input->name = "sirfsoc pwrckey";  	pwrcdrv->input->phys = "pwrc/input0"; -	pwrcdrv->input->evbit[0] = BIT_MASK(EV_PWR); +	pwrcdrv->input->evbit[0] = BIT_MASK(EV_KEY); +	input_set_capability(pwrcdrv->input, EV_KEY, KEY_POWER); + +	INIT_DELAYED_WORK(&pwrcdrv->work, sirfsoc_pwrc_report_event); + +	pwrcdrv->input->open = sirfsoc_pwrc_open; +	pwrcdrv->input->close = sirfsoc_pwrc_close; + +	input_set_drvdata(pwrcdrv->input, pwrcdrv); + +	/* Make sure the device is quiesced */ +	sirfsoc_pwrc_toggle_interrupts(pwrcdrv, false);  	irq = platform_get_irq(pdev, 0);  	error = devm_request_irq(&pdev->dev, irq, -				 sirfsoc_pwrc_isr, IRQF_SHARED, +				 sirfsoc_pwrc_isr, 0,  				 "sirfsoc_pwrc_int", pwrcdrv);  	if (error) {  		dev_err(&pdev->dev, "unable to claim irq %d, error: %d\n", @@ -99,11 +158,6 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev)  		return error;  	} -	sirfsoc_rtc_iobrg_writel( -		sirfsoc_rtc_iobrg_readl(pwrcdrv->pwrc_base + PWRC_INT_MASK) | -			PWRC_ON_KEY_BIT, -		pwrcdrv->pwrc_base + PWRC_INT_MASK); -  	error = input_register_device(pwrcdrv->input);  	if (error) {  		dev_err(&pdev->dev, @@ -112,7 +166,7 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev)  		return error;  	} -	platform_set_drvdata(pdev, pwrcdrv); +	dev_set_drvdata(&pdev->dev, pwrcdrv);  	device_init_wakeup(&pdev->dev, 1);  	return 0; @@ -126,25 +180,25 @@ static int sirfsoc_pwrc_remove(struct platform_device *pdev)  }  #ifdef CONFIG_PM_SLEEP -static int pwrc_resume(struct device *dev) +static int sirfsoc_pwrc_resume(struct device *dev)  { -	struct platform_device *pdev = to_platform_device(dev); -	struct sirfsoc_pwrc_drvdata *pwrcdrv = platform_get_drvdata(pdev); +	struct sirfsoc_pwrc_drvdata *pwrcdrv = dev_get_drvdata(dev); +	struct input_dev *input = pwrcdrv->input;  	/*  	 * Do not mask pwrc interrupt as we want pwrc work as a wakeup source  	 * if users touch X_ONKEY_B, see arch/arm/mach-prima2/pm.c  	 */ -	sirfsoc_rtc_iobrg_writel( -		sirfsoc_rtc_iobrg_readl( -		pwrcdrv->pwrc_base + PWRC_INT_MASK) | PWRC_ON_KEY_BIT, -		pwrcdrv->pwrc_base + PWRC_INT_MASK); +	mutex_lock(&input->mutex); +	if (input->users) +		sirfsoc_pwrc_toggle_interrupts(pwrcdrv, true); +	mutex_unlock(&input->mutex);  	return 0;  }  #endif -static SIMPLE_DEV_PM_OPS(sirfsoc_pwrc_pm_ops, NULL, pwrc_resume); +static SIMPLE_DEV_PM_OPS(sirfsoc_pwrc_pm_ops, NULL, sirfsoc_pwrc_resume);  static struct platform_driver sirfsoc_pwrc_driver = {  	.probe		= sirfsoc_pwrc_probe, @@ -153,13 +207,13 @@ static struct platform_driver sirfsoc_pwrc_driver = {  		.name	= "sirfsoc-pwrc",  		.owner	= THIS_MODULE,  		.pm	= &sirfsoc_pwrc_pm_ops, -		.of_match_table = of_match_ptr(sirfsoc_pwrc_of_match), +		.of_match_table = sirfsoc_pwrc_of_match,  	}  };  module_platform_driver(sirfsoc_pwrc_driver); -MODULE_LICENSE("GPLv2"); +MODULE_LICENSE("GPL v2");  MODULE_AUTHOR("Binghua Duan <Binghua.Duan@csr.com>, Xianglong Du <Xianglong.Du@csr.com>");  MODULE_DESCRIPTION("CSR Prima2 PWRC Driver");  MODULE_ALIAS("platform:sirfsoc-pwrc"); diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c new file mode 100644 index 00000000000..5a6334be30b --- /dev/null +++ b/drivers/input/misc/soc_button_array.c @@ -0,0 +1,218 @@ +/* + * Supports for the button array on SoC tablets originally running + * Windows 8. + * + * (C) Copyright 2014 Intel Corporation + * + * 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; version 2 + * of the License. + */ + +#include <linux/module.h> +#include <linux/input.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/acpi.h> +#include <linux/gpio/consumer.h> +#include <linux/gpio_keys.h> +#include <linux/platform_device.h> +#include <linux/pnp.h> + +/* + * Definition of buttons on the tablet. The ACPI index of each button + * is defined in section 2.8.7.2 of "Windows ACPI Design Guide for SoC + * Platforms" + */ +#define MAX_NBUTTONS	5 + +struct soc_button_info { +	const char *name; +	int acpi_index; +	unsigned int event_type; +	unsigned int event_code; +	bool autorepeat; +	bool wakeup; +}; + +/* + * Some of the buttons like volume up/down are auto repeat, while others + * are not. To support both, we register two platform devices, and put + * buttons into them based on whether the key should be auto repeat. + */ +#define BUTTON_TYPES	2 + +struct soc_button_data { +	struct platform_device *children[BUTTON_TYPES]; +}; + +/* + * Get the Nth GPIO number from the ACPI object. + */ +static int soc_button_lookup_gpio(struct device *dev, int acpi_index) +{ +	struct gpio_desc *desc; +	int gpio; + +	desc = gpiod_get_index(dev, KBUILD_MODNAME, acpi_index); +	if (IS_ERR(desc)) +		return PTR_ERR(desc); + +	gpio = desc_to_gpio(desc); + +	gpiod_put(desc); + +	return gpio; +} + +static struct platform_device * +soc_button_device_create(struct pnp_dev *pdev, +			 const struct soc_button_info *button_info, +			 bool autorepeat) +{ +	const struct soc_button_info *info; +	struct platform_device *pd; +	struct gpio_keys_button *gpio_keys; +	struct gpio_keys_platform_data *gpio_keys_pdata; +	int n_buttons = 0; +	int gpio; +	int error; + +	gpio_keys_pdata = devm_kzalloc(&pdev->dev, +				       sizeof(*gpio_keys_pdata) + +					sizeof(*gpio_keys) * MAX_NBUTTONS, +				       GFP_KERNEL); +	gpio_keys = (void *)(gpio_keys_pdata + 1); + +	for (info = button_info; info->name; info++) { +		if (info->autorepeat != autorepeat) +			continue; + +		gpio = soc_button_lookup_gpio(&pdev->dev, info->acpi_index); +		if (gpio < 0) +			continue; + +		gpio_keys[n_buttons].type = info->event_type; +		gpio_keys[n_buttons].code = info->event_code; +		gpio_keys[n_buttons].gpio = gpio; +		gpio_keys[n_buttons].active_low = 1; +		gpio_keys[n_buttons].desc = info->name; +		gpio_keys[n_buttons].wakeup = info->wakeup; +		n_buttons++; +	} + +	if (n_buttons == 0) { +		error = -ENODEV; +		goto err_free_mem; +	} + +	gpio_keys_pdata->buttons = gpio_keys; +	gpio_keys_pdata->nbuttons = n_buttons; +	gpio_keys_pdata->rep = autorepeat; + +	pd = platform_device_alloc("gpio-keys", PLATFORM_DEVID_AUTO); +	if (!pd) { +		error = -ENOMEM; +		goto err_free_mem; +	} + +	error = platform_device_add_data(pd, gpio_keys_pdata, +					 sizeof(*gpio_keys_pdata)); +	if (error) +		goto err_free_pdev; + +	error = platform_device_add(pd); +	if (error) +		goto err_free_pdev; + +	return pd; + +err_free_pdev: +	platform_device_put(pd); +err_free_mem: +	devm_kfree(&pdev->dev, gpio_keys_pdata); +	return ERR_PTR(error); +} + +static void soc_button_remove(struct pnp_dev *pdev) +{ +	struct soc_button_data *priv = pnp_get_drvdata(pdev); +	int i; + +	for (i = 0; i < BUTTON_TYPES; i++) +		if (priv->children[i]) +			platform_device_unregister(priv->children[i]); +} + +static int soc_button_pnp_probe(struct pnp_dev *pdev, +				const struct pnp_device_id *id) +{ +	const struct soc_button_info *button_info = (void *)id->driver_data; +	struct soc_button_data *priv; +	struct platform_device *pd; +	int i; +	int error; + +	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); +	if (!priv) +		return -ENOMEM; + +	pnp_set_drvdata(pdev, priv); + +	for (i = 0; i < BUTTON_TYPES; i++) { +		pd = soc_button_device_create(pdev, button_info, i == 0); +		if (IS_ERR(pd)) { +			error = PTR_ERR(pd); +			if (error != -ENODEV) { +				soc_button_remove(pdev); +				return error; +			} +			continue; +		} + +		priv->children[i] = pd; +	} + +	if (!priv->children[0] && !priv->children[1]) +		return -ENODEV; + +	return 0; +} + +static struct soc_button_info soc_button_PNP0C40[] = { +	{ "power", 0, EV_KEY, KEY_POWER, false, true }, +	{ "home", 1, EV_KEY, KEY_HOME, false, true }, +	{ "volume_up", 2, EV_KEY, KEY_VOLUMEUP, true, false }, +	{ "volume_down", 3, EV_KEY, KEY_VOLUMEDOWN, true, false }, +	{ "rotation_lock", 4, EV_SW, SW_ROTATE_LOCK, false, false }, +	{ } +}; + +static const struct pnp_device_id soc_button_pnp_match[] = { +	{ .id = "PNP0C40", .driver_data = (long)soc_button_PNP0C40 }, +	{ .id = "" } +}; +MODULE_DEVICE_TABLE(pnp, soc_button_pnp_match); + +static struct pnp_driver soc_button_pnp_driver = { +	.name		= KBUILD_MODNAME, +	.id_table	= soc_button_pnp_match, +	.probe          = soc_button_pnp_probe, +	.remove		= soc_button_remove, +}; + +static int __init soc_button_init(void) +{ +	return pnp_register_driver(&soc_button_pnp_driver); +} + +static void __exit soc_button_exit(void) +{ +	pnp_unregister_driver(&soc_button_pnp_driver); +} + +module_init(soc_button_init); +module_exit(soc_button_exit); + +MODULE_LICENSE("GPL"); diff --git a/drivers/input/misc/twl4030-pwrbutton.c b/drivers/input/misc/twl4030-pwrbutton.c index b9a05fda03e..fb3b63b2f85 100644 --- a/drivers/input/misc/twl4030-pwrbutton.c +++ b/drivers/input/misc/twl4030-pwrbutton.c @@ -52,15 +52,15 @@ static irqreturn_t powerbutton_irq(int irq, void *_pwr)  	return IRQ_HANDLED;  } -static int __init twl4030_pwrbutton_probe(struct platform_device *pdev) +static int twl4030_pwrbutton_probe(struct platform_device *pdev)  {  	struct input_dev *pwr;  	int irq = platform_get_irq(pdev, 0);  	int err; -	pwr = input_allocate_device(); +	pwr = devm_input_allocate_device(&pdev->dev);  	if (!pwr) { -		dev_dbg(&pdev->dev, "Can't allocate power button\n"); +		dev_err(&pdev->dev, "Can't allocate power button\n");  		return -ENOMEM;  	} @@ -70,52 +70,42 @@ static int __init twl4030_pwrbutton_probe(struct platform_device *pdev)  	pwr->phys = "twl4030_pwrbutton/input0";  	pwr->dev.parent = &pdev->dev; -	err = request_threaded_irq(irq, NULL, powerbutton_irq, +	err = devm_request_threaded_irq(&pwr->dev, irq, NULL, powerbutton_irq,  			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,  			"twl4030_pwrbutton", pwr);  	if (err < 0) { -		dev_dbg(&pdev->dev, "Can't get IRQ for pwrbutton: %d\n", err); -		goto free_input_dev; +		dev_err(&pdev->dev, "Can't get IRQ for pwrbutton: %d\n", err); +		return err;  	}  	err = input_register_device(pwr);  	if (err) { -		dev_dbg(&pdev->dev, "Can't register power button: %d\n", err); -		goto free_irq; +		dev_err(&pdev->dev, "Can't register power button: %d\n", err); +		return err;  	}  	platform_set_drvdata(pdev, pwr);  	return 0; - -free_irq: -	free_irq(irq, pwr); -free_input_dev: -	input_free_device(pwr); -	return err;  } -static int __exit twl4030_pwrbutton_remove(struct platform_device *pdev) -{ -	struct input_dev *pwr = platform_get_drvdata(pdev); -	int irq = platform_get_irq(pdev, 0); - -	free_irq(irq, pwr); -	input_unregister_device(pwr); - -	return 0; -} +#ifdef CONFIG_OF +static const struct of_device_id twl4030_pwrbutton_dt_match_table[] = { +       { .compatible = "ti,twl4030-pwrbutton" }, +       {}, +}; +MODULE_DEVICE_TABLE(of, twl4030_pwrbutton_dt_match_table); +#endif  static struct platform_driver twl4030_pwrbutton_driver = { -	.remove		= __exit_p(twl4030_pwrbutton_remove), +	.probe		= twl4030_pwrbutton_probe,  	.driver		= {  		.name	= "twl4030_pwrbutton",  		.owner	= THIS_MODULE, +		.of_match_table = of_match_ptr(twl4030_pwrbutton_dt_match_table),  	},  }; - -module_platform_driver_probe(twl4030_pwrbutton_driver, -			twl4030_pwrbutton_probe); +module_platform_driver(twl4030_pwrbutton_driver);  MODULE_ALIAS("platform:twl4030_pwrbutton");  MODULE_DESCRIPTION("Triton2 Power Button"); diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c index 68a5f33152a..960ef2a7091 100644 --- a/drivers/input/misc/twl4030-vibra.c +++ b/drivers/input/misc/twl4030-vibra.c @@ -185,15 +185,17 @@ static bool twl4030_vibra_check_coexist(struct twl4030_vibra_data *pdata,  	if (pdata && pdata->coexist)  		return true; -	if (of_find_node_by_name(node, "codec")) +	if (of_find_node_by_name(node, "codec")) { +		of_node_put(node);  		return true; +	}  	return false;  }  static int twl4030_vibra_probe(struct platform_device *pdev)  { -	struct twl4030_vibra_data *pdata = pdev->dev.platform_data; +	struct twl4030_vibra_data *pdata = dev_get_platdata(&pdev->dev);  	struct device_node *twl4030_core_node = pdev->dev.parent->of_node;  	struct vibra_info *info;  	int ret; diff --git a/drivers/input/misc/twl6040-vibra.c b/drivers/input/misc/twl6040-vibra.c index 7864b0c3ebb..6d26eecc278 100644 --- a/drivers/input/misc/twl6040-vibra.c +++ b/drivers/input/misc/twl6040-vibra.c @@ -258,17 +258,14 @@ static SIMPLE_DEV_PM_OPS(twl6040_vibra_pm_ops, twl6040_vibra_suspend, NULL);  static int twl6040_vibra_probe(struct platform_device *pdev)  {  	struct device *twl6040_core_dev = pdev->dev.parent; -	struct device_node *twl6040_core_node = NULL; +	struct device_node *twl6040_core_node;  	struct vibra_info *info;  	int vddvibl_uV = 0;  	int vddvibr_uV = 0; -	int ret; +	int error; -#ifdef CONFIG_OF  	twl6040_core_node = of_find_node_by_name(twl6040_core_dev->of_node,  						 "vibra"); -#endif -  	if (!twl6040_core_node) {  		dev_err(&pdev->dev, "parent of node is missing?\n");  		return -EINVAL; @@ -276,6 +273,7 @@ static int twl6040_vibra_probe(struct platform_device *pdev)  	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);  	if (!info) { +		of_node_put(twl6040_core_node);  		dev_err(&pdev->dev, "couldn't allocate memory\n");  		return -ENOMEM;  	} @@ -295,6 +293,8 @@ static int twl6040_vibra_probe(struct platform_device *pdev)  	of_property_read_u32(twl6040_core_node, "ti,vddvibl-uV", &vddvibl_uV);  	of_property_read_u32(twl6040_core_node, "ti,vddvibr-uV", &vddvibr_uV); +	of_node_put(twl6040_core_node); +  	if ((!info->vibldrv_res && !info->viblmotor_res) ||  	    (!info->vibrdrv_res && !info->vibrmotor_res)) {  		dev_err(info->dev, "invalid vibra driver/motor resistance\n"); @@ -309,12 +309,12 @@ static int twl6040_vibra_probe(struct platform_device *pdev)  	mutex_init(&info->mutex); -	ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL, -					twl6040_vib_irq_handler, 0, -					"twl6040_irq_vib", info); -	if (ret) { -		dev_err(info->dev, "VIB IRQ request failed: %d\n", ret); -		return ret; +	error = devm_request_threaded_irq(&pdev->dev, info->irq, NULL, +					  twl6040_vib_irq_handler, 0, +					  "twl6040_irq_vib", info); +	if (error) { +		dev_err(info->dev, "VIB IRQ request failed: %d\n", error); +		return error;  	}  	info->supplies[0].supply = "vddvibl"; @@ -323,40 +323,40 @@ static int twl6040_vibra_probe(struct platform_device *pdev)  	 * When booted with Device tree the regulators are attached to the  	 * parent device (twl6040 MFD core)  	 */ -	ret = regulator_bulk_get(twl6040_core_dev, ARRAY_SIZE(info->supplies), -				 info->supplies); -	if (ret) { -		dev_err(info->dev, "couldn't get regulators %d\n", ret); -		return ret; +	error = devm_regulator_bulk_get(twl6040_core_dev, +					ARRAY_SIZE(info->supplies), +					info->supplies); +	if (error) { +		dev_err(info->dev, "couldn't get regulators %d\n", error); +		return error;  	}  	if (vddvibl_uV) { -		ret = regulator_set_voltage(info->supplies[0].consumer, -					    vddvibl_uV, vddvibl_uV); -		if (ret) { +		error = regulator_set_voltage(info->supplies[0].consumer, +					      vddvibl_uV, vddvibl_uV); +		if (error) {  			dev_err(info->dev, "failed to set VDDVIBL volt %d\n", -				ret); -			goto err_regulator; +				error); +			return error;  		}  	}  	if (vddvibr_uV) { -		ret = regulator_set_voltage(info->supplies[1].consumer, -					    vddvibr_uV, vddvibr_uV); -		if (ret) { +		error = regulator_set_voltage(info->supplies[1].consumer, +					      vddvibr_uV, vddvibr_uV); +		if (error) {  			dev_err(info->dev, "failed to set VDDVIBR volt %d\n", -				ret); -			goto err_regulator; +				error); +			return error;  		}  	}  	INIT_WORK(&info->play_work, vibra_play_work); -	info->input_dev = input_allocate_device(); -	if (info->input_dev == NULL) { +	info->input_dev = devm_input_allocate_device(&pdev->dev); +	if (!info->input_dev) {  		dev_err(info->dev, "couldn't allocate input device\n"); -		ret = -ENOMEM; -		goto err_regulator; +		return -ENOMEM;  	}  	input_set_drvdata(info->input_dev, info); @@ -367,44 +367,25 @@ static int twl6040_vibra_probe(struct platform_device *pdev)  	info->input_dev->close = twl6040_vibra_close;  	__set_bit(FF_RUMBLE, info->input_dev->ffbit); -	ret = input_ff_create_memless(info->input_dev, NULL, vibra_play); -	if (ret < 0) { +	error = input_ff_create_memless(info->input_dev, NULL, vibra_play); +	if (error) {  		dev_err(info->dev, "couldn't register vibrator to FF\n"); -		goto err_ialloc; +		return error;  	} -	ret = input_register_device(info->input_dev); -	if (ret < 0) { +	error = input_register_device(info->input_dev); +	if (error) {  		dev_err(info->dev, "couldn't register input device\n"); -		goto err_iff; +		return error;  	}  	platform_set_drvdata(pdev, info);  	return 0; - -err_iff: -	input_ff_destroy(info->input_dev); -err_ialloc: -	input_free_device(info->input_dev); -err_regulator: -	regulator_bulk_free(ARRAY_SIZE(info->supplies), info->supplies); -	return ret; -} - -static int twl6040_vibra_remove(struct platform_device *pdev) -{ -	struct vibra_info *info = platform_get_drvdata(pdev); - -	input_unregister_device(info->input_dev); -	regulator_bulk_free(ARRAY_SIZE(info->supplies), info->supplies); - -	return 0;  }  static struct platform_driver twl6040_vibra_driver = {  	.probe		= twl6040_vibra_probe, -	.remove		= twl6040_vibra_remove,  	.driver		= {  		.name	= "twl6040-vibra",  		.owner	= THIS_MODULE, diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index a0a4bbaef02..85693624750 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -20,6 +20,8 @@   * Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>   *   * Changes/Revisions: + *	0.4	01/09/2014 (Benjamin Tissoires <benjamin.tissoires@redhat.com>) + *		- add UI_GET_SYSNAME ioctl   *	0.3	09/04/2006 (Anssi Hannula <anssi.hannula@gmail.com>)   *		- updated ff support for the changes in kernel interface   *		- added MODULE_VERSION @@ -430,20 +432,30 @@ static int uinput_setup_device(struct uinput_device *udev,  	return retval;  } -static ssize_t uinput_inject_event(struct uinput_device *udev, -				   const char __user *buffer, size_t count) +static ssize_t uinput_inject_events(struct uinput_device *udev, +				    const char __user *buffer, size_t count)  {  	struct input_event ev; +	size_t bytes = 0; -	if (count < input_event_size()) +	if (count != 0 && count < input_event_size())  		return -EINVAL; -	if (input_event_from_user(buffer, &ev)) -		return -EFAULT; +	while (bytes + input_event_size() <= count) { +		/* +		 * Note that even if some events were fetched successfully +		 * we are still going to return EFAULT instead of partial +		 * count to let userspace know that it got it's buffers +		 * all wrong. +		 */ +		if (input_event_from_user(buffer + bytes, &ev)) +			return -EFAULT; -	input_event(udev->dev, ev.type, ev.code, ev.value); +		input_event(udev->dev, ev.type, ev.code, ev.value); +		bytes += input_event_size(); +	} -	return input_event_size(); +	return bytes;  }  static ssize_t uinput_write(struct file *file, const char __user *buffer, @@ -460,7 +472,7 @@ static ssize_t uinput_write(struct file *file, const char __user *buffer,  		return retval;  	retval = udev->state == UIST_CREATED ? -			uinput_inject_event(udev, buffer, count) : +			uinput_inject_events(udev, buffer, count) :  			uinput_setup_device(udev, buffer, count);  	mutex_unlock(&udev->mutex); @@ -660,6 +672,31 @@ static int uinput_ff_upload_from_user(const char __user *buffer,  	__ret;						\  }) +static int uinput_str_to_user(void __user *dest, const char *str, +			      unsigned int maxlen) +{ +	char __user *p = dest; +	int len, ret; + +	if (!str) +		return -ENOENT; + +	if (maxlen == 0) +		return -EINVAL; + +	len = strlen(str) + 1; +	if (len > maxlen) +		len = maxlen; + +	ret = copy_to_user(p, str, len); +	if (ret) +		return -EFAULT; + +	/* force terminating '\0' */ +	ret = put_user(0, p + len - 1); +	return ret ? -EFAULT : len; +} +  static long uinput_ioctl_handler(struct file *file, unsigned int cmd,  				 unsigned long arg, void __user *p)  { @@ -669,6 +706,8 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,  	struct uinput_ff_erase  ff_erase;  	struct uinput_request   *req;  	char			*phys; +	const char		*name; +	unsigned int		size;  	retval = mutex_lock_interruptible(&udev->mutex);  	if (retval) @@ -683,51 +722,51 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,  	switch (cmd) {  		case UI_DEV_CREATE:  			retval = uinput_create_device(udev); -			break; +			goto out;  		case UI_DEV_DESTROY:  			uinput_destroy_device(udev); -			break; +			goto out;  		case UI_SET_EVBIT:  			retval = uinput_set_bit(arg, evbit, EV_MAX); -			break; +			goto out;  		case UI_SET_KEYBIT:  			retval = uinput_set_bit(arg, keybit, KEY_MAX); -			break; +			goto out;  		case UI_SET_RELBIT:  			retval = uinput_set_bit(arg, relbit, REL_MAX); -			break; +			goto out;  		case UI_SET_ABSBIT:  			retval = uinput_set_bit(arg, absbit, ABS_MAX); -			break; +			goto out;  		case UI_SET_MSCBIT:  			retval = uinput_set_bit(arg, mscbit, MSC_MAX); -			break; +			goto out;  		case UI_SET_LEDBIT:  			retval = uinput_set_bit(arg, ledbit, LED_MAX); -			break; +			goto out;  		case UI_SET_SNDBIT:  			retval = uinput_set_bit(arg, sndbit, SND_MAX); -			break; +			goto out;  		case UI_SET_FFBIT:  			retval = uinput_set_bit(arg, ffbit, FF_MAX); -			break; +			goto out;  		case UI_SET_SWBIT:  			retval = uinput_set_bit(arg, swbit, SW_MAX); -			break; +			goto out;  		case UI_SET_PROPBIT:  			retval = uinput_set_bit(arg, propbit, INPUT_PROP_MAX); -			break; +			goto out;  		case UI_SET_PHYS:  			if (udev->state == UIST_CREATED) { @@ -743,18 +782,18 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,  			kfree(udev->dev->phys);  			udev->dev->phys = phys; -			break; +			goto out;  		case UI_BEGIN_FF_UPLOAD:  			retval = uinput_ff_upload_from_user(p, &ff_up);  			if (retval) -				break; +				goto out;  			req = uinput_request_find(udev, ff_up.request_id);  			if (!req || req->code != UI_FF_UPLOAD ||  			    !req->u.upload.effect) {  				retval = -EINVAL; -				break; +				goto out;  			}  			ff_up.retval = 0; @@ -765,65 +804,77 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,  				memset(&ff_up.old, 0, sizeof(struct ff_effect));  			retval = uinput_ff_upload_to_user(p, &ff_up); -			break; +			goto out;  		case UI_BEGIN_FF_ERASE:  			if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) {  				retval = -EFAULT; -				break; +				goto out;  			}  			req = uinput_request_find(udev, ff_erase.request_id);  			if (!req || req->code != UI_FF_ERASE) {  				retval = -EINVAL; -				break; +				goto out;  			}  			ff_erase.retval = 0;  			ff_erase.effect_id = req->u.effect_id;  			if (copy_to_user(p, &ff_erase, sizeof(ff_erase))) {  				retval = -EFAULT; -				break; +				goto out;  			} -			break; +			goto out;  		case UI_END_FF_UPLOAD:  			retval = uinput_ff_upload_from_user(p, &ff_up);  			if (retval) -				break; +				goto out;  			req = uinput_request_find(udev, ff_up.request_id);  			if (!req || req->code != UI_FF_UPLOAD ||  			    !req->u.upload.effect) {  				retval = -EINVAL; -				break; +				goto out;  			}  			req->retval = ff_up.retval;  			uinput_request_done(udev, req); -			break; +			goto out;  		case UI_END_FF_ERASE:  			if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) {  				retval = -EFAULT; -				break; +				goto out;  			}  			req = uinput_request_find(udev, ff_erase.request_id);  			if (!req || req->code != UI_FF_ERASE) {  				retval = -EINVAL; -				break; +				goto out;  			}  			req->retval = ff_erase.retval;  			uinput_request_done(udev, req); -			break; +			goto out; +	} -		default: -			retval = -EINVAL; +	size = _IOC_SIZE(cmd); + +	/* Now check variable-length commands */ +	switch (cmd & ~IOCSIZE_MASK) { +	case UI_GET_SYSNAME(0): +		if (udev->state != UIST_CREATED) { +			retval = -ENOENT; +			goto out; +		} +		name = dev_name(&udev->dev->dev); +		retval = uinput_str_to_user(p, name, size); +		goto out;  	} +	retval = -EINVAL;   out:  	mutex_unlock(&udev->mutex);  	return retval; diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index b6505454bcc..7b7add5061a 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c @@ -277,6 +277,16 @@ static struct key_entry keymap_fs_amilo_pro_v3505[] __initdata = {  	{ KE_END,       0 }  }; +static struct key_entry keymap_fs_amilo_pro_v8210[] __initdata = { +	{ KE_KEY,       0x01, {KEY_HELP} },          /* Fn+F1 */ +	{ KE_KEY,       0x06, {KEY_DISPLAYTOGGLE} }, /* Fn+F4 */ +	{ KE_BLUETOOTH, 0x30 },                      /* Fn+F10 */ +	{ KE_KEY,       0x31, {KEY_MAIL} },          /* mail button */ +	{ KE_KEY,       0x36, {KEY_WWW} },           /* www button */ +	{ KE_WIFI,      0x78 },                      /* satelite dish button */ +	{ KE_END,       FE_WIFI_LED } +}; +  static struct key_entry keymap_fujitsu_n3510[] __initdata = {  	{ KE_KEY, 0x11, {KEY_PROG1} },  	{ KE_KEY, 0x12, {KEY_PROG2} }, @@ -654,6 +664,15 @@ static const struct dmi_system_id dmi_ids[] __initconst = {  		.driver_data = keymap_fs_amilo_pro_v3505  	},  	{ +		/* Fujitsu-Siemens Amilo Pro Edition V8210 */ +		.callback = dmi_matched, +		.matches = { +			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), +			DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro Series V8210"), +		}, +		.driver_data = keymap_fs_amilo_pro_v8210 +	}, +	{  		/* Fujitsu-Siemens Amilo M7400 */  		.callback = dmi_matched,  		.matches = { diff --git a/drivers/input/misc/wm831x-on.c b/drivers/input/misc/wm831x-on.c index caa2c4068f0..173b6dcca0d 100644 --- a/drivers/input/misc/wm831x-on.c +++ b/drivers/input/misc/wm831x-on.c @@ -18,7 +18,6 @@   */  #include <linux/module.h> -#include <linux/init.h>  #include <linux/slab.h>  #include <linux/kernel.h>  #include <linux/errno.h> diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c index e21c1816a8f..fbfdc10573b 100644 --- a/drivers/input/misc/xen-kbdfront.c +++ b/drivers/input/misc/xen-kbdfront.c @@ -29,6 +29,7 @@  #include <xen/interface/io/fbif.h>  #include <xen/interface/io/kbdif.h>  #include <xen/xenbus.h> +#include <xen/platform_pci.h>  struct xenkbd_info {  	struct input_dev *kbd; @@ -380,6 +381,9 @@ static int __init xenkbd_init(void)  	if (xen_initial_domain())  		return -ENODEV; +	if (!xen_has_pv_devices()) +		return -ENODEV; +  	return xenbus_register_frontend(&xenkbd_driver);  } diff --git a/drivers/input/misc/yealink.c b/drivers/input/misc/yealink.c index 285a5bd6cbc..79c964c075f 100644 --- a/drivers/input/misc/yealink.c +++ b/drivers/input/misc/yealink.c @@ -47,7 +47,6 @@   */  #include <linux/kernel.h> -#include <linux/init.h>  #include <linux/slab.h>  #include <linux/module.h>  #include <linux/rwsem.h>  | 
