Linux Input/HID development
 help / color / mirror / Atom feed
* [git pull] Input updates for 3.17-rc0 (part 2)
From: Dmitry Torokhov @ 2014-09-03 23:47 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-kernel, linux-input

[-- Attachment #1: Type: text/plain, Size: 1331 bytes --]

Hi Linus,

Please pull from:

	git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git for-linus
or
	master.kernel.org:/pub/scm/linux/kernel/git/dtor/input.git for-linus

to receive updates for the input subsystem. You will get a fix for MT
breakage, enhancement to Elantech PS/2 driver and a couple of assorted
fixes.

Changelog:
---------

Dmitry Torokhov (2):
      Input: fix used slots detection breakage
      Input: ALPS - suppress message about 'Unknown touchpad'

Nick Dyer (1):
      Input: atmel_mxt_ts - improve description of gpio-keymap property

Ulrik De Bie (2):
      Input: elantech - reset the device when elantech probe fails
      Input: elantech - add support for trackpoint found on some v3 models

Vincent Stehlé (1):
      Input: sparc - i8042-sparcio.h: fix unused kbd_res warning


Diffstat:
--------

 .../devicetree/bindings/input/atmel,maxtouch.txt   |  11 ++
 drivers/input/input-mt.c                           |  30 +++--
 drivers/input/mouse/alps.c                         |   4 +-
 drivers/input/mouse/elantech.c                     | 137 +++++++++++++++++++--
 drivers/input/mouse/elantech.h                     |   3 +
 drivers/input/serio/i8042-sparcio.h                |   3 +-
 6 files changed, 164 insertions(+), 24 deletions(-)

-- 
Dmitry


[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply

* Re: [PATCH v2 7/7] Input: cros_ec_keyb: Optimize ghosting algorithm.
From: Dmitry Torokhov @ 2014-09-04  0:06 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: Lee Jones, Wolfram Sang, Doug Anderson, Simon Glass,
	Bill Richardson, Andrew Bresticker, Derek Basehore, Todd Broch,
	Olof Johansson, linux-i2c, linux-input, linux-samsung-soc
In-Reply-To: <1408974008-17184-8-git-send-email-javier.martinez@collabora.co.uk>

On Mon, Aug 25, 2014 at 03:40:08PM +0200, Javier Martinez Canillas wrote:
> From: Todd Broch <tbroch@chromium.org>
> 
> Previous algorithm was a bit conservative and complicating with
> respect to identifying key ghosting.  This CL uses the bitops hamming
> weight function (hweight8) to count the number of matching rows for
> colM & colN.  If that number is > 1 ghosting is present.
> 
> Additionally it removes NULL keys and our one virtual keypress
> KEY_BATTERY from consideration as these inputs are never physical
> keypresses.
> 
> Signed-off-by: Todd Broch <tbroch@chromium.org>
> Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
> Reviewed-by: Luigi Semenzato <semenzato@chromium.org>
> Tested-by: Andreas Färber <afaerber@suse.de>
> Signed-off-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk>

Applied, thank you.

-- 
Dmitry

^ permalink raw reply

* Re: hid-thingm: kernel panic on remove
From: Dylan Alex Simon @ 2014-09-04  1:05 UTC (permalink / raw)
  To: Jiri Kosina; +Cc: Benjamin Tissoires, linux-input
In-Reply-To: <alpine.LNX.2.00.1409031636170.12309@pobox.suse.cz>

>From Jiri Kosina <jkosina@suse.cz>, Wed, Sep 03, 2014 at 04:37:05PM +0200:
> On Wed, 3 Sep 2014, Dylan Alex Simon wrote:
> 
> > I think that did the trick.  I've run through the whole cycle about 20 times
> > in various conditions, and it seems solid so far.  Thanks!
> 
> Thanks. I actually think that the minimal necessary fix is below. Could 
> you please do a (hopefully last) round of testing with just this patch 
> applied?
> 
> diff --git a/drivers/hid/hid-thingm.c b/drivers/hid/hid-thingm.c
> index 134be89..c1d21fa 100644
> --- a/drivers/hid/hid-thingm.c
> +++ b/drivers/hid/hid-thingm.c
> @@ -208,10 +208,10 @@ unregister_red:
>  
>  static void thingm_remove_rgb(struct thingm_rgb *rgb)
>  {
> -	flush_work(&rgb->work);
>  	led_classdev_unregister(&rgb->red.ldev);
>  	led_classdev_unregister(&rgb->green.ldev);
>  	led_classdev_unregister(&rgb->blue.ldev);
> +	flush_work(&rgb->work);
>  }
>  
>  static int thingm_probe(struct hid_device *hdev, const struct hid_device_id *id)
> 

(Sorry, didn't get a chance back at the machine until now.)  This seems to be
working fine, as well.  I now do get the "failed to write color" messages
again when unplugging, which didn't show up with the other patch, but no
panics.

^ permalink raw reply

* Re: [PATCH] HID: hid-sensor-hub: Adding USB_DEVICE_ID_STM_HID_SENSOR device id
From: Jiri Kosina @ 2014-09-04  6:50 UTC (permalink / raw)
  To: Srinivas Pandruvada; +Cc: elad, linux-input
In-Reply-To: <1409785254-20245-1-git-send-email-srinivas.pandruvada@linux.intel.com>

On Wed, 3 Sep 2014, Srinivas Pandruvada wrote:

> Adding USB_DEVICE_ID_STM_HID_SENSOR again in the quirk table. During 3.16 merge
> cycle somehow quirk for device id USB_DEVICE_ID_STM_HID_SENSOR is missing.
> I see commit dde3b45cd74e ("HID: hid-sensor-hub: new device id and quirk
> for STM Sensor hub") added new id USB_DEVICE_ID_STM_HID_SENSOR_1,
> but didn't really delete the old device id.
> Anyway we need to add this back, otherwise it breaks ST sensor hubs.
> 
> Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
> ---
>  drivers/hid/hid-sensor-hub.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c
> index 2ac2576..e6d8e18 100644
> --- a/drivers/hid/hid-sensor-hub.c
> +++ b/drivers/hid/hid-sensor-hub.c
> @@ -709,6 +709,9 @@ static const struct hid_device_id sensor_hub_devices[] = {
>  			USB_DEVICE_ID_MS_TYPE_COVER_2),
>  			.driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
>  	{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_STM_0,
> +			USB_DEVICE_ID_STM_HID_SENSOR),
> +			.driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
> +	{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_STM_0,
>  			USB_DEVICE_ID_STM_HID_SENSOR_1),
>  			.driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
>  	{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_TEXAS_INSTRUMENTS,

Queued for 3.17.

-- 
Jiri Kosina
SUSE Labs

^ permalink raw reply

* [PATCH] HID: thingm: fix workqueue race on remove
From: Jiri Kosina @ 2014-09-04  7:02 UTC (permalink / raw)
  To: Dylan Alex Simon
  Cc: Benjamin Tissoires, Vivien Didelot, linux-input, linux-kernel
In-Reply-To: <20140904010519.GA13189@datura.dylex.net>

thingm_remove_rgb() needs to flush the workqueue after all the LED classes 
have been unregistered, otherwise the removal might race with another LED 
event coming, causing thingm_led_set() to schedule additional work after 
thingm_remove_rgb() has flushed it. This obviously causes oops later, as 
the scheduled work has been freed in the meantime.

In addition to that, move the hid_hw_stop() to an earlier place, so that 
dmesg is not polluted by failure messages about not being able to write 
the LED while the device is being shut down.

Reported-and-tested-by: Dylan Alex Simon <dylan-kernel@dylex.net>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
---

Queued in hid.git#for-3.18/upstream

 drivers/hid/hid-thingm.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/hid/hid-thingm.c b/drivers/hid/hid-thingm.c
index 134be89..f206398 100644
--- a/drivers/hid/hid-thingm.c
+++ b/drivers/hid/hid-thingm.c
@@ -208,10 +208,10 @@ unregister_red:
 
 static void thingm_remove_rgb(struct thingm_rgb *rgb)
 {
-	flush_work(&rgb->work);
 	led_classdev_unregister(&rgb->red.ldev);
 	led_classdev_unregister(&rgb->green.ldev);
 	led_classdev_unregister(&rgb->blue.ldev);
+	flush_work(&rgb->work);
 }
 
 static int thingm_probe(struct hid_device *hdev, const struct hid_device_id *id)
@@ -286,10 +286,10 @@ static void thingm_remove(struct hid_device *hdev)
 	struct thingm_device *tdev = hid_get_drvdata(hdev);
 	int i;
 
+	hid_hw_stop(hdev);
+
 	for (i = 0; i < tdev->fwinfo->numrgb; ++i)
 		thingm_remove_rgb(tdev->rgb + i);
-
-	hid_hw_stop(hdev);
 }
 
 static const struct hid_device_id thingm_table[] = {

-- 
Jiri Kosina
SUSE Labs

^ permalink raw reply related

* Re: [PATCH v2 1/2] doc: dt/bindings: input: introduce TI DRV2667 haptic driver description
From: Murphy, Dan @ 2014-09-04 13:21 UTC (permalink / raw)
  To: devicetree@vger.kernel.org, linux-input@vger.kernel.org,
	dmitry.torokhov@gmail.com
  Cc: linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	sergei.shtylyov@cogentembedded.com
In-Reply-To: <1408980413-8763-1-git-send-email-dmurphy@ti.com>

Bumping x2

On 08/25/2014 10:26 AM, Murphy, Dan wrote:
> DRV2667 is a haptic/vibrator driver for Linear Resonant Actuators.
> Adding dt binding for this part
> 
> Signed-off-by: Dan Murphy <dmurphy@ti.com>
> ---
> 
> v2 - Removed extra tabs, changed node to function not device
> added vbat-supply, and removed confusing description - https://patchwork.kernel.org/patch/4759381/
> 
>  .../devicetree/bindings/input/ti,drv2667.txt       |   17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/input/ti,drv2667.txt
> 
> diff --git a/Documentation/devicetree/bindings/input/ti,drv2667.txt b/Documentation/devicetree/bindings/input/ti,drv2667.txt
> new file mode 100644
> index 0000000..996382c
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/input/ti,drv2667.txt
> @@ -0,0 +1,17 @@
> +* Texas Instruments - drv2667 Haptics driver
> +
> +Required properties:
> +	- compatible - "ti,drv2667" - DRV2667
> +	- reg -  I2C slave address
> +	- vbat-supply - Required supply regulator
> +
> +Example:
> +
> +haptics: haptics@59 {
> +	compatible = "ti,drv2667";
> +	reg = <0x59>;
> +	vbat-supply = <&vbat>;
> +};
> +
> +For more product information please see the link below:
> +http://www.ti.com/product/drv2667
> 


-- 
------------------
Dan Murphy

^ permalink raw reply

* Re: [PATCH v2 2/2] input: misc: Add support for the DRV2667 haptic driver
From: Murphy, Dan @ 2014-09-04 13:22 UTC (permalink / raw)
  To: devicetree@vger.kernel.org, linux-input@vger.kernel.org,
	dmitry.torokhov@gmail.com
  Cc: linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	sergei.shtylyov@cogentembedded.com
In-Reply-To: <1408980413-8763-2-git-send-email-dmurphy@ti.com>

Bumping x2

On 08/25/2014 10:26 AM, Murphy, Dan wrote:
> Adding support for the DRV2667 haptic driver.
> This device has the ability to store vibration
> patterns in RAM and execute them once the GO bit
> is set.
> 
> The initial driver sets a basic waveform in the
> first waveform sequence and will play the waveform
> when the GO bit is set and will continously play
> the waveform until the GO bit is unset.
> 
> Data sheet is here:
> http://www.ti.com/product/drv2667
> 
> Signed-off-by: Dan Murphy <dmurphy@ti.com>
> ---
> 
> v2 - No updates since no comments - https://patchwork.kernel.org/patch/4759391/
> 
>  drivers/input/misc/Kconfig   |   11 +
>  drivers/input/misc/Makefile  |    1 +
>  drivers/input/misc/drv2667.c |  500 ++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 512 insertions(+)
>  create mode 100644 drivers/input/misc/drv2667.c
> 
> diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
> index 41d0ae6..51891f6 100644
> --- a/drivers/input/misc/Kconfig
> +++ b/drivers/input/misc/Kconfig
> @@ -687,4 +687,15 @@ config INPUT_DRV260X_HAPTICS
>  	  To compile this driver as a module, choose M here: the
>  	  module will be called drv260x-haptics.
>  
> +config INPUT_DRV2667_HAPTICS
> +	tristate "TI DRV2667 haptics support"
> +	depends on INPUT && I2C
> +	select INPUT_FF_MEMLESS
> +	select REGMAP_I2C
> +	help
> +	  Say Y to enable support for the TI DRV2667 haptics driver.
> +
> +	  To compile this driver as a module, choose M here: the
> +	  module will be called drv260x-haptics.
> +
>  endif
> diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
> index cd4bc2d..e0cee17 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_DRV260X_HAPTICS)	+= drv260x.o
> +obj-$(CONFIG_INPUT_DRV2667_HAPTICS)	+= drv2667.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
> diff --git a/drivers/input/misc/drv2667.c b/drivers/input/misc/drv2667.c
> new file mode 100644
> index 0000000..0f43758
> --- /dev/null
> +++ b/drivers/input/misc/drv2667.c
> @@ -0,0 +1,500 @@
> +/*
> + * DRV2667 haptics driver family
> + *
> + * Author: Dan Murphy <dmurphy@ti.com>
> + *
> + * Copyright: (C) 2014 Texas Instruments, Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * General Public License for more details.
> + */
> +
> +#include <linux/i2c.h>
> +#include <linux/input.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/slab.h>
> +#include <linux/delay.h>
> +#include <linux/regulator/consumer.h>
> +
> +/* Contol registers */
> +#define DRV2667_STATUS	0x00
> +#define DRV2667_CTRL_1	0x01
> +#define DRV2667_CTRL_2	0x02
> +/* Waveform sequencer */
> +#define DRV2667_WV_SEQ_0	0x03
> +#define DRV2667_WV_SEQ_1	0x04
> +#define DRV2667_WV_SEQ_2	0x05
> +#define DRV2667_WV_SEQ_3	0x06
> +#define DRV2667_WV_SEQ_4	0x07
> +#define DRV2667_WV_SEQ_5	0x08
> +#define DRV2667_WV_SEQ_6	0x09
> +#define DRV2667_WV_SEQ_7	0x0A
> +#define DRV2667_FIFO		0x0B
> +#define DRV2667_PAGE		0xFF
> +#define DRV2667_MAX_REG		DRV2667_PAGE
> +
> +#define DRV2667_PAGE_0		0x00
> +#define DRV2667_PAGE_1		0x01
> +#define DRV2667_PAGE_2		0x02
> +#define DRV2667_PAGE_3		0x03
> +#define DRV2667_PAGE_4		0x04
> +#define DRV2667_PAGE_5		0x05
> +#define DRV2667_PAGE_6		0x06
> +#define DRV2667_PAGE_7		0x07
> +#define DRV2667_PAGE_8		0x08
> +
> +/* RAM fields */
> +#define DRV2667_RAM_HDR_SZ	0x0
> +/* RAM Header addresses */
> +#define DRV2667_RAM_START_HI	0x01
> +#define DRV2667_RAM_START_LO	0x02
> +#define DRV2667_RAM_STOP_HI		0x03
> +#define DRV2667_RAM_STOP_LO		0x04
> +#define DRV2667_RAM_REPEAT_CT	0x05
> +/* RAM data addresses */
> +#define DRV2667_RAM_AMP		0x06
> +#define DRV2667_RAM_FREQ	0x07
> +#define DRV2667_RAM_DURATION	0x08
> +#define DRV2667_RAM_ENVELOPE	0x09
> +
> +/* Control 1 Register */
> +#define DRV2667_25_VPP_GAIN		0x00
> +#define DRV2667_50_VPP_GAIN		0x01
> +#define DRV2667_75_VPP_GAIN		0x02
> +#define DRV2667_100_VPP_GAIN	0x03
> +#define DRV2667_DIGITAL_IN		0xfc
> +#define DRV2667_ANALOG_IN		(1 << 2)
> +
> +/* Control 2 Register */
> +#define DRV2667_GO			(1 << 0)
> +#define DRV2667_STANDBY		(1 << 6)
> +#define DRV2667_DEV_RST		(1 << 7)
> +
> +/* RAM Envelope settings */
> +#define DRV2667_NO_ENV			0x00
> +#define DRV2667_32_MS_ENV		0x01
> +#define DRV2667_64_MS_ENV		0x02
> +#define DRV2667_96_MS_ENV		0x03
> +#define DRV2667_128_MS_ENV		0x04
> +#define DRV2667_160_MS_ENV		0x05
> +#define DRV2667_192_MS_ENV		0x06
> +#define DRV2667_224_MS_ENV		0x07
> +#define DRV2667_256_MS_ENV		0x08
> +#define DRV2667_512_MS_ENV		0x09
> +#define DRV2667_768_MS_ENV		0x0a
> +#define DRV2667_1024_MS_ENV		0x0b
> +#define DRV2667_1280_MS_ENV		0x0c
> +#define DRV2667_1536_MS_ENV		0x0d
> +#define DRV2667_1792_MS_ENV		0x0e
> +#define DRV2667_2048_MS_ENV		0x0f
> +
> +/**
> + * struct drv2667_data -
> + * @input_dev - Pointer to the input device
> + * @client - Pointer to the I2C client
> + * @regmap - Register map of the device
> + * @work - Work item used to off load the enable/disable of the vibration
> + * @regulator - Pointer to the regulator for the IC
> + * @magnitude - Magnitude of the vibration event
> +**/
> +struct drv2667_data {
> +	struct input_dev *input_dev;
> +	struct i2c_client *client;
> +	struct regmap *regmap;
> +	struct work_struct work;
> +	struct regulator *regulator;
> +	u32 page;
> +	u32 magnitude;
> +	u32 frequency;
> +};
> +
> +static struct reg_default drv2667_reg_defs[] = {
> +	{ DRV2667_STATUS, 0x02 },
> +	{ DRV2667_CTRL_1, 0x28 },
> +	{ DRV2667_CTRL_2, 0x40 },
> +	{ DRV2667_WV_SEQ_0, 0x00 },
> +	{ DRV2667_WV_SEQ_1, 0x00 },
> +	{ DRV2667_WV_SEQ_2, 0x00 },
> +	{ DRV2667_WV_SEQ_3, 0x00 },
> +	{ DRV2667_WV_SEQ_4, 0x00 },
> +	{ DRV2667_WV_SEQ_5, 0x00 },
> +	{ DRV2667_WV_SEQ_6, 0x00 },
> +	{ DRV2667_WV_SEQ_7, 0x00 },
> +	{ DRV2667_FIFO, 0x00 },
> +	{ DRV2667_PAGE, 0x00 },
> +};
> +
> +static int drv2667_set_waveform_freq(struct drv2667_data *haptics)
> +{
> +	unsigned int read_buf;
> +	int freq;
> +	int error;
> +
> +	/* Per the data sheet:
> +	 * Sinusoid Frequency (Hz) = 7.8125 x Frequency
> +	 */
> +	freq = (haptics->frequency * 1000) / 78125;
> +	if (freq <= 0) {
> +		dev_err(&haptics->client->dev,
> +			"ERROR: Frequency calculated to %i\n", freq);
> +		return -EINVAL;
> +	}
> +
> +	error = regmap_read(haptics->regmap, DRV2667_PAGE, &read_buf);
> +	if (error) {
> +		dev_err(&haptics->client->dev,
> +			"Failed to read the page number: %d\n", error);
> +		return -EIO;
> +	}
> +
> +	if (read_buf == DRV2667_PAGE_0 ||
> +		haptics->page != read_buf) {
> +		error = regmap_write(haptics->regmap,
> +				DRV2667_PAGE, haptics->page);
> +		if (error) {
> +			dev_err(&haptics->client->dev,
> +				"Failed to set the page: %d\n", error);
> +			return -EIO;
> +		}
> +	}
> +
> +	error = regmap_write(haptics->regmap, DRV2667_RAM_FREQ,	freq);
> +	if (error)
> +		dev_err(&haptics->client->dev,
> +				"Failed to set the frequency: %d\n", error);
> +
> +	/* Reset back to original page */
> +	if (read_buf == DRV2667_PAGE_0 ||
> +		haptics->page != read_buf) {
> +		error = regmap_write(haptics->regmap, DRV2667_PAGE, read_buf);
> +		if (error) {
> +			dev_err(&haptics->client->dev,
> +					"Failed to set the page: %d\n", error);
> +				return -EIO;
> +			}
> +	}
> +
> +	return error;
> +}
> +
> +static void drv2667_worker(struct work_struct *work)
> +{
> +	struct drv2667_data *haptics = container_of(work, struct drv2667_data, work);
> +	int error;
> +
> +	if (haptics->magnitude) {
> +		error = regmap_write(haptics->regmap,
> +				DRV2667_PAGE, haptics->page);
> +		if (error) {
> +			dev_err(&haptics->client->dev,
> +				"Failed to set the page: %d\n", error);
> +			return;
> +		}
> +
> +		error = regmap_write(haptics->regmap, DRV2667_RAM_AMP,
> +				haptics->magnitude);
> +		if (error) {
> +			dev_err(&haptics->client->dev,
> +				"Failed to set the amplitude: %d\n", error);
> +			return;
> +		}
> +
> +		error = regmap_write(haptics->regmap,
> +				DRV2667_PAGE, DRV2667_PAGE_0);
> +		if (error) {
> +			dev_err(&haptics->client->dev,
> +				"Failed to set the page: %d\n", error);
> +			return;
> +		}
> +
> +		error = regmap_write(haptics->regmap,
> +				DRV2667_CTRL_2, DRV2667_GO);
> +		if (error) {
> +			dev_err(&haptics->client->dev,
> +				"Failed to set the GO bit: %d\n", error);
> +		}
> +	} else {
> +		error = regmap_update_bits(haptics->regmap, DRV2667_CTRL_2,
> +				DRV2667_GO, 0);
> +		if (error) {
> +			dev_err(&haptics->client->dev,
> +				"Failed to unset the GO bit: %d\n", error);
> +		}
> +	}
> +}
> +
> +static int drv2667_haptics_play(struct input_dev *input, void *data,
> +				struct ff_effect *effect)
> +{
> +	struct drv2667_data *haptics = input_get_drvdata(input);
> +
> +	if (effect->u.rumble.strong_magnitude > 0)
> +		haptics->magnitude = effect->u.rumble.strong_magnitude;
> +	else if (effect->u.rumble.weak_magnitude > 0)
> +		haptics->magnitude = effect->u.rumble.weak_magnitude;
> +	else
> +		haptics->magnitude = 0;
> +
> +	schedule_work(&haptics->work);
> +
> +	return 0;
> +}
> +
> +static void drv2667_close(struct input_dev *input)
> +{
> +	struct drv2667_data *haptics = input_get_drvdata(input);
> +	int error;
> +
> +	cancel_work_sync(&haptics->work);
> +
> +	error = regmap_update_bits(haptics->regmap, DRV2667_CTRL_2,
> +				DRV2667_STANDBY, 1);
> +	if (error)
> +		dev_err(&haptics->client->dev,
> +			"Failed to enter standby mode: %d\n", error);
> +}
> +
> +static const struct reg_default drv2667_init_regs[] = {
> +	{ DRV2667_CTRL_2, 0 },
> +	{ DRV2667_CTRL_1, DRV2667_25_VPP_GAIN },
> +	{ DRV2667_WV_SEQ_0, 1 },
> +	{ DRV2667_WV_SEQ_1, 0 }
> +};
> +
> +static const struct reg_default drv2667_page1_init[] = {
> +	{ DRV2667_RAM_HDR_SZ, 0x05 },
> +	{ DRV2667_RAM_START_HI, 0x80 },
> +	{ DRV2667_RAM_START_LO, 0x06 },
> +	{ DRV2667_RAM_STOP_HI, 0x00 },
> +	{ DRV2667_RAM_STOP_LO, 0x09 },
> +	{ DRV2667_RAM_REPEAT_CT, 0 },
> +	{ DRV2667_RAM_DURATION, 0x05 },
> +	{ DRV2667_RAM_ENVELOPE, DRV2667_NO_ENV },
> +	{ DRV2667_RAM_AMP, 0x60 },
> +};
> +
> +static int drv2667_init(struct drv2667_data *haptics)
> +{
> +	int error;
> +
> +	/* Set default haptic frequency to 195Hz on Page 1*/
> +	haptics->frequency = 195;
> +	haptics->page = DRV2667_PAGE_1;
> +
> +	error = regmap_register_patch(haptics->regmap,
> +				      drv2667_init_regs,
> +				      ARRAY_SIZE(drv2667_init_regs));
> +	if (error) {
> +		dev_err(&haptics->client->dev,
> +			"Failed to write init registers: %d\n",
> +			error);
> +		return error;
> +	}
> +
> +	error = regmap_write(haptics->regmap, DRV2667_PAGE, haptics->page);
> +	if (error) {
> +		dev_err(&haptics->client->dev, "Failed to set page: %d\n",
> +			error);
> +		goto error_out;
> +	}
> +
> +	error = drv2667_set_waveform_freq(haptics);
> +	if (error)
> +		goto error_page;
> +
> +	error = regmap_register_patch(haptics->regmap,
> +				      drv2667_page1_init,
> +				      ARRAY_SIZE(drv2667_page1_init));
> +	if (error) {
> +		dev_err(&haptics->client->dev,
> +			"Failed to write page registers: %d\n",
> +			error);
> +		return error;
> +	}
> +
> +	error = regmap_write(haptics->regmap, DRV2667_PAGE, DRV2667_PAGE_0);
> +	return error;
> +
> +error_page:
> +	regmap_write(haptics->regmap, DRV2667_PAGE, DRV2667_PAGE_0);
> +error_out:
> +	return error;
> +}
> +
> +static const struct regmap_config drv2667_regmap_config = {
> +	.reg_bits = 8,
> +	.val_bits = 8,
> +
> +	.max_register = DRV2667_MAX_REG,
> +	.reg_defaults = drv2667_reg_defs,
> +	.num_reg_defaults = ARRAY_SIZE(drv2667_reg_defs),
> +	.cache_type = REGCACHE_NONE,
> +};
> +
> +static int drv2667_probe(struct i2c_client *client,
> +			 const struct i2c_device_id *id)
> +{
> +	struct drv2667_data *haptics;
> +	int error;
> +
> +	haptics = devm_kzalloc(&client->dev, sizeof(*haptics), GFP_KERNEL);
> +	if (!haptics)
> +		return -ENOMEM;
> +
> +	haptics->regulator = devm_regulator_get(&client->dev, "vbat");
> +	if (IS_ERR(haptics->regulator)) {
> +		error = PTR_ERR(haptics->regulator);
> +		dev_err(&client->dev,
> +			"unable to get regulator, error: %d\n", error);
> +		return error;
> +	}
> +
> +	haptics->input_dev = devm_input_allocate_device(&client->dev);
> +	if (!haptics->input_dev) {
> +		dev_err(&client->dev, "Failed to allocate input device\n");
> +		return -ENOMEM;
> +	}
> +
> +	haptics->input_dev->name = "drv2667:haptics";
> +	haptics->input_dev->dev.parent = client->dev.parent;
> +	haptics->input_dev->close = drv2667_close;
> +	input_set_drvdata(haptics->input_dev, haptics);
> +	input_set_capability(haptics->input_dev, EV_FF, FF_RUMBLE);
> +
> +	error = input_ff_create_memless(haptics->input_dev, NULL,
> +					drv2667_haptics_play);
> +	if (error) {
> +		dev_err(&client->dev, "input_ff_create() failed: %d\n",
> +			error);
> +		return error;
> +	}
> +
> +	INIT_WORK(&haptics->work, drv2667_worker);
> +
> +	haptics->client = client;
> +	i2c_set_clientdata(client, haptics);
> +
> +	haptics->regmap = devm_regmap_init_i2c(client, &drv2667_regmap_config);
> +	if (IS_ERR(haptics->regmap)) {
> +		error = PTR_ERR(haptics->regmap);
> +		dev_err(&client->dev, "Failed to allocate register map: %d\n",
> +			error);
> +		return error;
> +	}
> +
> +	error = drv2667_init(haptics);
> +	if (error) {
> +		dev_err(&client->dev, "Device init failed: %d\n", error);
> +		return error;
> +	}
> +
> +	error = input_register_device(haptics->input_dev);
> +	if (error) {
> +		dev_err(&client->dev, "couldn't register input device: %d\n",
> +			error);
> +		return error;
> +	}
> +
> +	return 0;
> +}
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int drv2667_suspend(struct device *dev)
> +{
> +	struct drv2667_data *haptics = dev_get_drvdata(dev);
> +	int ret = 0;
> +
> +	mutex_lock(&haptics->input_dev->mutex);
> +
> +	if (haptics->input_dev->users) {
> +		ret = regmap_update_bits(haptics->regmap, DRV2667_CTRL_2,
> +				DRV2667_STANDBY, 1);
> +		if (ret) {
> +			dev_err(dev, "Failed to set standby mode\n");
> +			regulator_disable(haptics->regulator);
> +			goto out;
> +		}
> +
> +		ret = regulator_disable(haptics->regulator);
> +		if (ret) {
> +			dev_err(dev, "Failed to disable regulator\n");
> +			regmap_update_bits(haptics->regmap,
> +					   DRV2667_CTRL_2,
> +					   DRV2667_STANDBY, 0);
> +		}
> +	}
> +out:
> +	mutex_unlock(&haptics->input_dev->mutex);
> +	return ret;
> +}
> +
> +static int drv2667_resume(struct device *dev)
> +{
> +	struct drv2667_data *haptics = dev_get_drvdata(dev);
> +	int ret = 0;
> +
> +	mutex_lock(&haptics->input_dev->mutex);
> +
> +	if (haptics->input_dev->users) {
> +		ret = regulator_enable(haptics->regulator);
> +		if (ret) {
> +			dev_err(dev, "Failed to enable regulator\n");
> +			goto out;
> +		}
> +
> +		ret = regmap_update_bits(haptics->regmap, DRV2667_CTRL_2,
> +					 DRV2667_STANDBY, 0);
> +		if (ret) {
> +			dev_err(dev, "Failed to unset standby mode\n");
> +			regulator_disable(haptics->regulator);
> +			goto out;
> +		}
> +
> +	}
> +
> +out:
> +	mutex_unlock(&haptics->input_dev->mutex);
> +	return ret;
> +}
> +#endif
> +
> +static SIMPLE_DEV_PM_OPS(drv2667_pm_ops, drv2667_suspend, drv2667_resume);
> +
> +static const struct i2c_device_id drv2667_id[] = {
> +	{ "drv2667", 0 },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(i2c, drv2667_id);
> +
> +#ifdef CONFIG_OF
> +static const struct of_device_id drv2667_of_match[] = {
> +	{ .compatible = "ti,drv2667", },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(of, drv2667_of_match);
> +#endif
> +
> +static struct i2c_driver drv2667_driver = {
> +	.probe		= drv2667_probe,
> +	.driver		= {
> +		.name	= "drv2667-haptics",
> +		.owner	= THIS_MODULE,
> +		.of_match_table = of_match_ptr(drv2667_of_match),
> +		.pm	= &drv2667_pm_ops,
> +	},
> +	.id_table = drv2667_id,
> +};
> +module_i2c_driver(drv2667_driver);
> +
> +MODULE_ALIAS("platform:drv2667-haptics");
> +MODULE_DESCRIPTION("TI DRV2667 haptics driver");
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
> 


-- 
------------------
Dan Murphy

^ permalink raw reply

* [PATCH 2/3] input: ti_am335x_tsc: Remove DT wire-config parameter
From: Sebastian Andrzej Siewior @ 2014-09-04 14:39 UTC (permalink / raw)
  To: linux-input
  Cc: Dmitry Torokhov, Felipe Balbi, linux-omap, Jeff Lance,
	Benoît Cousson, Tony Lindgren, Sebastian Andrzej Siewior
In-Reply-To: <1409841555-11336-1-git-send-email-bigeasy@linutronix.de>

From: Jeff Lance <j-lance1@ti.com>

With the touschscreen in am335x, you do not have the option to mux the
analog input lines. You must connect the analog input to the corresponding
touchscreen terminal.
This patch removes the code that is parsing the ti,wire-config and uses
the "default" parameters instead.
In short,
	inp_xp => STEPCONFIG_INP(0)
	inp_xn => STEPCONFIG_INP(1)
	inp_yp => STEPCONFIG_INP(2)
	inp_yn => STEPCONFIG_INP(3)
	bit_xp => STEPCONFIG_XPP
	bit_xn => STEPCONFIG_XNN
	bit_yp => STEPCONFIG_YPP
	bit_yn => STEPCONFIG_YNN

Cc: "Benoît Cousson" <bcousson@baylibre.com>
Cc: Tony Lindgren <tony@atomide.com>
Signed-off-by: Jeff Lance <j-lance1@ti.com>
[bigeasy: refresh, drop AIN defines.]
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 drivers/input/touchscreen/ti_am335x_tsc.c | 109 +++++-------------------------
 1 file changed, 16 insertions(+), 93 deletions(-)

diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
index 092fa8b31c67..92fb473621b0 100644
--- a/drivers/input/touchscreen/ti_am335x_tsc.c
+++ b/drivers/input/touchscreen/ti_am335x_tsc.c
@@ -33,13 +33,6 @@
 #define SEQ_SETTLE		275
 #define MAX_12BIT		((1 << 12) - 1)
 
-static const int config_pins[] = {
-	STEPCONFIG_XPP,
-	STEPCONFIG_XNN,
-	STEPCONFIG_YPP,
-	STEPCONFIG_YNN,
-};
-
 struct titsc {
 	struct input_dev	*input;
 	struct ti_tscadc_dev	*mfd_tscadc;
@@ -48,9 +41,6 @@ struct titsc {
 	unsigned int		x_plate_resistance;
 	bool			pen_down;
 	int			coordinate_readouts;
-	u32			config_inp[4];
-	u32			bit_xp, bit_xn, bit_yp, bit_yn;
-	u32			inp_xp, inp_xn, inp_yp, inp_yn;
 	u32			step_mask;
 };
 
@@ -65,58 +55,6 @@ static void titsc_writel(struct titsc *tsc, unsigned int reg,
 	writel(val, tsc->mfd_tscadc->tscadc_base + reg);
 }
 
-static int titsc_config_wires(struct titsc *ts_dev)
-{
-	u32 analog_line[4];
-	u32 wire_order[4];
-	int i, bit_cfg;
-
-	for (i = 0; i < 4; i++) {
-		/*
-		 * Get the order in which TSC wires are attached
-		 * w.r.t. each of the analog input lines on the EVM.
-		 */
-		analog_line[i] = (ts_dev->config_inp[i] & 0xF0) >> 4;
-		wire_order[i] = ts_dev->config_inp[i] & 0x0F;
-		if (WARN_ON(analog_line[i] > 7))
-			return -EINVAL;
-		if (WARN_ON(wire_order[i] > ARRAY_SIZE(config_pins)))
-			return -EINVAL;
-	}
-
-	for (i = 0; i < 4; i++) {
-		int an_line;
-		int wi_order;
-
-		an_line = analog_line[i];
-		wi_order = wire_order[i];
-		bit_cfg = config_pins[wi_order];
-		if (bit_cfg == 0)
-			return -EINVAL;
-		switch (wi_order) {
-		case 0:
-			ts_dev->bit_xp = bit_cfg;
-			ts_dev->inp_xp = an_line;
-			break;
-
-		case 1:
-			ts_dev->bit_xn = bit_cfg;
-			ts_dev->inp_xn = an_line;
-			break;
-
-		case 2:
-			ts_dev->bit_yp = bit_cfg;
-			ts_dev->inp_yp = an_line;
-			break;
-		case 3:
-			ts_dev->bit_yn = bit_cfg;
-			ts_dev->inp_yn = an_line;
-			break;
-		}
-	}
-	return 0;
-}
-
 static void titsc_step_config(struct titsc *ts_dev)
 {
 	unsigned int	config;
@@ -124,19 +62,17 @@ static void titsc_step_config(struct titsc *ts_dev)
 	int end_step;
 	u32 stepenable;
 
-	config = STEPCONFIG_MODE_HWSYNC |
-			STEPCONFIG_AVG_16 | ts_dev->bit_xp;
+	config = STEPCONFIG_MODE_HWSYNC | STEPCONFIG_AVG_16 | STEPCONFIG_XPP;
 	switch (ts_dev->wires) {
 	case 4:
-		config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn;
+		config |= STEPCONFIG_INP(2) | STEPCONFIG_XNN;
 		break;
 	case 5:
-		config |= ts_dev->bit_yn |
-				STEPCONFIG_INP_AN4 | ts_dev->bit_xn |
-				ts_dev->bit_yp;
+		config |= STEPCONFIG_YNN | STEPCONFIG_INP_AN4 | STEPCONFIG_XNN |
+				STEPCONFIG_YPP;
 		break;
 	case 8:
-		config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn;
+		config |= STEPCONFIG_INP(2) | STEPCONFIG_XNN;
 		break;
 	}
 
@@ -147,20 +83,18 @@ static void titsc_step_config(struct titsc *ts_dev)
 		titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
 	}
 
-	config = 0;
-	config = STEPCONFIG_MODE_HWSYNC |
-			STEPCONFIG_AVG_16 | ts_dev->bit_yn |
+	config = STEPCONFIG_MODE_HWSYNC | STEPCONFIG_AVG_16 | STEPCONFIG_YNN |
 			STEPCONFIG_INM_ADCREFM;
 	switch (ts_dev->wires) {
 	case 4:
-		config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp);
+		config |= STEPCONFIG_YPP | STEPCONFIG_INP(0);
 		break;
 	case 5:
-		config |= ts_dev->bit_xp | STEPCONFIG_INP_AN4 |
+		config |= STEPCONFIG_XPP | STEPCONFIG_INP_AN4 |
 				STEPCONFIG_XNP | STEPCONFIG_YPN;
 		break;
 	case 8:
-		config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp);
+		config |= STEPCONFIG_YPP | STEPCONFIG_INP(0);
 		break;
 	}
 
@@ -172,24 +106,23 @@ static void titsc_step_config(struct titsc *ts_dev)
 	}
 
 	/* Charge step configuration */
-	config = ts_dev->bit_xp | ts_dev->bit_yn |
-			STEPCHARGE_RFP_XPUL | STEPCHARGE_RFM_XNUR |
-			STEPCHARGE_INM_AN1 | STEPCHARGE_INP(ts_dev->inp_yp);
+	config = STEPCONFIG_XPP | STEPCONFIG_YNN | STEPCHARGE_RFP_XPUL |
+		STEPCHARGE_RFM_XNUR | STEPCHARGE_INM_AN1 | STEPCHARGE_INP(2);
 
 	titsc_writel(ts_dev, REG_CHARGECONFIG, config);
 	titsc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY);
 
 	/* coordinate_readouts * 2 … coordinate_readouts * 2 + 2 is for Z */
 	config = STEPCONFIG_MODE_HWSYNC |
-			STEPCONFIG_AVG_16 | ts_dev->bit_yp |
-			ts_dev->bit_xn | STEPCONFIG_INM_ADCREFM |
-			STEPCONFIG_INP(ts_dev->inp_xp);
+			STEPCONFIG_AVG_16 | STEPCONFIG_YPP |
+			STEPCONFIG_XNN | STEPCONFIG_INM_ADCREFM |
+			STEPCONFIG_INP(0);
 	titsc_writel(ts_dev, REG_STEPCONFIG(end_step), config);
 	titsc_writel(ts_dev, REG_STEPDELAY(end_step),
 			STEPCONFIG_OPENDLY);
 
 	end_step++;
-	config |= STEPCONFIG_INP(ts_dev->inp_yn);
+	config |= STEPCONFIG_INP(3);
 	titsc_writel(ts_dev, REG_STEPCONFIG(end_step), config);
 	titsc_writel(ts_dev, REG_STEPDELAY(end_step),
 			STEPCONFIG_OPENDLY);
@@ -364,12 +297,7 @@ static int titsc_parse_dt(struct platform_device *pdev,
 		err = of_property_read_u32(node, "ti,coordiante-readouts",
 				&ts_dev->coordinate_readouts);
 	}
-
-	if (err < 0)
-		return err;
-
-	return of_property_read_u32_array(node, "ti,wire-config",
-			ts_dev->config_inp, ARRAY_SIZE(ts_dev->config_inp));
+	return err;
 }
 
 /*
@@ -411,11 +339,6 @@ static int titsc_probe(struct platform_device *pdev)
 	}
 
 	titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES);
-	err = titsc_config_wires(ts_dev);
-	if (err) {
-		dev_err(&pdev->dev, "wrong i/p wire configuration\n");
-		goto err_free_irq;
-	}
 	titsc_step_config(ts_dev);
 	titsc_writel(ts_dev, REG_FIFO0THR,
 			ts_dev->coordinate_readouts * 2 + 2 - 1);
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH 3/3] ARM: DTS: AM335x: Drop TSC's wire-config parameters
From: Sebastian Andrzej Siewior @ 2014-09-04 14:39 UTC (permalink / raw)
  To: linux-input
  Cc: Dmitry Torokhov, Felipe Balbi, linux-omap, Jeff Lance,
	Benoît Cousson, Tony Lindgren, devicetree,
	Sebastian Andrzej Siewior
In-Reply-To: <1409841555-11336-1-git-send-email-bigeasy@linutronix.de>

From: Jeff Lance <j-lance1@ti.com>

The TSC driver is beeing updated, the parameter is not used anymore. The
AIN lines can not be muxed. All boards use the same value.
This patch updates the Documentation and dts files.

Cc: "Benoît Cousson" <bcousson@baylibre.com>
Cc: Tony Lindgren <tony@atomide.com>
Cc: devicetree@vger.kernel.org
Signed-off-by: Jeff Lance <j-lance1@ti.com>
[bigeasy: split, add .dts files to the removal]
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 .../devicetree/bindings/input/touchscreen/ti-tsc-adc.txt       | 10 ----------
 arch/arm/boot/dts/am335x-evm.dts                               |  1 -
 arch/arm/boot/dts/am335x-evmsk.dts                             |  1 -
 arch/arm/boot/dts/am335x-pepper.dts                            |  1 -
 4 files changed, 13 deletions(-)

diff --git a/Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt b/Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt
index 878549ba814d..eeaf065563c9 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt
@@ -15,15 +15,6 @@
 				Y and 2 for Z (always). This utilises 12
 				of the 16 software steps available. The
 				remaining 4 can be used by the ADC.
-	ti,wire-config: Different boards could have a different order for
-			connecting wires on touchscreen. We need to provide an
-			8 bit number where in the 1st four bits represent the
-			analog lines and the next 4 bits represent positive/
-			negative terminal on that input line. Notations to
-			represent the input lines and terminals resoectively
-			is as follows:
-			AIN0 = 0, AIN1 = 1 and so on till AIN7 = 7.
-			XP  = 0, XN = 1, YP = 2, YN = 3.
 - child "adc"
 	ti,adc-channels: List of analog inputs available for ADC.
 			 AIN0 = 0, AIN1 = 1 and so on till AIN7 = 7.
@@ -35,7 +26,6 @@
 			ti,wires = <4>;
 			ti,x-plate-resistance = <200>;
 			ti,coordiante-readouts = <5>;
-			ti,wire-config = <0x00 0x11 0x22 0x33>;
 		};
 
 		adc {
diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
index e2156a583de7..4c0a5eab5ef2 100644
--- a/arch/arm/boot/dts/am335x-evm.dts
+++ b/arch/arm/boot/dts/am335x-evm.dts
@@ -640,7 +640,6 @@
 		ti,wires = <4>;
 		ti,x-plate-resistance = <200>;
 		ti,coordinate-readouts = <5>;
-		ti,wire-config = <0x00 0x11 0x22 0x33>;
 	};
 
 	adc {
diff --git a/arch/arm/boot/dts/am335x-evmsk.dts b/arch/arm/boot/dts/am335x-evmsk.dts
index df5fee6b6b4b..88d83b25089a 100644
--- a/arch/arm/boot/dts/am335x-evmsk.dts
+++ b/arch/arm/boot/dts/am335x-evmsk.dts
@@ -671,7 +671,6 @@
 		ti,wires = <4>;
 		ti,x-plate-resistance = <200>;
 		ti,coordinate-readouts = <5>;
-		ti,wire-config = <0x00 0x11 0x22 0x33>;
 	};
 };
 
diff --git a/arch/arm/boot/dts/am335x-pepper.dts b/arch/arm/boot/dts/am335x-pepper.dts
index 0d35ab64641c..0939ded7eea5 100644
--- a/arch/arm/boot/dts/am335x-pepper.dts
+++ b/arch/arm/boot/dts/am335x-pepper.dts
@@ -502,7 +502,6 @@
 		ti,wires = <4>;
 		ti,x-plate-resistance = <200>;
 		ti,coordinate-readouts = <5>;
-		ti,wire-config = <0x00 0x11 0x22 0x33>;
 	};
 
 	adc {
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH 1/3] Input: ti_am335x_tsc: Fix incorrect step config 5 wire touschscreen
From: Sebastian Andrzej Siewior @ 2014-09-04 14:39 UTC (permalink / raw)
  To: linux-input
  Cc: Dmitry Torokhov, Felipe Balbi, linux-omap, Jeff Lance,
	Sebastian Andrzej Siewior

From: Jeff Lance <j-lance1@ti.com>

The step config setting for a 5 wire touchscreen is incorrectly sets the
Y coordinates.
It was broken while we moved to DT. If you look close, the change was:

|- STEPCONFIG_XNP | STEPCONFIG_YPN;
|+ ts_dev->bit_xn | ts_dev->bit_yp;

while bit_xn = STEPCONFIG_XNN and bit_yp = STEPCONFIG_YNN. Not quite the
same :)

Fixes: bb76dc09ddfc ("input: ti_am33x_tsc: Order of TSC wires, made
configurable")
Signed-off-by: Jeff Lance <j-lance1@ti.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 drivers/input/touchscreen/ti_am335x_tsc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
index 2ce649520fe0..092fa8b31c67 100644
--- a/drivers/input/touchscreen/ti_am335x_tsc.c
+++ b/drivers/input/touchscreen/ti_am335x_tsc.c
@@ -157,7 +157,7 @@ static void titsc_step_config(struct titsc *ts_dev)
 		break;
 	case 5:
 		config |= ts_dev->bit_xp | STEPCONFIG_INP_AN4 |
-				ts_dev->bit_xn | ts_dev->bit_yp;
+				STEPCONFIG_XNP | STEPCONFIG_YPN;
 		break;
 	case 8:
 		config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp);
-- 
2.1.0


^ permalink raw reply related

* [PATCH v2 4/4] mfd: max77693: Update DT binding to support haptic
From: Jaewon Kim @ 2014-09-04 15:01 UTC (permalink / raw)
  To: Dmitry Torokhov, Samuel Ortiz, Lee Jones
  Cc: linux-kernel, linux-input, Chanwoo Choi, Jaewon Kim
In-Reply-To: <1409842891-26549-1-git-send-email-jaewon02.kim@samsung.com>

This patch add haptic DT binding documentation and example
to support haptic driver in max77693 Multifunction device.

Signed-off-by: Jaewon Kim <jaewon02.kim@samsung.com>
Acked-by: Chanwoo Choi <cw00.choi@samsung.com>
---
 Documentation/devicetree/bindings/mfd/max77693.txt |   18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/Documentation/devicetree/bindings/mfd/max77693.txt b/Documentation/devicetree/bindings/mfd/max77693.txt
index 11921cc..d178b9e 100644
--- a/Documentation/devicetree/bindings/mfd/max77693.txt
+++ b/Documentation/devicetree/bindings/mfd/max77693.txt
@@ -27,6 +27,17 @@ Optional properties:
 
 	[*] refer Documentation/devicetree/bindings/regulator/regulator.txt
 
+- haptic : The haptic of max77693 have to be instantiated under subnod
+  named "haptic" using the following haptic format in example.
+  Haptic sensation from motor can be changed by changing a period cycle in pwms.
+
+ Required properties:
+	- compatible : Must be "maxim,max77693-hpatic"
+	- haptic-supply : power supply for haptic motor
+		[*] refer Documentation/devicetree/bindings/regulator/regulator.txt
+	- pwms : phandle to the physical PWM device,
+		[*] refer Documentation/devicetree/bindings/pwm/pwm.txt
+
 Example:
 	max77693@66 {
 		compatible = "maxim,max77693";
@@ -52,4 +63,11 @@ Example:
 					regulator-boot-on;
 			};
 		};
+
+		haptic {
+			compatible = "maxim,max77693-haptic";
+			haptic-supply = <&haptic_supply>;
+			pwms = <&pwm 0 40000 0>;
+			pwm-names = "haptic";
+		};
 	};
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH v2 0/4] Add max77693 haptic driver
From: Jaewon Kim @ 2014-09-04 15:01 UTC (permalink / raw)
  To: Dmitry Torokhov, Samuel Ortiz, Lee Jones
  Cc: linux-kernel, linux-input, Chanwoo Choi, Jaewon Kim

This series adds max77693 haptic driver.
The max77693 is a Multifunction device with PMIC, CHARGER, LED,
MUIC, HAPTIC and this series is haptic device driver in MAX77693.
The haptic driver use regmap method for i2c communication and
support force feedback framework in input device.

Changes in v2:
 - split to documentation and mfd patchs.
 - Documentation : change explanation of haptic 
 - Documentation : remove pwm-names propertie in example

Jaewon Kim (4):
  mfd: max77693: Initialize haptic register map
  Input: misc: Add haptic driver on max77693
  mfd: max77693: add haptic of_compatible in mfd_cell
  mfd: max77693: Update DT binding to support haptic

 Documentation/devicetree/bindings/mfd/max77693.txt |   18 ++
 drivers/input/misc/Kconfig                         |   12 +
 drivers/input/misc/Makefile                        |    1 +
 drivers/input/misc/max77693-haptic.c               |  333 ++++++++++++++++++++
 drivers/mfd/max77693.c                             |   26 +-
 include/linux/mfd/max77693-private.h               |    9 +
 6 files changed, 395 insertions(+), 4 deletions(-)
 create mode 100644 drivers/input/misc/max77693-haptic.c

-- 
1.7.9.5


^ permalink raw reply

* [PATCH v2 1/4] mfd: max77693: Initialize haptic register map
From: Jaewon Kim @ 2014-09-04 15:01 UTC (permalink / raw)
  To: Dmitry Torokhov, Samuel Ortiz, Lee Jones
  Cc: linux-kernel, linux-input, Chanwoo Choi, Jaewon Kim
In-Reply-To: <1409842891-26549-1-git-send-email-jaewon02.kim@samsung.com>

This patch add regmap_haptic initialization to use haptic register map
in haptic device driver.

Signed-off-by: Jaewon Kim <jaewon02.kim@samsung.com>
Acked-by: Chanwoo Choi <cw00.choi@samsung.com>
Acked-by: Lee Jones <lee.jones@linaro.org>
---
 drivers/mfd/max77693.c |   21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c
index 249c139..fbfed56 100644
--- a/drivers/mfd/max77693.c
+++ b/drivers/mfd/max77693.c
@@ -144,6 +144,12 @@ static const struct regmap_irq_chip max77693_muic_irq_chip = {
 	.num_irqs		= ARRAY_SIZE(max77693_muic_irqs),
 };
 
+static const struct regmap_config max77693_regmap_haptic_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = MAX77693_HAPTIC_REG_END,
+};
+
 static int max77693_i2c_probe(struct i2c_client *i2c,
 			      const struct i2c_device_id *id)
 {
@@ -193,6 +199,15 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
 	}
 	i2c_set_clientdata(max77693->haptic, max77693);
 
+	max77693->regmap_haptic = devm_regmap_init_i2c(max77693->haptic,
+					&max77693_regmap_haptic_config);
+	if (IS_ERR(max77693->regmap_haptic)) {
+		ret = PTR_ERR(max77693->regmap_haptic);
+		dev_err(max77693->dev,
+			"failed to initialize haptic register map: %d\n", ret);
+		goto err_regmap;
+	}
+
 	/*
 	 * Initialize register map for MUIC device because use regmap-muic
 	 * instance of MUIC device when irq of max77693 is initialized
@@ -204,7 +219,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
 		ret = PTR_ERR(max77693->regmap_muic);
 		dev_err(max77693->dev,
 			"failed to allocate register map: %d\n", ret);
-		goto err_regmap_muic;
+		goto err_regmap;
 	}
 
 	ret = regmap_add_irq_chip(max77693->regmap, max77693->irq,
@@ -214,7 +229,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
 				&max77693->irq_data_led);
 	if (ret) {
 		dev_err(max77693->dev, "failed to add irq chip: %d\n", ret);
-		goto err_regmap_muic;
+		goto err_regmap;
 	}
 
 	ret = regmap_add_irq_chip(max77693->regmap, max77693->irq,
@@ -265,7 +280,7 @@ err_irq_charger:
 	regmap_del_irq_chip(max77693->irq, max77693->irq_data_topsys);
 err_irq_topsys:
 	regmap_del_irq_chip(max77693->irq, max77693->irq_data_led);
-err_regmap_muic:
+err_regmap:
 	i2c_unregister_device(max77693->haptic);
 err_i2c_haptic:
 	i2c_unregister_device(max77693->muic);
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v2 3/4] mfd: max77693: add haptic of_compatible in mfd_cell
From: Jaewon Kim @ 2014-09-04 15:01 UTC (permalink / raw)
  To: Dmitry Torokhov, Samuel Ortiz, Lee Jones
  Cc: linux-kernel, linux-input, Chanwoo Choi, Jaewon Kim
In-Reply-To: <1409842891-26549-1-git-send-email-jaewon02.kim@samsung.com>

This patch add haptic of_compatible in order to use the haptic
device driver using Devicetree.

Signed-off-by: Jaewon Kim <jaewon02.kim@samsung.com>
Acked-by: Chanwoo Choi <cw00.choi@samsung.com>
---
 drivers/mfd/max77693.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c
index fbfed56..03fd431 100644
--- a/drivers/mfd/max77693.c
+++ b/drivers/mfd/max77693.c
@@ -46,7 +46,10 @@ static const struct mfd_cell max77693_devs[] = {
 	{ .name = "max77693-charger", },
 	{ .name = "max77693-flash", },
 	{ .name = "max77693-muic", },
-	{ .name = "max77693-haptic", },
+	{
+	  .name = "max77693-haptic",
+	  .of_compatible = "maxim,max77693-haptic",
+	},
 };
 
 static const struct regmap_config max77693_regmap_config = {
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v2 2/4] Input: misc: Add haptic driver on max77693
From: Jaewon Kim @ 2014-09-04 15:01 UTC (permalink / raw)
  To: Dmitry Torokhov, Samuel Ortiz, Lee Jones
  Cc: linux-kernel, linux-input, Chanwoo Choi, Jaewon Kim
In-Reply-To: <1409842891-26549-1-git-send-email-jaewon02.kim@samsung.com>

This patch add max77693-haptic device driver to support the haptic controller
on MAX77693. The MAX77693 is a Multifunction device with PMIC, CHARGER, LED,
MUIC, HAPTIC and the patch is haptic device driver in the MAX77693. This driver
support external pwm and LRA(Linear Resonant Actuator) motor. User can control
the haptic driver by using force feedback framework.

Signed-off-by: Jaewon Kim <jaewon02.kim@samsung.com>
Acked-by: Chanwoo Choi <cw00.choi@samsung.com>
---
 drivers/input/misc/Kconfig           |   12 ++
 drivers/input/misc/Makefile          |    1 +
 drivers/input/misc/max77693-haptic.c |  333 ++++++++++++++++++++++++++++++++++
 include/linux/mfd/max77693-private.h |    9 +
 4 files changed, 355 insertions(+)
 create mode 100644 drivers/input/misc/max77693-haptic.c

diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 2ff4425..c597c52 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -144,6 +144,18 @@ config INPUT_M68K_BEEP
 	tristate "M68k Beeper support"
 	depends on M68K
 
+config INPUT_MAX77693_HAPTIC
+	tristate "MAXIM MAX77693 haptic controller support"
+	depends on MFD_MAX77693 && PWM
+	select INPUT_FF_MEMLESS
+	help
+	  This option enables device driver support for the haptic controller
+	  on MAXIM MAX77693 chip. This driver supports ff-memless interface
+	  from input framework.
+
+	  To compile this driver as module, choose M here: the
+	  module will be called max77693-haptic.
+
 config INPUT_MAX8925_ONKEY
 	tristate "MAX8925 ONKEY support"
 	depends on MFD_MAX8925
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 4955ad3..b28570c 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_INPUT_IXP4XX_BEEPER)	+= ixp4xx-beeper.o
 obj-$(CONFIG_INPUT_KEYSPAN_REMOTE)	+= keyspan_remote.o
 obj-$(CONFIG_INPUT_KXTJ9)		+= kxtj9.o
 obj-$(CONFIG_INPUT_M68K_BEEP)		+= m68kspkr.o
+obj-$(CONFIG_INPUT_MAX77693_HAPTIC)	+= max77693-haptic.o
 obj-$(CONFIG_INPUT_MAX8925_ONKEY)	+= max8925_onkey.o
 obj-$(CONFIG_INPUT_MAX8997_HAPTIC)	+= max8997_haptic.o
 obj-$(CONFIG_INPUT_MC13783_PWRBUTTON)	+= mc13783-pwrbutton.o
diff --git a/drivers/input/misc/max77693-haptic.c b/drivers/input/misc/max77693-haptic.c
new file mode 100644
index 0000000..2a69496
--- /dev/null
+++ b/drivers/input/misc/max77693-haptic.c
@@ -0,0 +1,333 @@
+/*
+ * max77693-haptic.c - MAXIM MAX77693 Haptic device driver
+ *
+ * Copyright (C) 2014 Samsung Electronics
+ * Jaewon Kim <jaewon02.kim@samsung.com>
+ *
+ * This program is not provided / owned by Maxim Integrated Products.
+ *
+ * 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/err.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/regulator/consumer.h>
+#include <linux/mfd/max77693.h>
+#include <linux/mfd/max77693-private.h>
+
+#define MAX_MAGNITUDE_SHIFT	16
+
+enum max77693_haptic_motor_type {
+	MAX77693_HAPTIC_ERM = 0,
+	MAX77693_HAPTIC_LRA,
+};
+
+enum max77693_haptic_pulse_mode {
+	MAX77693_HAPTIC_EXTERNAL_MODE = 0,
+	MAX77693_HAPTIC_INTERNAL_MODE,
+};
+
+enum max77693_haptic_pwm_divisor {
+	MAX77693_HAPTIC_PWM_DIVISOR_32 = 0,
+	MAX77693_HAPTIC_PWM_DIVISOR_64,
+	MAX77693_HAPTIC_PWM_DIVISOR_128,
+	MAX77693_HAPTIC_PWM_DIVISOR_256,
+};
+
+struct max77693_haptic {
+	struct regmap *regmap_pmic;
+	struct regmap *regmap_haptic;
+	struct device *dev;
+	struct input_dev *input_dev;
+	struct pwm_device *pwm_dev;
+	struct regulator *motor_reg;
+
+	bool enabled;
+	unsigned int magnitude;
+	enum max77693_haptic_motor_type type;
+	enum max77693_haptic_pulse_mode mode;
+	enum max77693_haptic_pwm_divisor pwm_divisor;
+
+	struct mutex mutex;
+	struct work_struct work;
+};
+
+static int max77693_haptic_set_duty_cycle(struct max77693_haptic *haptic,
+						unsigned int pwm_duty)
+{
+	int ret;
+	int delta = (haptic->pwm_dev->period + pwm_duty)/2;
+
+	ret = pwm_config(haptic->pwm_dev, delta, haptic->pwm_dev->period);
+	if (ret) {
+		dev_err(haptic->dev, "cannot configuration pwm\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int max77693_haptic_configure(struct max77693_haptic *haptic,
+						unsigned int enable)
+{
+	int ret;
+	unsigned int value = 0;
+
+	value = ((haptic->type << MAX77693_CONFIG2_MODE) |
+		(enable << MAX77693_CONFIG2_MEN) |
+		(haptic->mode << MAX77693_CONFIG2_HTYP) |
+		(haptic->pwm_divisor));
+
+	ret = regmap_write(haptic->regmap_haptic,
+				MAX77693_HAPTIC_REG_CONFIG2, value);
+	if (ret) {
+		dev_err(haptic->dev, "cannot write haptic regmap\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int max77693_haptic_lowsys(struct max77693_haptic *haptic,
+						unsigned int enable)
+{
+	int ret;
+
+	ret = regmap_update_bits(haptic->regmap_pmic,
+			MAX77693_PMIC_REG_LSCNFG,
+			MAX77693_PMIC_LOW_SYS_MASK,
+			enable << MAX77693_PMIC_LOW_SYS_SHIFT);
+	if (ret) {
+		dev_err(haptic->dev, "cannot update pmic regmap\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static void max77693_haptic_enable(struct max77693_haptic *haptic)
+{
+	int ret;
+
+	if (haptic->enabled)
+		return;
+
+	ret = pwm_enable(haptic->pwm_dev);
+	if (ret < 0) {
+		dev_err(haptic->dev, "cannot enable haptic pwm device");
+		return;
+	}
+
+	ret = regulator_enable(haptic->motor_reg);
+	if (ret) {
+		dev_err(haptic->dev, "cannot enable haptic regulator\n");
+		goto err_pwm_enable;
+	}
+
+	ret = max77693_haptic_lowsys(haptic, 1);
+	if (ret)
+		goto err_enable_lowsys;
+
+	ret = max77693_haptic_configure(haptic, 1);
+	if (ret < 0)
+		goto err_enable_config;
+
+	haptic->enabled = true;
+
+	return;
+
+err_enable_config:
+	max77693_haptic_lowsys(haptic, 0);
+err_enable_lowsys:
+	regulator_disable(haptic->motor_reg);
+err_pwm_enable:
+	pwm_disable(haptic->pwm_dev);
+}
+
+static void max77693_haptic_disable(struct max77693_haptic *haptic)
+{
+	int ret;
+
+	if (!haptic->enabled)
+		return;
+
+	ret = max77693_haptic_configure(haptic, 0);
+	if (ret < 0)
+		return;
+
+	ret = max77693_haptic_lowsys(haptic, 0);
+	if (ret)
+		goto err_disable_lowsys;
+
+	ret = regulator_disable(haptic->motor_reg);
+	if (ret) {
+		dev_err(haptic->dev, "cannot disable haptic regulator\n");
+		goto err_reg_disable;
+	}
+
+	pwm_disable(haptic->pwm_dev);
+	haptic->enabled = false;
+
+	return;
+
+err_reg_disable:
+	max77693_haptic_lowsys(haptic, 1);
+err_disable_lowsys:
+	max77693_haptic_configure(haptic, 1);
+}
+
+static void max77693_haptic_play_work(struct work_struct *work)
+{
+	struct max77693_haptic *haptic =
+			container_of(work, struct max77693_haptic, work);
+
+	mutex_lock(&haptic->mutex);
+	if (haptic->magnitude)
+		max77693_haptic_enable(haptic);
+	else
+		max77693_haptic_disable(haptic);
+	mutex_unlock(&haptic->mutex);
+}
+
+static int max77693_haptic_play_effect(struct input_dev *dev, void *data,
+				struct ff_effect *effect)
+{
+	struct max77693_haptic *haptic = input_get_drvdata(dev);
+	uint64_t period_mag_multi;
+	unsigned int pwm_duty;
+	int ret;
+
+	haptic->magnitude = effect->u.rumble.strong_magnitude;
+	if (!haptic->magnitude)
+		haptic->magnitude = effect->u.rumble.weak_magnitude;
+
+	/*
+	 * The magnitude comes from force-feedback interface.
+	 * The formula convert magnitude to pwm_duty as following:
+	 * - pwm_duty = (magnitude * pwm_period) / MAX_MAGNITUDE(0xFFFF)
+	 */
+	period_mag_multi = (int64_t)(haptic->pwm_dev->period *
+						haptic->magnitude);
+	pwm_duty = (unsigned int)(period_mag_multi >> MAX_MAGNITUDE_SHIFT);
+	ret = max77693_haptic_set_duty_cycle(haptic, pwm_duty);
+	if (ret)
+		return ret;
+
+	schedule_work(&haptic->work);
+
+	return 0;
+}
+
+static void max77693_haptic_close(struct input_dev *dev)
+{
+	struct max77693_haptic *haptic = input_get_drvdata(dev);
+
+	cancel_work_sync(&haptic->work);
+	max77693_haptic_disable(haptic);
+}
+
+static int max77693_haptic_probe(struct platform_device *pdev)
+{
+	struct max77693_dev *max77693 = dev_get_drvdata(pdev->dev.parent);
+	struct max77693_haptic *haptic;
+	int ret = 0;
+
+	haptic = devm_kzalloc(&pdev->dev, sizeof(*haptic), GFP_KERNEL);
+	if (!haptic)
+		return -ENOMEM;
+
+	haptic->regmap_pmic = max77693->regmap;
+	haptic->regmap_haptic = max77693->regmap_haptic;
+	haptic->dev = &pdev->dev;
+	haptic->type = MAX77693_HAPTIC_LRA;
+	haptic->mode = MAX77693_HAPTIC_EXTERNAL_MODE;
+	haptic->pwm_divisor = MAX77693_HAPTIC_PWM_DIVISOR_128;
+	mutex_init(&haptic->mutex);
+
+	/* Get pwm and regulatot for haptic device */
+	haptic->pwm_dev = devm_pwm_get(&pdev->dev, NULL);
+	if (IS_ERR(haptic->pwm_dev)) {
+		dev_err(&pdev->dev, "failed to get pwm device\n");
+		return PTR_ERR(haptic->pwm_dev);
+	}
+
+	haptic->motor_reg = devm_regulator_get(&pdev->dev, "haptic");
+	if (IS_ERR(haptic->motor_reg)) {
+		dev_err(&pdev->dev, "failed to get regulator\n");
+		return PTR_ERR(haptic->motor_reg);
+	}
+
+	/* Initialize input device for haptic device */
+	haptic->input_dev = devm_input_allocate_device(&pdev->dev);
+	if (!haptic->input_dev) {
+		dev_err(&pdev->dev, "failed to allocate input device\n");
+		return -ENOMEM;
+	}
+
+	haptic->input_dev->name = "max77693-haptic";
+	haptic->input_dev->id.version = 1;
+	haptic->input_dev->dev.parent = &pdev->dev;
+	haptic->input_dev->close = max77693_haptic_close;
+	input_set_drvdata(haptic->input_dev, haptic);
+	input_set_capability(haptic->input_dev, EV_FF, FF_RUMBLE);
+
+	ret = input_ff_create_memless(haptic->input_dev, NULL,
+				max77693_haptic_play_effect);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to create force-feedback\n");
+		return ret;
+	}
+
+	ret = input_register_device(haptic->input_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register input device\n");
+		goto err_input_device;
+	}
+
+	INIT_WORK(&haptic->work, max77693_haptic_play_work);
+
+	platform_set_drvdata(pdev, haptic);
+
+	return 0;
+
+err_input_device:
+	input_ff_destroy(haptic->input_dev);
+
+	return ret;
+}
+
+static int max77693_haptic_remove(struct platform_device *pdev)
+{
+	struct max77693_haptic *haptic = platform_get_drvdata(pdev);
+
+	max77693_haptic_disable(haptic);
+	input_unregister_device(haptic->input_dev);
+
+	return 0;
+}
+
+static struct platform_driver max77693_haptic_driver = {
+	.driver		= {
+		.name	= "max77693-haptic",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= max77693_haptic_probe,
+	.remove		= max77693_haptic_remove,
+};
+module_platform_driver(max77693_haptic_driver);
+
+MODULE_AUTHOR("Jaewon Kim <jaewon02.kim@samsung.com>");
+MODULE_DESCRIPTION("MAXIM MAX77693 Haptic driver");
+MODULE_ALIAS("platform:max77693-haptic");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/max77693-private.h b/include/linux/mfd/max77693-private.h
index c466ff3..d0e578f 100644
--- a/include/linux/mfd/max77693-private.h
+++ b/include/linux/mfd/max77693-private.h
@@ -251,6 +251,15 @@ enum max77693_haptic_reg {
 	MAX77693_HAPTIC_REG_END,
 };
 
+/* max77693-pmic LSCNFG configuraton register */
+#define MAX77693_PMIC_LOW_SYS_MASK      0x80
+#define MAX77693_PMIC_LOW_SYS_SHIFT     7
+
+/* max77693-haptic configuration register */
+#define MAX77693_CONFIG2_MODE           7
+#define MAX77693_CONFIG2_MEN            6
+#define MAX77693_CONFIG2_HTYP           5
+
 enum max77693_irq_source {
 	LED_INT = 0,
 	TOPSYS_INT,
-- 
1.7.9.5


^ permalink raw reply related

* Re: [PATCH v2 2/4] Input: misc: Add haptic driver on max77693
From: Dmitry Torokhov @ 2014-09-04 16:59 UTC (permalink / raw)
  To: Jaewon Kim
  Cc: Samuel Ortiz, Lee Jones, linux-kernel, linux-input, Chanwoo Choi
In-Reply-To: <1409842891-26549-3-git-send-email-jaewon02.kim@samsung.com>

Hi Jaewon,

On Fri, Sep 05, 2014 at 12:01:29AM +0900, Jaewon Kim wrote:
> This patch add max77693-haptic device driver to support the haptic controller
> on MAX77693. The MAX77693 is a Multifunction device with PMIC, CHARGER, LED,
> MUIC, HAPTIC and the patch is haptic device driver in the MAX77693. This driver
> support external pwm and LRA(Linear Resonant Actuator) motor. User can control
> the haptic driver by using force feedback framework.
> 
> Signed-off-by: Jaewon Kim <jaewon02.kim@samsung.com>
> Acked-by: Chanwoo Choi <cw00.choi@samsung.com>
> ---
>  drivers/input/misc/Kconfig           |   12 ++
>  drivers/input/misc/Makefile          |    1 +
>  drivers/input/misc/max77693-haptic.c |  333 ++++++++++++++++++++++++++++++++++
>  include/linux/mfd/max77693-private.h |    9 +
>  4 files changed, 355 insertions(+)
>  create mode 100644 drivers/input/misc/max77693-haptic.c
> 
> diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
> index 2ff4425..c597c52 100644
> --- a/drivers/input/misc/Kconfig
> +++ b/drivers/input/misc/Kconfig
> @@ -144,6 +144,18 @@ config INPUT_M68K_BEEP
>  	tristate "M68k Beeper support"
>  	depends on M68K
>  
> +config INPUT_MAX77693_HAPTIC
> +	tristate "MAXIM MAX77693 haptic controller support"
> +	depends on MFD_MAX77693 && PWM
> +	select INPUT_FF_MEMLESS
> +	help
> +	  This option enables device driver support for the haptic controller
> +	  on MAXIM MAX77693 chip. This driver supports ff-memless interface
> +	  from input framework.
> +
> +	  To compile this driver as module, choose M here: the
> +	  module will be called max77693-haptic.
> +
>  config INPUT_MAX8925_ONKEY
>  	tristate "MAX8925 ONKEY support"
>  	depends on MFD_MAX8925
> diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
> index 4955ad3..b28570c 100644
> --- a/drivers/input/misc/Makefile
> +++ b/drivers/input/misc/Makefile
> @@ -35,6 +35,7 @@ obj-$(CONFIG_INPUT_IXP4XX_BEEPER)	+= ixp4xx-beeper.o
>  obj-$(CONFIG_INPUT_KEYSPAN_REMOTE)	+= keyspan_remote.o
>  obj-$(CONFIG_INPUT_KXTJ9)		+= kxtj9.o
>  obj-$(CONFIG_INPUT_M68K_BEEP)		+= m68kspkr.o
> +obj-$(CONFIG_INPUT_MAX77693_HAPTIC)	+= max77693-haptic.o
>  obj-$(CONFIG_INPUT_MAX8925_ONKEY)	+= max8925_onkey.o
>  obj-$(CONFIG_INPUT_MAX8997_HAPTIC)	+= max8997_haptic.o
>  obj-$(CONFIG_INPUT_MC13783_PWRBUTTON)	+= mc13783-pwrbutton.o
> diff --git a/drivers/input/misc/max77693-haptic.c b/drivers/input/misc/max77693-haptic.c
> new file mode 100644
> index 0000000..2a69496
> --- /dev/null
> +++ b/drivers/input/misc/max77693-haptic.c
> @@ -0,0 +1,333 @@
> +/*
> + * max77693-haptic.c - MAXIM MAX77693 Haptic device driver
> + *
> + * Copyright (C) 2014 Samsung Electronics
> + * Jaewon Kim <jaewon02.kim@samsung.com>
> + *
> + * This program is not provided / owned by Maxim Integrated Products.
> + *
> + * 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/err.h>
> +#include <linux/init.h>
> +#include <linux/i2c.h>
> +#include <linux/regmap.h>
> +#include <linux/input.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/pwm.h>
> +#include <linux/slab.h>
> +#include <linux/workqueue.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/mfd/max77693.h>
> +#include <linux/mfd/max77693-private.h>
> +
> +#define MAX_MAGNITUDE_SHIFT	16
> +
> +enum max77693_haptic_motor_type {
> +	MAX77693_HAPTIC_ERM = 0,
> +	MAX77693_HAPTIC_LRA,
> +};
> +
> +enum max77693_haptic_pulse_mode {
> +	MAX77693_HAPTIC_EXTERNAL_MODE = 0,
> +	MAX77693_HAPTIC_INTERNAL_MODE,
> +};
> +
> +enum max77693_haptic_pwm_divisor {
> +	MAX77693_HAPTIC_PWM_DIVISOR_32 = 0,
> +	MAX77693_HAPTIC_PWM_DIVISOR_64,
> +	MAX77693_HAPTIC_PWM_DIVISOR_128,
> +	MAX77693_HAPTIC_PWM_DIVISOR_256,
> +};
> +
> +struct max77693_haptic {
> +	struct regmap *regmap_pmic;
> +	struct regmap *regmap_haptic;
> +	struct device *dev;
> +	struct input_dev *input_dev;
> +	struct pwm_device *pwm_dev;
> +	struct regulator *motor_reg;
> +
> +	bool enabled;
> +	unsigned int magnitude;
> +	enum max77693_haptic_motor_type type;
> +	enum max77693_haptic_pulse_mode mode;
> +	enum max77693_haptic_pwm_divisor pwm_divisor;
> +
> +	struct mutex mutex;
> +	struct work_struct work;
> +};
> +
> +static int max77693_haptic_set_duty_cycle(struct max77693_haptic *haptic,
> +						unsigned int pwm_duty)
> +{
> +	int ret;
> +	int delta = (haptic->pwm_dev->period + pwm_duty)/2;
> +
> +	ret = pwm_config(haptic->pwm_dev, delta, haptic->pwm_dev->period);
> +	if (ret) {
> +		dev_err(haptic->dev, "cannot configuration pwm\n");
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int max77693_haptic_configure(struct max77693_haptic *haptic,
> +						unsigned int enable)
> +{
> +	int ret;
> +	unsigned int value = 0;
> +
> +	value = ((haptic->type << MAX77693_CONFIG2_MODE) |
> +		(enable << MAX77693_CONFIG2_MEN) |
> +		(haptic->mode << MAX77693_CONFIG2_HTYP) |
> +		(haptic->pwm_divisor));
> +
> +	ret = regmap_write(haptic->regmap_haptic,
> +				MAX77693_HAPTIC_REG_CONFIG2, value);
> +	if (ret) {
> +		dev_err(haptic->dev, "cannot write haptic regmap\n");
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int max77693_haptic_lowsys(struct max77693_haptic *haptic,
> +						unsigned int enable)
> +{
> +	int ret;
> +
> +	ret = regmap_update_bits(haptic->regmap_pmic,
> +			MAX77693_PMIC_REG_LSCNFG,
> +			MAX77693_PMIC_LOW_SYS_MASK,
> +			enable << MAX77693_PMIC_LOW_SYS_SHIFT);
> +	if (ret) {
> +		dev_err(haptic->dev, "cannot update pmic regmap\n");
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static void max77693_haptic_enable(struct max77693_haptic *haptic)
> +{
> +	int ret;
> +
> +	if (haptic->enabled)
> +		return;
> +
> +	ret = pwm_enable(haptic->pwm_dev);
> +	if (ret < 0) {
> +		dev_err(haptic->dev, "cannot enable haptic pwm device");
> +		return;
> +	}
> +
> +	ret = regulator_enable(haptic->motor_reg);
> +	if (ret) {
> +		dev_err(haptic->dev, "cannot enable haptic regulator\n");
> +		goto err_pwm_enable;
> +	}
> +
> +	ret = max77693_haptic_lowsys(haptic, 1);
> +	if (ret)
> +		goto err_enable_lowsys;
> +
> +	ret = max77693_haptic_configure(haptic, 1);
> +	if (ret < 0)
> +		goto err_enable_config;
> +
> +	haptic->enabled = true;
> +
> +	return;
> +
> +err_enable_config:
> +	max77693_haptic_lowsys(haptic, 0);
> +err_enable_lowsys:
> +	regulator_disable(haptic->motor_reg);
> +err_pwm_enable:
> +	pwm_disable(haptic->pwm_dev);
> +}
> +
> +static void max77693_haptic_disable(struct max77693_haptic *haptic)
> +{
> +	int ret;
> +
> +	if (!haptic->enabled)
> +		return;
> +
> +	ret = max77693_haptic_configure(haptic, 0);
> +	if (ret < 0)

Why sometimes you test for negative errors and sometimes for != 0 from the same
MFD core? Can you settle on one, preferably 0/!0, in which case please also call
local local variables holding the result 'error' so that you have sequences:

	error = action();
	if (error)
		handle_error;

> +		return;
> +
> +	ret = max77693_haptic_lowsys(haptic, 0);
> +	if (ret)
> +		goto err_disable_lowsys;
> +
> +	ret = regulator_disable(haptic->motor_reg);
> +	if (ret) {
> +		dev_err(haptic->dev, "cannot disable haptic regulator\n");
> +		goto err_reg_disable;
> +	}
> +
> +	pwm_disable(haptic->pwm_dev);
> +	haptic->enabled = false;
> +
> +	return;
> +
> +err_reg_disable:
> +	max77693_haptic_lowsys(haptic, 1);
> +err_disable_lowsys:
> +	max77693_haptic_configure(haptic, 1);
> +}
> +
> +static void max77693_haptic_play_work(struct work_struct *work)
> +{
> +	struct max77693_haptic *haptic =
> +			container_of(work, struct max77693_haptic, work);
> +
> +	mutex_lock(&haptic->mutex);

Workqueues are not reentrant by default, you do not need this mutex.

> +	if (haptic->magnitude)
> +		max77693_haptic_enable(haptic);
> +	else
> +		max77693_haptic_disable(haptic);

Hmm, do you really want to bounce regulator on and off on every buzz? I guess
it may save some power...

> +	mutex_unlock(&haptic->mutex);
> +}
> +
> +static int max77693_haptic_play_effect(struct input_dev *dev, void *data,
> +				struct ff_effect *effect)
> +{
> +	struct max77693_haptic *haptic = input_get_drvdata(dev);
> +	uint64_t period_mag_multi;
> +	unsigned int pwm_duty;
> +	int ret;
> +
> +	haptic->magnitude = effect->u.rumble.strong_magnitude;
> +	if (!haptic->magnitude)
> +		haptic->magnitude = effect->u.rumble.weak_magnitude;
> +
> +	/*
> +	 * The magnitude comes from force-feedback interface.
> +	 * The formula convert magnitude to pwm_duty as following:
> +	 * - pwm_duty = (magnitude * pwm_period) / MAX_MAGNITUDE(0xFFFF)
> +	 */
> +	period_mag_multi = (int64_t)(haptic->pwm_dev->period *
> +						haptic->magnitude);
> +	pwm_duty = (unsigned int)(period_mag_multi >> MAX_MAGNITUDE_SHIFT);
> +	ret = max77693_haptic_set_duty_cycle(haptic, pwm_duty);

Why is this done here and not in max77693_haptic_play_work? Is it even safe to
access the device here (you are running under a spinlock with interrupts off).

> +	if (ret)
> +		return ret;
> +
> +	schedule_work(&haptic->work);
> +
> +	return 0;
> +}
> +
> +static void max77693_haptic_close(struct input_dev *dev)
> +{
> +	struct max77693_haptic *haptic = input_get_drvdata(dev);
> +
> +	cancel_work_sync(&haptic->work);
> +	max77693_haptic_disable(haptic);
> +}
> +
> +static int max77693_haptic_probe(struct platform_device *pdev)
> +{
> +	struct max77693_dev *max77693 = dev_get_drvdata(pdev->dev.parent);
> +	struct max77693_haptic *haptic;
> +	int ret = 0;
> +
> +	haptic = devm_kzalloc(&pdev->dev, sizeof(*haptic), GFP_KERNEL);
> +	if (!haptic)
> +		return -ENOMEM;
> +
> +	haptic->regmap_pmic = max77693->regmap;
> +	haptic->regmap_haptic = max77693->regmap_haptic;
> +	haptic->dev = &pdev->dev;
> +	haptic->type = MAX77693_HAPTIC_LRA;
> +	haptic->mode = MAX77693_HAPTIC_EXTERNAL_MODE;
> +	haptic->pwm_divisor = MAX77693_HAPTIC_PWM_DIVISOR_128;
> +	mutex_init(&haptic->mutex);
> +
> +	/* Get pwm and regulatot for haptic device */
> +	haptic->pwm_dev = devm_pwm_get(&pdev->dev, NULL);
> +	if (IS_ERR(haptic->pwm_dev)) {
> +		dev_err(&pdev->dev, "failed to get pwm device\n");
> +		return PTR_ERR(haptic->pwm_dev);
> +	}
> +
> +	haptic->motor_reg = devm_regulator_get(&pdev->dev, "haptic");
> +	if (IS_ERR(haptic->motor_reg)) {
> +		dev_err(&pdev->dev, "failed to get regulator\n");
> +		return PTR_ERR(haptic->motor_reg);
> +	}
> +
> +	/* Initialize input device for haptic device */
> +	haptic->input_dev = devm_input_allocate_device(&pdev->dev);
> +	if (!haptic->input_dev) {
> +		dev_err(&pdev->dev, "failed to allocate input device\n");
> +		return -ENOMEM;
> +	}
> +
> +	haptic->input_dev->name = "max77693-haptic";
> +	haptic->input_dev->id.version = 1;
> +	haptic->input_dev->dev.parent = &pdev->dev;
> +	haptic->input_dev->close = max77693_haptic_close;
> +	input_set_drvdata(haptic->input_dev, haptic);
> +	input_set_capability(haptic->input_dev, EV_FF, FF_RUMBLE);
> +
> +	ret = input_ff_create_memless(haptic->input_dev, NULL,
> +				max77693_haptic_play_effect);
> +	if (ret) {
> +		dev_err(&pdev->dev, "failed to create force-feedback\n");
> +		return ret;
> +	}
> +
> +	ret = input_register_device(haptic->input_dev);
> +	if (ret) {
> +		dev_err(&pdev->dev, "failed to register input device\n");
> +		goto err_input_device;
> +	}
> +
> +	INIT_WORK(&haptic->work, max77693_haptic_play_work);
> +
> +	platform_set_drvdata(pdev, haptic);
> +
> +	return 0;
> +
> +err_input_device:
> +	input_ff_destroy(haptic->input_dev);

No need to call, will be done automatically.

> +
> +	return ret;
> +}
> +
> +static int max77693_haptic_remove(struct platform_device *pdev)
> +{
> +	struct max77693_haptic *haptic = platform_get_drvdata(pdev);
> +
> +	max77693_haptic_disable(haptic);

It is done in close() so no need to cal here.

> +	input_unregister_device(haptic->input_dev);

You are using devm so no need to call it either. Just remove
max77693_haptic_remove() altogether.

What you need I think is suspend/resume to make sure the device is shut off
when system is suspending.

> +
> +	return 0;
> +}
> +
> +static struct platform_driver max77693_haptic_driver = {
> +	.driver		= {
> +		.name	= "max77693-haptic",
> +		.owner	= THIS_MODULE,
> +	},
> +	.probe		= max77693_haptic_probe,
> +	.remove		= max77693_haptic_remove,
> +};
> +module_platform_driver(max77693_haptic_driver);
> +
> +MODULE_AUTHOR("Jaewon Kim <jaewon02.kim@samsung.com>");
> +MODULE_DESCRIPTION("MAXIM MAX77693 Haptic driver");
> +MODULE_ALIAS("platform:max77693-haptic");
> +MODULE_LICENSE("GPL");
> diff --git a/include/linux/mfd/max77693-private.h b/include/linux/mfd/max77693-private.h
> index c466ff3..d0e578f 100644
> --- a/include/linux/mfd/max77693-private.h
> +++ b/include/linux/mfd/max77693-private.h
> @@ -251,6 +251,15 @@ enum max77693_haptic_reg {
>  	MAX77693_HAPTIC_REG_END,
>  };
>  
> +/* max77693-pmic LSCNFG configuraton register */
> +#define MAX77693_PMIC_LOW_SYS_MASK      0x80
> +#define MAX77693_PMIC_LOW_SYS_SHIFT     7
> +
> +/* max77693-haptic configuration register */
> +#define MAX77693_CONFIG2_MODE           7
> +#define MAX77693_CONFIG2_MEN            6
> +#define MAX77693_CONFIG2_HTYP           5
> +
>  enum max77693_irq_source {
>  	LED_INT = 0,
>  	TOPSYS_INT,
> -- 
> 1.7.9.5
> 

Thanks.

-- 
Dmitry

^ permalink raw reply

* [PATCH] mfd: ti_am335x_tscadc: Update logic in CTRL register for 5-wire TS
From: Sebastian Andrzej Siewior @ 2014-09-04 17:01 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-input, Felipe Balbi, linux-omap, Samuel Ortiz, Lee Jones,
	Jeff Lance, Sebastian Andrzej Siewior

From: Jeff Lance <j-lance1@ti.com>

The logic in AFE_Pen_Ctrl bitmask in the CTRL register is different for five
wire versus four or eight wire touschscreens. This patch should fix this for
five-wire touch screens. There should be no change needed here for four and
eight wire tousch screens.

Signed-off-by: Jeff Lance <j-lance1@ti.com>
[bigeasy: keep the change mfd only]
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
I've been looking at moving this piece and the idle mode setting into the
TSC driver. Kinda odd that I have to patch within the MFD driver for this
TSC related change.
Anyone disagrees?

 drivers/mfd/ti_am335x_tscadc.c       | 30 +++++++++++++++++-------------
 include/linux/mfd/ti_am335x_tscadc.h |  1 +
 2 files changed, 18 insertions(+), 13 deletions(-)

diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
index dd4bf5816221..6c9cfb8c1d01 100644
--- a/drivers/mfd/ti_am335x_tscadc.c
+++ b/drivers/mfd/ti_am335x_tscadc.c
@@ -241,18 +241,20 @@ static	int ti_tscadc_probe(struct platform_device *pdev)
 	tscadc_writel(tscadc, REG_CLKDIV, tscadc->clk_div);
 
 	/* Set the control register bits */
-	ctrl = CNTRLREG_STEPCONFIGWRT |
-			CNTRLREG_STEPID;
-	if (tsc_wires > 0)
-		ctrl |= CNTRLREG_4WIRE | CNTRLREG_TSCENB;
+	ctrl = CNTRLREG_STEPCONFIGWRT |	CNTRLREG_STEPID;
 	tscadc_writel(tscadc, REG_CTRL, ctrl);
 
 	/* Set register bits for Idle Config Mode */
-	if (tsc_wires > 0)
+	if (tsc_wires > 0) {
+		tscadc->tsc_wires = tsc_wires;
+		if (tsc_wires == 5)
+			ctrl |= CNTRLREG_5WIRE | CNTRLREG_TSCENB;
+		else
+			ctrl |= CNTRLREG_4WIRE | CNTRLREG_TSCENB;
 		tscadc_idle_config(tscadc);
+	}
 
 	/* Enable the TSC module enable bit */
-	ctrl = tscadc_readl(tscadc, REG_CTRL);
 	ctrl |= CNTRLREG_TSCSSENB;
 	tscadc_writel(tscadc, REG_CTRL, ctrl);
 
@@ -324,21 +326,23 @@ static int tscadc_suspend(struct device *dev)
 static int tscadc_resume(struct device *dev)
 {
 	struct ti_tscadc_dev	*tscadc_dev = dev_get_drvdata(dev);
-	unsigned int restore, ctrl;
+	u32 ctrl;
 
 	pm_runtime_get_sync(dev);
 
 	/* context restore */
 	ctrl = CNTRLREG_STEPCONFIGWRT |	CNTRLREG_STEPID;
-	if (tscadc_dev->tsc_cell != -1)
-		ctrl |= CNTRLREG_TSCENB | CNTRLREG_4WIRE;
 	tscadc_writel(tscadc_dev, REG_CTRL, ctrl);
 
-	if (tscadc_dev->tsc_cell != -1)
+	if (tscadc_dev->tsc_cell != -1) {
+		if (tscadc_dev->tsc_wires == 5)
+			ctrl |= CNTRLREG_5WIRE | CNTRLREG_TSCENB;
+		else
+			ctrl |= CNTRLREG_4WIRE | CNTRLREG_TSCENB;
 		tscadc_idle_config(tscadc_dev);
-	restore = tscadc_readl(tscadc_dev, REG_CTRL);
-	tscadc_writel(tscadc_dev, REG_CTRL,
-			(restore | CNTRLREG_TSCSSENB));
+	}
+	ctrl |= CNTRLREG_TSCSSENB;
+	tscadc_writel(tscadc_dev, REG_CTRL, ctrl);
 
 	tscadc_writel(tscadc_dev, REG_CLKDIV, tscadc_dev->clk_div);
 
diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
index fb96c84dada5..e2e70053470e 100644
--- a/include/linux/mfd/ti_am335x_tscadc.h
+++ b/include/linux/mfd/ti_am335x_tscadc.h
@@ -155,6 +155,7 @@ struct ti_tscadc_dev {
 	void __iomem *tscadc_base;
 	int irq;
 	int used_cells;	/* 1-2 */
+	int tsc_wires;
 	int tsc_cell;	/* -1 if not used */
 	int adc_cell;	/* -1 if not used */
 	struct mfd_cell cells[TSCADC_CELLS];
-- 
2.1.0

^ permalink raw reply related

* [PATCH] HID: Add Holtek USB ID 04d9:a0c2 ETEKCITY Scroll
From: John DeSilva @ 2014-09-05  1:08 UTC (permalink / raw)
  To: jkosina; +Cc: linux-input, linux-kernel, John DeSilva

The report descriptor for the HOLTEK USB ID 04d9:a0c2 (ETEKCITY Scroll
T-140 Gaming Mouse) is set to a very large amount of consumer usages
(2^16), exceeding HID_MAX_USAGES. Added id, bindings and comments for
the mouse, and reduced the usage and logical maximums to 0x2fff,
consistent with the other mice in the category.
Tested on the hardware.

Signed-off-by: John C. DeSilva <desilvjo@umich.edu>
---
 drivers/hid/hid-holtek-mouse.c | 4 ++++
 drivers/hid/hid-ids.h          | 1 +
 2 files changed, 5 insertions(+)

diff --git a/drivers/hid/hid-holtek-mouse.c b/drivers/hid/hid-holtek-mouse.c
index d60fbd0..78b3a0c 100644
--- a/drivers/hid/hid-holtek-mouse.c
+++ b/drivers/hid/hid-holtek-mouse.c
@@ -29,6 +29,7 @@
  *   and Zalman ZM-GM1
  * - USB ID 04d9:a081, sold as SHARKOON DarkGlider Gaming mouse
  * - USB ID 04d9:a072, sold as LEETGION Hellion Gaming Mouse
+ * - USB ID 04d9:a0c2, sold as ETEKCITY Scroll T-140 Gaming Mouse
  */
 
 static __u8 *holtek_mouse_report_fixup(struct hid_device *hdev, __u8 *rdesc,
@@ -42,6 +43,7 @@ static __u8 *holtek_mouse_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 		switch (hdev->product) {
 		case USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067:
 		case USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A072:
+		case USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A0C2:
 			if (*rsize >= 122 && rdesc[115] == 0xff && rdesc[116] == 0x7f
 					&& rdesc[120] == 0xff && rdesc[121] == 0x7f) {
 				hid_info(hdev, "Fixing up report descriptor\n");
@@ -74,6 +76,8 @@ static const struct hid_device_id holtek_mouse_devices[] = {
 			USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A072) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT,
 			USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT,
+			USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A0C2) },
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, holtek_mouse_devices);
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 25cd674..c7b36ad 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -479,6 +479,7 @@
 #define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A070	0xa070
 #define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A072	0xa072
 #define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081	0xa081
+#define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A0C2	0xa0c2
 #define USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD_A096	0xa096
 
 #define USB_VENDOR_ID_IMATION		0x0718
-- 
1.8.5.5


^ permalink raw reply related

* Re: [PATCH v2 2/4] Input: misc: Add haptic driver on max77693
From: Jaewon Kim @ 2014-09-05  3:00 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Samuel Ortiz, Lee Jones, linux-kernel, linux-input, Chanwoo Choi
In-Reply-To: <20140904165958.GA10224@core.coreip.homeip.net>

Hi Dmitry Torokhov

thanks to review my patchs.

2014년 09월 05일 01:59에 Dmitry Torokhov 이(가) 쓴 글:
> Hi Jaewon,
>
> On Fri, Sep 05, 2014 at 12:01:29AM +0900, Jaewon Kim wrote:
>> This patch add max77693-haptic device driver to support the haptic controller
>> on MAX77693. The MAX77693 is a Multifunction device with PMIC, CHARGER, LED,
>> MUIC, HAPTIC and the patch is haptic device driver in the MAX77693. This driver
>> support external pwm and LRA(Linear Resonant Actuator) motor. User can control
>> the haptic driver by using force feedback framework.
>>
>> Signed-off-by: Jaewon Kim <jaewon02.kim@samsung.com>
>> Acked-by: Chanwoo Choi <cw00.choi@samsung.com>
>> ---
>>   drivers/input/misc/Kconfig           |   12 ++
>>   drivers/input/misc/Makefile          |    1 +
>>   drivers/input/misc/max77693-haptic.c |  333 ++++++++++++++++++++++++++++++++++
>>   include/linux/mfd/max77693-private.h |    9 +
>>   4 files changed, 355 insertions(+)
>>   create mode 100644 drivers/input/misc/max77693-haptic.c
>>
>> diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
>> index 2ff4425..c597c52 100644
>> --- a/drivers/input/misc/Kconfig
>> +++ b/drivers/input/misc/Kconfig
>> @@ -144,6 +144,18 @@ config INPUT_M68K_BEEP
>>   	tristate "M68k Beeper support"
>>   	depends on M68K
>>   
>> +config INPUT_MAX77693_HAPTIC
>> +	tristate "MAXIM MAX77693 haptic controller support"
>> +	depends on MFD_MAX77693 && PWM
>> +	select INPUT_FF_MEMLESS
>> +	help
>> +	  This option enables device driver support for the haptic controller
>> +	  on MAXIM MAX77693 chip. This driver supports ff-memless interface
>> +	  from input framework.
>> +
>> +	  To compile this driver as module, choose M here: the
>> +	  module will be called max77693-haptic.
>> +
>>   config INPUT_MAX8925_ONKEY
>>   	tristate "MAX8925 ONKEY support"
>>   	depends on MFD_MAX8925
>> diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
>> index 4955ad3..b28570c 100644
>> --- a/drivers/input/misc/Makefile
>> +++ b/drivers/input/misc/Makefile
>> @@ -35,6 +35,7 @@ obj-$(CONFIG_INPUT_IXP4XX_BEEPER)	+= ixp4xx-beeper.o
>>   obj-$(CONFIG_INPUT_KEYSPAN_REMOTE)	+= keyspan_remote.o
>>   obj-$(CONFIG_INPUT_KXTJ9)		+= kxtj9.o
>>   obj-$(CONFIG_INPUT_M68K_BEEP)		+= m68kspkr.o
>> +obj-$(CONFIG_INPUT_MAX77693_HAPTIC)	+= max77693-haptic.o
>>   obj-$(CONFIG_INPUT_MAX8925_ONKEY)	+= max8925_onkey.o
>>   obj-$(CONFIG_INPUT_MAX8997_HAPTIC)	+= max8997_haptic.o
>>   obj-$(CONFIG_INPUT_MC13783_PWRBUTTON)	+= mc13783-pwrbutton.o
>> diff --git a/drivers/input/misc/max77693-haptic.c b/drivers/input/misc/max77693-haptic.c
>> new file mode 100644
>> index 0000000..2a69496
>> --- /dev/null
>> +++ b/drivers/input/misc/max77693-haptic.c
>> @@ -0,0 +1,333 @@
>> +/*
>> + * max77693-haptic.c - MAXIM MAX77693 Haptic device driver
>> + *
>> + * Copyright (C) 2014 Samsung Electronics
>> + * Jaewon Kim <jaewon02.kim@samsung.com>
>> + *
>> + * This program is not provided / owned by Maxim Integrated Products.
>> + *
>> + * 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/err.h>
>> +#include <linux/init.h>
>> +#include <linux/i2c.h>
>> +#include <linux/regmap.h>
>> +#include <linux/input.h>
>> +#include <linux/module.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/pwm.h>
>> +#include <linux/slab.h>
>> +#include <linux/workqueue.h>
>> +#include <linux/regulator/consumer.h>
>> +#include <linux/mfd/max77693.h>
>> +#include <linux/mfd/max77693-private.h>
>> +
>> +#define MAX_MAGNITUDE_SHIFT	16
>> +
>> +enum max77693_haptic_motor_type {
>> +	MAX77693_HAPTIC_ERM = 0,
>> +	MAX77693_HAPTIC_LRA,
>> +};
>> +
>> +enum max77693_haptic_pulse_mode {
>> +	MAX77693_HAPTIC_EXTERNAL_MODE = 0,
>> +	MAX77693_HAPTIC_INTERNAL_MODE,
>> +};
>> +
>> +enum max77693_haptic_pwm_divisor {
>> +	MAX77693_HAPTIC_PWM_DIVISOR_32 = 0,
>> +	MAX77693_HAPTIC_PWM_DIVISOR_64,
>> +	MAX77693_HAPTIC_PWM_DIVISOR_128,
>> +	MAX77693_HAPTIC_PWM_DIVISOR_256,
>> +};
>> +
>> +struct max77693_haptic {
>> +	struct regmap *regmap_pmic;
>> +	struct regmap *regmap_haptic;
>> +	struct device *dev;
>> +	struct input_dev *input_dev;
>> +	struct pwm_device *pwm_dev;
>> +	struct regulator *motor_reg;
>> +
>> +	bool enabled;
>> +	unsigned int magnitude;
>> +	enum max77693_haptic_motor_type type;
>> +	enum max77693_haptic_pulse_mode mode;
>> +	enum max77693_haptic_pwm_divisor pwm_divisor;
>> +
>> +	struct mutex mutex;
>> +	struct work_struct work;
>> +};
>> +
>> +static int max77693_haptic_set_duty_cycle(struct max77693_haptic *haptic,
>> +						unsigned int pwm_duty)
>> +{
>> +	int ret;
>> +	int delta = (haptic->pwm_dev->period + pwm_duty)/2;
>> +
>> +	ret = pwm_config(haptic->pwm_dev, delta, haptic->pwm_dev->period);
>> +	if (ret) {
>> +		dev_err(haptic->dev, "cannot configuration pwm\n");
>> +		return ret;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int max77693_haptic_configure(struct max77693_haptic *haptic,
>> +						unsigned int enable)
>> +{
>> +	int ret;
>> +	unsigned int value = 0;
>> +
>> +	value = ((haptic->type << MAX77693_CONFIG2_MODE) |
>> +		(enable << MAX77693_CONFIG2_MEN) |
>> +		(haptic->mode << MAX77693_CONFIG2_HTYP) |
>> +		(haptic->pwm_divisor));
>> +
>> +	ret = regmap_write(haptic->regmap_haptic,
>> +				MAX77693_HAPTIC_REG_CONFIG2, value);
>> +	if (ret) {
>> +		dev_err(haptic->dev, "cannot write haptic regmap\n");
>> +		return ret;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int max77693_haptic_lowsys(struct max77693_haptic *haptic,
>> +						unsigned int enable)
>> +{
>> +	int ret;
>> +
>> +	ret = regmap_update_bits(haptic->regmap_pmic,
>> +			MAX77693_PMIC_REG_LSCNFG,
>> +			MAX77693_PMIC_LOW_SYS_MASK,
>> +			enable << MAX77693_PMIC_LOW_SYS_SHIFT);
>> +	if (ret) {
>> +		dev_err(haptic->dev, "cannot update pmic regmap\n");
>> +		return ret;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static void max77693_haptic_enable(struct max77693_haptic *haptic)
>> +{
>> +	int ret;
>> +
>> +	if (haptic->enabled)
>> +		return;
>> +
>> +	ret = pwm_enable(haptic->pwm_dev);
>> +	if (ret < 0) {
>> +		dev_err(haptic->dev, "cannot enable haptic pwm device");
>> +		return;
>> +	}
>> +
>> +	ret = regulator_enable(haptic->motor_reg);
>> +	if (ret) {
>> +		dev_err(haptic->dev, "cannot enable haptic regulator\n");
>> +		goto err_pwm_enable;
>> +	}
>> +
>> +	ret = max77693_haptic_lowsys(haptic, 1);
>> +	if (ret)
>> +		goto err_enable_lowsys;
>> +
>> +	ret = max77693_haptic_configure(haptic, 1);
>> +	if (ret < 0)
>> +		goto err_enable_config;
>> +
>> +	haptic->enabled = true;
>> +
>> +	return;
>> +
>> +err_enable_config:
>> +	max77693_haptic_lowsys(haptic, 0);
>> +err_enable_lowsys:
>> +	regulator_disable(haptic->motor_reg);
>> +err_pwm_enable:
>> +	pwm_disable(haptic->pwm_dev);
>> +}
>> +
>> +static void max77693_haptic_disable(struct max77693_haptic *haptic)
>> +{
>> +	int ret;
>> +
>> +	if (!haptic->enabled)
>> +		return;
>> +
>> +	ret = max77693_haptic_configure(haptic, 0);
>> +	if (ret < 0)
> Why sometimes you test for negative errors and sometimes for != 0 from the same
> MFD core? Can you settle on one, preferably 0/!0, in which case please also call
> local local variables holding the result 'error' so that you have sequences:
>
> 	error = action();
> 	if (error)
> 		handle_error;
Ok, i will settle on.
>
>> +		return;
>> +
>> +	ret = max77693_haptic_lowsys(haptic, 0);
>> +	if (ret)
>> +		goto err_disable_lowsys;
>> +
>> +	ret = regulator_disable(haptic->motor_reg);
>> +	if (ret) {
>> +		dev_err(haptic->dev, "cannot disable haptic regulator\n");
>> +		goto err_reg_disable;
>> +	}
>> +
>> +	pwm_disable(haptic->pwm_dev);
>> +	haptic->enabled = false;
>> +
>> +	return;
>> +
>> +err_reg_disable:
>> +	max77693_haptic_lowsys(haptic, 1);
>> +err_disable_lowsys:
>> +	max77693_haptic_configure(haptic, 1);
>> +}
>> +
>> +static void max77693_haptic_play_work(struct work_struct *work)
>> +{
>> +	struct max77693_haptic *haptic =
>> +			container_of(work, struct max77693_haptic, work);
>> +
>> +	mutex_lock(&haptic->mutex);
> Workqueues are not reentrant by default, you do not need this mutex.
I will remove them.
>
>> +	if (haptic->magnitude)
>> +		max77693_haptic_enable(haptic);
>> +	else
>> +		max77693_haptic_disable(haptic);
> Hmm, do you really want to bounce regulator on and off on every buzz? I guess
> it may save some power...
Yes, You are right.

>
>> +	mutex_unlock(&haptic->mutex);
>> +}
>> +
>> +static int max77693_haptic_play_effect(struct input_dev *dev, void *data,
>> +				struct ff_effect *effect)
>> +{
>> +	struct max77693_haptic *haptic = input_get_drvdata(dev);
>> +	uint64_t period_mag_multi;
>> +	unsigned int pwm_duty;
>> +	int ret;
>> +
>> +	haptic->magnitude = effect->u.rumble.strong_magnitude;
>> +	if (!haptic->magnitude)
>> +		haptic->magnitude = effect->u.rumble.weak_magnitude;
>> +
>> +	/*
>> +	 * The magnitude comes from force-feedback interface.
>> +	 * The formula convert magnitude to pwm_duty as following:
>> +	 * - pwm_duty = (magnitude * pwm_period) / MAX_MAGNITUDE(0xFFFF)
>> +	 */
>> +	period_mag_multi = (int64_t)(haptic->pwm_dev->period *
>> +						haptic->magnitude);
>> +	pwm_duty = (unsigned int)(period_mag_multi >> MAX_MAGNITUDE_SHIFT);
>> +	ret = max77693_haptic_set_duty_cycle(haptic, pwm_duty);
> Why is this done here and not in max77693_haptic_play_work? Is it even safe to
> access the device here (you are running under a spinlock with interrupts off).
I miss that is in spinlock.
max77693_haptic_set_duty_cycle() will move in workqueue.

>
>> +	if (ret)
>> +		return ret;
>> +
>> +	schedule_work(&haptic->work);
>> +
>> +	return 0;
>> +}
>> +
>> +static void max77693_haptic_close(struct input_dev *dev)
>> +{
>> +	struct max77693_haptic *haptic = input_get_drvdata(dev);
>> +
>> +	cancel_work_sync(&haptic->work);
>> +	max77693_haptic_disable(haptic);
>> +}
>> +
>> +static int max77693_haptic_probe(struct platform_device *pdev)
>> +{
>> +	struct max77693_dev *max77693 = dev_get_drvdata(pdev->dev.parent);
>> +	struct max77693_haptic *haptic;
>> +	int ret = 0;
>> +
>> +	haptic = devm_kzalloc(&pdev->dev, sizeof(*haptic), GFP_KERNEL);
>> +	if (!haptic)
>> +		return -ENOMEM;
>> +
>> +	haptic->regmap_pmic = max77693->regmap;
>> +	haptic->regmap_haptic = max77693->regmap_haptic;
>> +	haptic->dev = &pdev->dev;
>> +	haptic->type = MAX77693_HAPTIC_LRA;
>> +	haptic->mode = MAX77693_HAPTIC_EXTERNAL_MODE;
>> +	haptic->pwm_divisor = MAX77693_HAPTIC_PWM_DIVISOR_128;
>> +	mutex_init(&haptic->mutex);
>> +
>> +	/* Get pwm and regulatot for haptic device */
>> +	haptic->pwm_dev = devm_pwm_get(&pdev->dev, NULL);
>> +	if (IS_ERR(haptic->pwm_dev)) {
>> +		dev_err(&pdev->dev, "failed to get pwm device\n");
>> +		return PTR_ERR(haptic->pwm_dev);
>> +	}
>> +
>> +	haptic->motor_reg = devm_regulator_get(&pdev->dev, "haptic");
>> +	if (IS_ERR(haptic->motor_reg)) {
>> +		dev_err(&pdev->dev, "failed to get regulator\n");
>> +		return PTR_ERR(haptic->motor_reg);
>> +	}
>> +
>> +	/* Initialize input device for haptic device */
>> +	haptic->input_dev = devm_input_allocate_device(&pdev->dev);
>> +	if (!haptic->input_dev) {
>> +		dev_err(&pdev->dev, "failed to allocate input device\n");
>> +		return -ENOMEM;
>> +	}
>> +
>> +	haptic->input_dev->name = "max77693-haptic";
>> +	haptic->input_dev->id.version = 1;
>> +	haptic->input_dev->dev.parent = &pdev->dev;
>> +	haptic->input_dev->close = max77693_haptic_close;
>> +	input_set_drvdata(haptic->input_dev, haptic);
>> +	input_set_capability(haptic->input_dev, EV_FF, FF_RUMBLE);
>> +
>> +	ret = input_ff_create_memless(haptic->input_dev, NULL,
>> +				max77693_haptic_play_effect);
>> +	if (ret) {
>> +		dev_err(&pdev->dev, "failed to create force-feedback\n");
>> +		return ret;
>> +	}
>> +
>> +	ret = input_register_device(haptic->input_dev);
>> +	if (ret) {
>> +		dev_err(&pdev->dev, "failed to register input device\n");
>> +		goto err_input_device;
>> +	}
>> +
>> +	INIT_WORK(&haptic->work, max77693_haptic_play_work);
>> +
>> +	platform_set_drvdata(pdev, haptic);
>> +
>> +	return 0;
>> +
>> +err_input_device:
>> +	input_ff_destroy(haptic->input_dev);
> No need to call, will be done automatically.
>
>> +
>> +	return ret;
>> +}
>> +
>> +static int max77693_haptic_remove(struct platform_device *pdev)
>> +{
>> +	struct max77693_haptic *haptic = platform_get_drvdata(pdev);
>> +
>> +	max77693_haptic_disable(haptic);
> It is done in close() so no need to cal here.
>
>> +	input_unregister_device(haptic->input_dev);
> You are using devm so no need to call it either. Just remove
> max77693_haptic_remove() altogether.
Ok. i will remove unnecessary unregister functions.

>
> What you need I think is suspend/resume to make sure the device is shut off
> when system is suspending.

If haptic motor buzzing when device entening suspend state, i turn off 
motor.
but, i think resume code not necessary in this driver.
>> +
>> +	return 0;
>> +}
>> +
>> +static struct platform_driver max77693_haptic_driver = {
>> +	.driver		= {
>> +		.name	= "max77693-haptic",
>> +		.owner	= THIS_MODULE,
>> +	},
>> +	.probe		= max77693_haptic_probe,
>> +	.remove		= max77693_haptic_remove,
>> +};
>> +module_platform_driver(max77693_haptic_driver);
>> +
>> +MODULE_AUTHOR("Jaewon Kim <jaewon02.kim@samsung.com>");
>> +MODULE_DESCRIPTION("MAXIM MAX77693 Haptic driver");
>> +MODULE_ALIAS("platform:max77693-haptic");
>> +MODULE_LICENSE("GPL");
>> diff --git a/include/linux/mfd/max77693-private.h b/include/linux/mfd/max77693-private.h
>> index c466ff3..d0e578f 100644
>> --- a/include/linux/mfd/max77693-private.h
>> +++ b/include/linux/mfd/max77693-private.h
>> @@ -251,6 +251,15 @@ enum max77693_haptic_reg {
>>   	MAX77693_HAPTIC_REG_END,
>>   };
>>   
>> +/* max77693-pmic LSCNFG configuraton register */
>> +#define MAX77693_PMIC_LOW_SYS_MASK      0x80
>> +#define MAX77693_PMIC_LOW_SYS_SHIFT     7
>> +
>> +/* max77693-haptic configuration register */
>> +#define MAX77693_CONFIG2_MODE           7
>> +#define MAX77693_CONFIG2_MEN            6
>> +#define MAX77693_CONFIG2_HTYP           5
>> +
>>   enum max77693_irq_source {
>>   	LED_INT = 0,
>>   	TOPSYS_INT,
>> -- 
>> 1.7.9.5
>>
> Thanks.
>

Thanks
Jaewon Kim.
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH] HID: Add Holtek USB ID 04d9:a0c2 ETEKCITY Scroll
From: Jiri Kosina @ 2014-09-05  8:35 UTC (permalink / raw)
  To: John DeSilva; +Cc: linux-input, linux-kernel
In-Reply-To: <1409879285-15816-1-git-send-email-desilvjo@umich.edu>

On Thu, 4 Sep 2014, John DeSilva wrote:

> The report descriptor for the HOLTEK USB ID 04d9:a0c2 (ETEKCITY Scroll
> T-140 Gaming Mouse) is set to a very large amount of consumer usages
> (2^16), exceeding HID_MAX_USAGES. Added id, bindings and comments for
> the mouse, and reduced the usage and logical maximums to 0x2fff,
> consistent with the other mice in the category.
> Tested on the hardware.
> 
> Signed-off-by: John C. DeSilva <desilvjo@umich.edu>

Thanks for the patch.

> ---
>  drivers/hid/hid-holtek-mouse.c | 4 ++++
>  drivers/hid/hid-ids.h          | 1 +
>  2 files changed, 5 insertions(+)
> 
> diff --git a/drivers/hid/hid-holtek-mouse.c b/drivers/hid/hid-holtek-mouse.c
> index d60fbd0..78b3a0c 100644
> --- a/drivers/hid/hid-holtek-mouse.c
> +++ b/drivers/hid/hid-holtek-mouse.c
> @@ -29,6 +29,7 @@
>   *   and Zalman ZM-GM1
>   * - USB ID 04d9:a081, sold as SHARKOON DarkGlider Gaming mouse
>   * - USB ID 04d9:a072, sold as LEETGION Hellion Gaming Mouse
> + * - USB ID 04d9:a0c2, sold as ETEKCITY Scroll T-140 Gaming Mouse
>   */
>  
>  static __u8 *holtek_mouse_report_fixup(struct hid_device *hdev, __u8 *rdesc,
> @@ -42,6 +43,7 @@ static __u8 *holtek_mouse_report_fixup(struct hid_device *hdev, __u8 *rdesc,
>  		switch (hdev->product) {
>  		case USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067:
>  		case USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A072:
> +		case USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A0C2:
>  			if (*rsize >= 122 && rdesc[115] == 0xff && rdesc[116] == 0x7f
>  					&& rdesc[120] == 0xff && rdesc[121] == 0x7f) {
>  				hid_info(hdev, "Fixing up report descriptor\n");
> @@ -74,6 +76,8 @@ static const struct hid_device_id holtek_mouse_devices[] = {
>  			USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A072) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT,
>  			USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081) },
> +	{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT,
> +			USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A0C2) },

You also need entry in hid_have_special_driver[] to make sure that 
hid-core doesn't override hid-holtek-mouse.

Could you please fix that and resend? Thanks.

>  	{ }
>  };
>  MODULE_DEVICE_TABLE(hid, holtek_mouse_devices);
> diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
> index 25cd674..c7b36ad 100644
> --- a/drivers/hid/hid-ids.h
> +++ b/drivers/hid/hid-ids.h
> @@ -479,6 +479,7 @@
>  #define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A070	0xa070
>  #define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A072	0xa072
>  #define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081	0xa081
> +#define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A0C2	0xa0c2
>  #define USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD_A096	0xa096
>  
>  #define USB_VENDOR_ID_IMATION		0x0718
> -- 
> 1.8.5.5
> 

-- 
Jiri Kosina
SUSE Labs

^ permalink raw reply

* [PATCH v3 0/4] Add max77693 haptic driver
From: Jaewon Kim @ 2014-09-05 11:48 UTC (permalink / raw)
  To: Dmitry Torokhov, Samuel Ortiz, Lee Jones
  Cc: linux-kernel, linux-input, Chanwoo Choi, Jaewon Kim

This series adds max77693 haptic driver.
The max77693 is a Multifunction device with PMIC, CHARGER, LED,
MUIC, HAPTIC and this series is haptic device driver in MAX77693.
The haptic driver use regmap method for i2c communication and
support force feedback framework in input device.

Changes in v3:
 - driver : remove mutex in workqueue
 - driver : mv max77693_haptic_set_duty_cyle() to workqueue.
 - driver : remove max77693_haptic_remove[]
 - driver : add suspend() function to turn-off entering suspend.

Changes in v2:
 - split to documentation and mfd patchs.
 - Documentation : change explanation of haptic 
 - Documentation : remove pwm-names propertie in example

Jaewon Kim (4):
  mfd: max77693: Initialize haptic register map
  Input: misc: Add haptic driver on max77693
  mfd: max77693: add haptic of_compatible in mfd_cell
  mfd: max77693: Update DT binding to support haptic

 Documentation/devicetree/bindings/mfd/max77693.txt |   18 ++
 drivers/input/misc/Kconfig                         |   12 +
 drivers/input/misc/Makefile                        |    1 +
 drivers/input/misc/max77693-haptic.c               |  321 ++++++++++++++++++++
 drivers/mfd/max77693.c                             |   26 +-
 include/linux/mfd/max77693-private.h               |    9 +
 6 files changed, 383 insertions(+), 4 deletions(-)
 create mode 100644 drivers/input/misc/max77693-haptic.c

-- 
1.7.9.5

^ permalink raw reply

* [PATCH v3 2/4] Input: misc: Add haptic driver on max77693
From: Jaewon Kim @ 2014-09-05 11:48 UTC (permalink / raw)
  To: Dmitry Torokhov, Samuel Ortiz, Lee Jones
  Cc: linux-kernel, linux-input, Chanwoo Choi, Jaewon Kim
In-Reply-To: <1409917702-17009-1-git-send-email-jaewon02.kim@samsung.com>

This patch add max77693-haptic device driver to support the haptic controller
on MAX77693. The MAX77693 is a Multifunction device with PMIC, CHARGER, LED,
MUIC, HAPTIC and the patch is haptic device driver in the MAX77693. This driver
support external pwm and LRA(Linear Resonant Actuator) motor. User can control
the haptic driver by using force feedback framework.

Signed-off-by: Jaewon Kim <jaewon02.kim@samsung.com>
Acked-by: Chanwoo Choi <cw00.choi@samsung.com>
---
 drivers/input/misc/Kconfig           |   12 ++
 drivers/input/misc/Makefile          |    1 +
 drivers/input/misc/max77693-haptic.c |  321 ++++++++++++++++++++++++++++++++++
 include/linux/mfd/max77693-private.h |    9 +
 4 files changed, 343 insertions(+)
 create mode 100644 drivers/input/misc/max77693-haptic.c

diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 2ff4425..c597c52 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -144,6 +144,18 @@ config INPUT_M68K_BEEP
 	tristate "M68k Beeper support"
 	depends on M68K
 
+config INPUT_MAX77693_HAPTIC
+	tristate "MAXIM MAX77693 haptic controller support"
+	depends on MFD_MAX77693 && PWM
+	select INPUT_FF_MEMLESS
+	help
+	  This option enables device driver support for the haptic controller
+	  on MAXIM MAX77693 chip. This driver supports ff-memless interface
+	  from input framework.
+
+	  To compile this driver as module, choose M here: the
+	  module will be called max77693-haptic.
+
 config INPUT_MAX8925_ONKEY
 	tristate "MAX8925 ONKEY support"
 	depends on MFD_MAX8925
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 4955ad3..b28570c 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_INPUT_IXP4XX_BEEPER)	+= ixp4xx-beeper.o
 obj-$(CONFIG_INPUT_KEYSPAN_REMOTE)	+= keyspan_remote.o
 obj-$(CONFIG_INPUT_KXTJ9)		+= kxtj9.o
 obj-$(CONFIG_INPUT_M68K_BEEP)		+= m68kspkr.o
+obj-$(CONFIG_INPUT_MAX77693_HAPTIC)	+= max77693-haptic.o
 obj-$(CONFIG_INPUT_MAX8925_ONKEY)	+= max8925_onkey.o
 obj-$(CONFIG_INPUT_MAX8997_HAPTIC)	+= max8997_haptic.o
 obj-$(CONFIG_INPUT_MC13783_PWRBUTTON)	+= mc13783-pwrbutton.o
diff --git a/drivers/input/misc/max77693-haptic.c b/drivers/input/misc/max77693-haptic.c
new file mode 100644
index 0000000..d06026b
--- /dev/null
+++ b/drivers/input/misc/max77693-haptic.c
@@ -0,0 +1,321 @@
+/*
+ * max77693-haptic.c - MAXIM MAX77693 Haptic device driver
+ *
+ * Copyright (C) 2014 Samsung Electronics
+ * Jaewon Kim <jaewon02.kim@samsung.com>
+ *
+ * This program is not provided / owned by Maxim Integrated Products.
+ *
+ * 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/err.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/regulator/consumer.h>
+#include <linux/mfd/max77693.h>
+#include <linux/mfd/max77693-private.h>
+
+#define MAX_MAGNITUDE_SHIFT	16
+
+enum max77693_haptic_motor_type {
+	MAX77693_HAPTIC_ERM = 0,
+	MAX77693_HAPTIC_LRA,
+};
+
+enum max77693_haptic_pulse_mode {
+	MAX77693_HAPTIC_EXTERNAL_MODE = 0,
+	MAX77693_HAPTIC_INTERNAL_MODE,
+};
+
+enum max77693_haptic_pwm_divisor {
+	MAX77693_HAPTIC_PWM_DIVISOR_32 = 0,
+	MAX77693_HAPTIC_PWM_DIVISOR_64,
+	MAX77693_HAPTIC_PWM_DIVISOR_128,
+	MAX77693_HAPTIC_PWM_DIVISOR_256,
+};
+
+struct max77693_haptic {
+	struct regmap *regmap_pmic;
+	struct regmap *regmap_haptic;
+	struct device *dev;
+	struct input_dev *input_dev;
+	struct pwm_device *pwm_dev;
+	struct regulator *motor_reg;
+
+	bool enabled;
+	unsigned int magnitude;
+	unsigned int pwm_duty;
+	enum max77693_haptic_motor_type type;
+	enum max77693_haptic_pulse_mode mode;
+	enum max77693_haptic_pwm_divisor pwm_divisor;
+
+	struct work_struct work;
+};
+
+static int max77693_haptic_set_duty_cycle(struct max77693_haptic *haptic)
+{
+	int ret;
+	int delta = (haptic->pwm_dev->period + haptic->pwm_duty)/2;
+
+	ret = pwm_config(haptic->pwm_dev, delta, haptic->pwm_dev->period);
+	if (ret) {
+		dev_err(haptic->dev, "cannot configuration pwm\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int max77693_haptic_configure(struct max77693_haptic *haptic,
+						unsigned int enable)
+{
+	int ret;
+	unsigned int value = 0;
+
+	value = ((haptic->type << MAX77693_CONFIG2_MODE) |
+		(enable << MAX77693_CONFIG2_MEN) |
+		(haptic->mode << MAX77693_CONFIG2_HTYP) |
+		(haptic->pwm_divisor));
+
+	ret = regmap_write(haptic->regmap_haptic,
+				MAX77693_HAPTIC_REG_CONFIG2, value);
+	if (ret) {
+		dev_err(haptic->dev, "cannot write haptic regmap\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int max77693_haptic_lowsys(struct max77693_haptic *haptic,
+						unsigned int enable)
+{
+	int ret;
+
+	ret = regmap_update_bits(haptic->regmap_pmic,
+			MAX77693_PMIC_REG_LSCNFG,
+			MAX77693_PMIC_LOW_SYS_MASK,
+			enable << MAX77693_PMIC_LOW_SYS_SHIFT);
+	if (ret) {
+		dev_err(haptic->dev, "cannot update pmic regmap\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static void max77693_haptic_enable(struct max77693_haptic *haptic)
+{
+	int ret;
+
+	if (haptic->enabled)
+		return;
+
+	ret = pwm_enable(haptic->pwm_dev);
+	if (ret) {
+		dev_err(haptic->dev, "cannot enable haptic pwm device");
+		return;
+	}
+
+	ret = max77693_haptic_lowsys(haptic, 1);
+	if (ret)
+		goto err_enable_lowsys;
+
+	ret = max77693_haptic_configure(haptic, 1);
+	if (ret)
+		goto err_enable_config;
+
+	haptic->enabled = true;
+
+	return;
+
+err_enable_config:
+	max77693_haptic_lowsys(haptic, 0);
+err_enable_lowsys:
+	pwm_disable(haptic->pwm_dev);
+}
+
+static void max77693_haptic_disable(struct max77693_haptic *haptic)
+{
+	int ret;
+
+	if (!haptic->enabled)
+		return;
+
+	ret = max77693_haptic_configure(haptic, 0);
+	if (ret)
+		return;
+
+	ret = max77693_haptic_lowsys(haptic, 0);
+	if (ret)
+		goto err_disable_lowsys;
+
+	pwm_disable(haptic->pwm_dev);
+	haptic->enabled = false;
+
+	return;
+
+err_disable_lowsys:
+	max77693_haptic_configure(haptic, 1);
+}
+
+static void max77693_haptic_play_work(struct work_struct *work)
+{
+	struct max77693_haptic *haptic =
+			container_of(work, struct max77693_haptic, work);
+	int ret;
+
+	ret = max77693_haptic_set_duty_cycle(haptic);
+	if (ret) {
+		dev_err(haptic->dev, "cannot set duty cycle\n");
+		return;
+	}
+
+	if (haptic->magnitude)
+		max77693_haptic_enable(haptic);
+	else
+		max77693_haptic_disable(haptic);
+}
+
+static int max77693_haptic_play_effect(struct input_dev *dev, void *data,
+				struct ff_effect *effect)
+{
+	struct max77693_haptic *haptic = input_get_drvdata(dev);
+	uint64_t period_mag_multi;
+
+	haptic->magnitude = effect->u.rumble.strong_magnitude;
+	if (!haptic->magnitude)
+		haptic->magnitude = effect->u.rumble.weak_magnitude;
+
+	/*
+	 * The magnitude comes from force-feedback interface.
+	 * The formula convert magnitude to pwm_duty as following:
+	 * - pwm_duty = (magnitude * pwm_period) / MAX_MAGNITUDE(0xFFFF)
+	 */
+	period_mag_multi = (int64_t)(haptic->pwm_dev->period *
+						haptic->magnitude);
+	haptic->pwm_duty = (unsigned int)(period_mag_multi >>
+						MAX_MAGNITUDE_SHIFT);
+
+	schedule_work(&haptic->work);
+
+	return 0;
+}
+
+static void max77693_haptic_close(struct input_dev *dev)
+{
+	struct max77693_haptic *haptic = input_get_drvdata(dev);
+
+	cancel_work_sync(&haptic->work);
+	max77693_haptic_disable(haptic);
+}
+
+static int max77693_haptic_probe(struct platform_device *pdev)
+{
+	struct max77693_dev *max77693 = dev_get_drvdata(pdev->dev.parent);
+	struct max77693_haptic *haptic;
+	int ret = 0;
+
+	haptic = devm_kzalloc(&pdev->dev, sizeof(*haptic), GFP_KERNEL);
+	if (!haptic)
+		return -ENOMEM;
+
+	haptic->regmap_pmic = max77693->regmap;
+	haptic->regmap_haptic = max77693->regmap_haptic;
+	haptic->dev = &pdev->dev;
+	haptic->type = MAX77693_HAPTIC_LRA;
+	haptic->mode = MAX77693_HAPTIC_EXTERNAL_MODE;
+	haptic->pwm_divisor = MAX77693_HAPTIC_PWM_DIVISOR_128;
+
+	/* Get pwm and regulatot for haptic device */
+	haptic->pwm_dev = devm_pwm_get(&pdev->dev, NULL);
+	if (IS_ERR(haptic->pwm_dev)) {
+		dev_err(&pdev->dev, "failed to get pwm device\n");
+		return PTR_ERR(haptic->pwm_dev);
+	}
+
+	haptic->motor_reg = devm_regulator_get(&pdev->dev, "haptic");
+	if (IS_ERR(haptic->motor_reg)) {
+		dev_err(&pdev->dev, "failed to get regulator\n");
+		return PTR_ERR(haptic->motor_reg);
+	}
+
+	ret = regulator_enable(haptic->motor_reg);
+	if (ret) {
+		dev_err(haptic->dev, "failed to enable regulator\n");
+		return ret;
+	}
+
+	/* Initialize input device for haptic device */
+	haptic->input_dev = devm_input_allocate_device(&pdev->dev);
+	if (!haptic->input_dev) {
+		dev_err(&pdev->dev, "failed to allocate input device\n");
+		return -ENOMEM;
+	}
+
+	haptic->input_dev->name = "max77693-haptic";
+	haptic->input_dev->id.version = 1;
+	haptic->input_dev->dev.parent = &pdev->dev;
+	haptic->input_dev->close = max77693_haptic_close;
+	input_set_drvdata(haptic->input_dev, haptic);
+	input_set_capability(haptic->input_dev, EV_FF, FF_RUMBLE);
+
+	ret = input_ff_create_memless(haptic->input_dev, NULL,
+				max77693_haptic_play_effect);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to create force-feedback\n");
+		return ret;
+	}
+
+	ret = input_register_device(haptic->input_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register input device\n");
+		return ret;
+	}
+
+	INIT_WORK(&haptic->work, max77693_haptic_play_work);
+
+	platform_set_drvdata(pdev, haptic);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int max77693_haptic_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct max77693_haptic *haptic = platform_get_drvdata(pdev);
+
+	max77693_haptic_disable(haptic);
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(max77693_haptic_pm_ops, max77693_haptic_suspend, NULL);
+
+static struct platform_driver max77693_haptic_driver = {
+	.driver		= {
+		.name	= "max77693-haptic",
+		.owner	= THIS_MODULE,
+		.pm	= &max77693_haptic_pm_ops,
+	},
+	.probe		= max77693_haptic_probe,
+};
+module_platform_driver(max77693_haptic_driver);
+
+MODULE_AUTHOR("Jaewon Kim <jaewon02.kim@samsung.com>");
+MODULE_DESCRIPTION("MAXIM MAX77693 Haptic driver");
+MODULE_ALIAS("platform:max77693-haptic");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/max77693-private.h b/include/linux/mfd/max77693-private.h
index c466ff3..d0e578f 100644
--- a/include/linux/mfd/max77693-private.h
+++ b/include/linux/mfd/max77693-private.h
@@ -251,6 +251,15 @@ enum max77693_haptic_reg {
 	MAX77693_HAPTIC_REG_END,
 };
 
+/* max77693-pmic LSCNFG configuraton register */
+#define MAX77693_PMIC_LOW_SYS_MASK      0x80
+#define MAX77693_PMIC_LOW_SYS_SHIFT     7
+
+/* max77693-haptic configuration register */
+#define MAX77693_CONFIG2_MODE           7
+#define MAX77693_CONFIG2_MEN            6
+#define MAX77693_CONFIG2_HTYP           5
+
 enum max77693_irq_source {
 	LED_INT = 0,
 	TOPSYS_INT,
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH v3 3/4] mfd: max77693: add haptic of_compatible in mfd_cell
From: Jaewon Kim @ 2014-09-05 11:48 UTC (permalink / raw)
  To: Dmitry Torokhov, Samuel Ortiz, Lee Jones
  Cc: linux-kernel, linux-input, Chanwoo Choi, Jaewon Kim
In-Reply-To: <1409917702-17009-1-git-send-email-jaewon02.kim@samsung.com>

This patch add haptic of_compatible in order to use the haptic
device driver using Devicetree.

Signed-off-by: Jaewon Kim <jaewon02.kim@samsung.com>
Acked-by: Chanwoo Choi <cw00.choi@samsung.com>
---
 drivers/mfd/max77693.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c
index fbfed56..03fd431 100644
--- a/drivers/mfd/max77693.c
+++ b/drivers/mfd/max77693.c
@@ -46,7 +46,10 @@ static const struct mfd_cell max77693_devs[] = {
 	{ .name = "max77693-charger", },
 	{ .name = "max77693-flash", },
 	{ .name = "max77693-muic", },
-	{ .name = "max77693-haptic", },
+	{
+	  .name = "max77693-haptic",
+	  .of_compatible = "maxim,max77693-haptic",
+	},
 };
 
 static const struct regmap_config max77693_regmap_config = {
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH v3 4/4] mfd: max77693: Update DT binding to support haptic
From: Jaewon Kim @ 2014-09-05 11:48 UTC (permalink / raw)
  To: Dmitry Torokhov, Samuel Ortiz, Lee Jones
  Cc: linux-kernel, linux-input, Chanwoo Choi, Jaewon Kim
In-Reply-To: <1409917702-17009-1-git-send-email-jaewon02.kim@samsung.com>

This patch add haptic DT binding documentation and example
to support haptic driver in max77693 Multifunction device.

Signed-off-by: Jaewon Kim <jaewon02.kim@samsung.com>
Acked-by: Chanwoo Choi <cw00.choi@samsung.com>
---
 Documentation/devicetree/bindings/mfd/max77693.txt |   18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/Documentation/devicetree/bindings/mfd/max77693.txt b/Documentation/devicetree/bindings/mfd/max77693.txt
index 11921cc..d178b9e 100644
--- a/Documentation/devicetree/bindings/mfd/max77693.txt
+++ b/Documentation/devicetree/bindings/mfd/max77693.txt
@@ -27,6 +27,17 @@ Optional properties:
 
 	[*] refer Documentation/devicetree/bindings/regulator/regulator.txt
 
+- haptic : The haptic of max77693 have to be instantiated under subnod
+  named "haptic" using the following haptic format in example.
+  Haptic sensation from motor can be changed by changing a period cycle in pwms.
+
+ Required properties:
+	- compatible : Must be "maxim,max77693-hpatic"
+	- haptic-supply : power supply for haptic motor
+		[*] refer Documentation/devicetree/bindings/regulator/regulator.txt
+	- pwms : phandle to the physical PWM device,
+		[*] refer Documentation/devicetree/bindings/pwm/pwm.txt
+
 Example:
 	max77693@66 {
 		compatible = "maxim,max77693";
@@ -52,4 +63,11 @@ Example:
 					regulator-boot-on;
 			};
 		};
+
+		haptic {
+			compatible = "maxim,max77693-haptic";
+			haptic-supply = <&haptic_supply>;
+			pwms = <&pwm 0 40000 0>;
+			pwm-names = "haptic";
+		};
 	};
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v3 1/4] mfd: max77693: Initialize haptic register map
From: Jaewon Kim @ 2014-09-05 11:48 UTC (permalink / raw)
  To: Dmitry Torokhov, Samuel Ortiz, Lee Jones
  Cc: linux-kernel, linux-input, Chanwoo Choi, Jaewon Kim
In-Reply-To: <1409917702-17009-1-git-send-email-jaewon02.kim@samsung.com>

This patch add regmap_haptic initialization to use haptic register map
in haptic device driver.

Signed-off-by: Jaewon Kim <jaewon02.kim@samsung.com>
Acked-by: Chanwoo Choi <cw00.choi@samsung.com>
Acked-by: Lee Jones <lee.jones@linaro.org>
---
 drivers/mfd/max77693.c |   21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c
index 249c139..fbfed56 100644
--- a/drivers/mfd/max77693.c
+++ b/drivers/mfd/max77693.c
@@ -144,6 +144,12 @@ static const struct regmap_irq_chip max77693_muic_irq_chip = {
 	.num_irqs		= ARRAY_SIZE(max77693_muic_irqs),
 };
 
+static const struct regmap_config max77693_regmap_haptic_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = MAX77693_HAPTIC_REG_END,
+};
+
 static int max77693_i2c_probe(struct i2c_client *i2c,
 			      const struct i2c_device_id *id)
 {
@@ -193,6 +199,15 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
 	}
 	i2c_set_clientdata(max77693->haptic, max77693);
 
+	max77693->regmap_haptic = devm_regmap_init_i2c(max77693->haptic,
+					&max77693_regmap_haptic_config);
+	if (IS_ERR(max77693->regmap_haptic)) {
+		ret = PTR_ERR(max77693->regmap_haptic);
+		dev_err(max77693->dev,
+			"failed to initialize haptic register map: %d\n", ret);
+		goto err_regmap;
+	}
+
 	/*
 	 * Initialize register map for MUIC device because use regmap-muic
 	 * instance of MUIC device when irq of max77693 is initialized
@@ -204,7 +219,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
 		ret = PTR_ERR(max77693->regmap_muic);
 		dev_err(max77693->dev,
 			"failed to allocate register map: %d\n", ret);
-		goto err_regmap_muic;
+		goto err_regmap;
 	}
 
 	ret = regmap_add_irq_chip(max77693->regmap, max77693->irq,
@@ -214,7 +229,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
 				&max77693->irq_data_led);
 	if (ret) {
 		dev_err(max77693->dev, "failed to add irq chip: %d\n", ret);
-		goto err_regmap_muic;
+		goto err_regmap;
 	}
 
 	ret = regmap_add_irq_chip(max77693->regmap, max77693->irq,
@@ -265,7 +280,7 @@ err_irq_charger:
 	regmap_del_irq_chip(max77693->irq, max77693->irq_data_topsys);
 err_irq_topsys:
 	regmap_del_irq_chip(max77693->irq, max77693->irq_data_led);
-err_regmap_muic:
+err_regmap:
 	i2c_unregister_device(max77693->haptic);
 err_i2c_haptic:
 	i2c_unregister_device(max77693->muic);
-- 
1.7.9.5


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox