* Re: Microsoft Surface Pro 3 Type Cover keyboard
From: Benjamin Tissoires @ 2014-11-03 15:28 UTC (permalink / raw)
To: Jiri Kosina; +Cc: Jarrad Whitaker, linux-input, Alan Wu
In-Reply-To: <alpine.LNX.2.00.1411031431150.19451@pobox.suse.cz>
On Mon, Nov 3, 2014 at 8:33 AM, Jiri Kosina <jkosina@suse.cz> wrote:
> On Fri, 24 Oct 2014, Jarrad Whitaker wrote:
>
>> The keyboard on the Surface Pro 3 type cover does not function without
>> some patching, similar to what was apparently required for the SP2
>> type/touch covers.
>>
>> A working patch against 3.16 attached, it's an amalgamation of "some
>> dude posted this on the ubuntu/arch forums and it seems to work" so
>> I'm making no claims that it's kernel-quality! Just trying to give a
>> better indication of what needs to be added. My C is rudimentary and
>> my knowledge of the kernel limited to 'fakeroot debian/rules
>> updateconfigs', sorry. :)
>> Happy to test any improved version, but note I only have a type, not a
>> touch cover.
>>
>> Patch source is
>> http://winaero.com/blog/how-to-install-linux-on-surface-pro-3/, which
>> in turn sources a Russian site.
>
> Hi,
>
> thanks. Adding Alan Wu to CC, who sent me a slightly different patch for
> this issue -- see the archives of linux-input list from a few days back.
>
> Your patch is missing at least Signed-off-by: line, and also seems to lack
> the update to hid_have_special_driver[].
Jiri, actually, the hid_have_special_driver entry is not 100% required
to make it work (though it would be cleaner, I agree).
Actually, the TypeCover presents a Precision TouchPad, so hid-core
considers it should have the hid-multitouch driver driving it (see
https://bugzilla.redhat.com/show_bug.cgi?id=1135338 )
I am not sure we should use hid-multtiouch or hid-microsoft. My guess
is that both will work, but hid-multitouch might provide true raw
reporting for the touchpad. On the other hand, maybe hid-microsoft
will bind special keys that hid-multitouch will not...
If the path is to go through hid-microsoft, then Jarrad, Alan, yes,
please, add your device to hid_have_special_driver.
Cheers,
Benjamin
>
> Could you two guys please cooperate and send me a patch that should be
> applied? I don't have the device so can't really test properly myself.
>
> Thanks,
>
> --
> Jiri Kosina
> SUSE Labs
> --
> 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 1/3] mfd: stmpe: add pull up/down register offsets for STMPE
From: Linus Walleij @ 2014-11-03 15:27 UTC (permalink / raw)
To: Lee Jones
Cc: Dmitry Torokhov, Samuel Ortiz, linux-kernel@vger.kernel.org,
Linux Input
In-Reply-To: <20141103125732.GF4538@x1>
On Mon, Nov 3, 2014 at 1:57 PM, Lee Jones <lee.jones@linaro.org> wrote:
> On Mon, 03 Nov 2014, Linus Walleij wrote:
>
>> Lee, can Dmitry take these through input?
>
> That was weird, I replied at the same as as you sent this.
Synchronicity... :)
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH 2/4] input: touchscreen: ti_am335x_tsc: Remove udelay in interrupt handler
From: Lee Jones @ 2014-11-03 15:05 UTC (permalink / raw)
To: Vignesh R
Cc: Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
Benoit Cousson, Tony Lindgren, Russell King, Jonathan Cameron,
Dmitry Torokhov, Hartmut Knaack, Lars-Peter Clausen,
Peter Meerwald, Samuel Ortiz, Felipe Balbi,
Sebastian Andrzej Siewior, Jan Kardell, Paul Gortmaker,
Brad Griffis, devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-omap-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-iio-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1414408111-2631-3-git-send-email-vigneshr-l0cyMroinI0@public.gmane.org>
On Mon, 27 Oct 2014, Vignesh R wrote:
> From: Brad Griffis <bgriffis-l0cyMroinI0@public.gmane.org>
>
> TSC interrupt handler had udelay to avoid reporting of false pen-up
> interrupt to user space. This patch implements workaround suggesting in
> Advisory 1.0.31 of silicon errata for am335x, thus eliminating udelay
> and touchscreen lag. This also improves performance of touchscreen and
> eliminates sudden jump of cursor at touch release.
>
> IDLECONFIG and CHARGECONFIG registers are to be configured
> with same values in order to eliminate false pen-up events. This
> workaround may result in false pen-down to be detected, hence considerable
> charge step delay needs to be added. The charge delay is set to 0xB000
> (in terms of ADC clock cycles) by default.
>
> TSC steps are disabled at the end of every sampling cycle and EOS bit is
> set. Once the EOS bit is set, the TSC steps need to be re-enabled to begin
> next sampling cycle.
>
> In one shot mode, sequencer automatically disables all enabled steps at
> the end of each cycle. (both ADC steps and TSC steps) Hence these steps
> need not be saved in reg_se_cache for clearing these steps at a later
> stage.
>
> Signed-off-by: Brad Griffis <bgriffis-l0cyMroinI0@public.gmane.org>
> [vigneshr-l0cyMroinI0@public.gmane.org: Ported patch from v3.12 to v3.18rc2]
> Signed-off-by: Vignesh R <vigneshr-l0cyMroinI0@public.gmane.org>
> ---
> drivers/input/touchscreen/ti_am335x_tsc.c | 56 ++++++++++++-------------------
> drivers/mfd/ti_am335x_tscadc.c | 7 ++--
> include/linux/mfd/ti_am335x_tscadc.h | 4 ++-
> 3 files changed, 30 insertions(+), 37 deletions(-)
[...]
> diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
> index d877e777cce6..94ef8992f46b 100644
> --- a/drivers/mfd/ti_am335x_tscadc.c
> +++ b/drivers/mfd/ti_am335x_tscadc.c
> @@ -86,8 +86,12 @@ static void am335x_tscadc_need_adc(struct ti_tscadc_dev *tsadc)
> spin_lock_irq(&tsadc->reg_lock);
> finish_wait(&tsadc->reg_se_wait, &wait);
>
> + /*
> + * Sequencer should either be idle or
> + * busy applying the charge step.
> + */
> reg = tscadc_readl(tsadc, REG_ADCFSM);
> - WARN_ON(reg & SEQ_STATUS);
> + WARN_ON(reg & SEQ_STATUS & (!CHARGE_STEP));
> tsadc->adc_waiting = false;
> }
> tsadc->adc_in_use = true;
> @@ -96,7 +100,6 @@ static void am335x_tscadc_need_adc(struct ti_tscadc_dev *tsadc)
> void am335x_tsc_se_set_once(struct ti_tscadc_dev *tsadc, u32 val)
> {
> spin_lock_irq(&tsadc->reg_lock);
> - tsadc->reg_se_cache |= val;
> am335x_tscadc_need_adc(tsadc);
>
> tscadc_writel(tsadc, REG_SE, val);
I believe all of these changes can, and therefor should live in a
separate patch.
> diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
> index e2e70053470e..fcce182e4a35 100644
> --- a/include/linux/mfd/ti_am335x_tscadc.h
> +++ b/include/linux/mfd/ti_am335x_tscadc.h
> @@ -52,6 +52,7 @@
>
> /* IRQ enable */
> #define IRQENB_HW_PEN BIT(0)
> +#define IRQENB_EOS BIT(1)
> #define IRQENB_FIFO0THRES BIT(2)
> #define IRQENB_FIFO0OVRRUN BIT(3)
> #define IRQENB_FIFO0UNDRFLW BIT(4)
> @@ -107,7 +108,7 @@
> /* Charge delay */
> #define CHARGEDLY_OPEN_MASK (0x3FFFF << 0)
> #define CHARGEDLY_OPEN(val) ((val) << 0)
> -#define CHARGEDLY_OPENDLY CHARGEDLY_OPEN(1)
> +#define CHARGEDLY_OPENDLY CHARGEDLY_OPEN(0xB000)
>
> /* Control register */
> #define CNTRLREG_TSCSSENB BIT(0)
> @@ -127,6 +128,7 @@
>
> /* Sequencer Status */
> #define SEQ_STATUS BIT(5)
> +#define CHARGE_STEP 0x11
>
> #define ADC_CLK 3000000
> #define TOTAL_STEPS 16
The header changes should be split between the two Input and MFD
patches.
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply
* Re: [PATCH 02/15] GPIO: port LoCoMo gpio support from old driver
From: Linus Walleij @ 2014-11-03 13:43 UTC (permalink / raw)
To: Dmitry Eremin-Solenikov
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
linux-gpio-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Linux Input,
linux-leds-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-spi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-fbdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw@public.gmane.org, Andrea Adami,
Russell King, Daniel Mack, Haojian Zhuang, Robert Jarzmik,
Alexandre Courbot, Dmitry Torokhov, Bryan Wu, Richard Purdie,
Samuel Ortiz, Lee Jones, Mark Brown, Jingoo
In-Reply-To: <CALT56yOgMUA7o2dzfHph=S2zkDV4zERzMh4ishpPwpAx7Cqj6Q-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
On Fri, Oct 31, 2014 at 10:39 AM, Dmitry Eremin-Solenikov
<dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> 2014-10-31 10:48 GMT+03:00 Linus Walleij <linus.walleij-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>:
>> On Tue, Oct 28, 2014 at 1:01 AM, Dmitry Eremin-Solenikov
>> <dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>>
>>> Add gpiolib driver for gpio pins placed on the LoCoMo GA.
>>>
>>> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>>
>
> [skipped]
>
>> (etc, everywhere this pattern occurs).
>>> +static void locomo_gpio_set(struct gpio_chip *chip,
>>> + unsigned offset, int value)
>>> +{
>>> + struct locomo_gpio *lg = container_of(chip, struct locomo_gpio, gpio);
>>> + unsigned long flags;
>>> +
>>> + spin_lock_irqsave(&lg->lock, flags);
>>> +
>>> + __locomo_gpio_set(chip, offset, value);
>>> +
>>> + spin_unlock_irqrestore(&lg->lock, flags);
>>
>> If you actually always have to be getting and releasing a spin lock around
>> the register writes, contemplate using regmap-mmio because that
>> is part of what it does.
>>
>> But is this locking really necessary?
>
> I have a custom of doing such locking and never having to think about
> somebody breaking into RMW cycles.
>
> Also isn't regmap an overkill here? Wouldn't regmap also do a lock/unlock
> around each register read/write/RMW?
Yes that's the point: if you use regmap mmio you get the RMW-locking
for free, with the regmap implementation.
Yours,
Linus Walleij
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 01/15] mfd: add new driver for Sharp LoCoMo
From: Linus Walleij @ 2014-11-03 13:41 UTC (permalink / raw)
To: Dmitry Eremin-Solenikov
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
linux-gpio-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Linux Input,
linux-leds-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-spi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-fbdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw@public.gmane.org, Andrea Adami,
Russell King, Daniel Mack, Haojian Zhuang, Robert Jarzmik,
Alexandre Courbot, Dmitry Torokhov, Bryan Wu, Richard Purdie,
Samuel Ortiz, Lee Jones, Mark Brown, Jingoo
In-Reply-To: <CALT56yNX8v4mZn=o1ZoVLHPmg6wq0dgFNowpqNuFtU=eCc+d8w-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
On Fri, Oct 31, 2014 at 10:54 AM, Dmitry Eremin-Solenikov
<dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> 2014-10-31 10:42 GMT+03:00 Linus Walleij <linus.walleij-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>:
>> It seems some DAC handling is part of the MFD driver, and we recently
>> discussed that MFD should not be doing misc stuff but mainly act as
>> arbiter and switching station.
>>
>> Can you please move the DAC parts of the driver to
>> drivers/iio/dac?
>>
>> The IIO DAC subsystem will likely add other goodies to
>> the driver for free and give a nice API to consumers.
>
> I wanted this part to be as simple as possible. I will look into IIO
> DAC subsystem.
> The DAC is as simple 2 channel 8-bit i2c device connected to a separate i2c bus
> controlled through a register in LoCoMo device. One channel is used
> for backlight,
> other will be used for volume control. So (in theory) I can add the
> following device
> chain: locomo -> i2c-locomo -> m62332 -> IIO DAC client. However isn't that
> quite an overkill for just backlight & volume control? Please advice me on this.
The point is still the same: no unrelated code in drivers/mfd,
then either use IIO DAC as a middle layer or sink the DAC handling
into respective subdriver, i.e. push it into the backlight or
volume directly then.
>>> + /* Longtime timer */
>>> + writew(0, lchip->base + LOCOMO_LTINT);
>>> + /* SPI */
>>> + writew(0, lchip->base + LOCOMO_SPI + LOCOMO_SPIIE);
>>> +
>>> + writew(6 + 8 + 320 + 30 - 10, lchip->base + LOCOMO_ASD);
>>
>> That's a few magic numbers and calculation don't you think?
>>
>> A comment stating what's going on would be helpful.
>
> Unfortunately little is known here - these values are c&p from old 2.4
> Lineo code.
> This part is related to generating synchronization pulses for accessing
> touchscreen.
OK we have to live with reverse engineering results, that's OK.
Yours,
Linus Walleij
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: PATCH: Quirk (hid-saitek.c) for Saitek R.A.T.7 works with R.A.T.9 too
From: Jiri Kosina @ 2014-11-03 13:34 UTC (permalink / raw)
To: Ville Aakko; +Cc: linux-input, hbrinkmann
In-Reply-To: <CAEP-KKshiXPfDhHPE7uatU70wfiOM-xMbFS2+6VxBbFM-LMfjw@mail.gmail.com>
On Sun, 2 Nov 2014, Ville Aakko wrote:
> Hi,
>
> I have tested HID quirk for Saitek R.A.T.7 with my R.A.T. 9.
>
> (original commit 37c492c8f6a99870551fe2964b2dfce5d9e87375; " HID: quirk for
> Saitek RAT7 and MMO7 mices' mode button ").
>
> It works fine for me. Attached patch makes the nesessary changes to use the
> quirk on the R.A.T.9 too. No one else has tested this, but it seems quite
> trivial to me.
>
> Cheers!
>
> p.s. I have never submitted patches, I apologize if I have done something
> in a wrong way! Should I have added / updated the description in the
> comments?
Hi Ville,
patch looks good, the only thing it is missing is your Signed-off-by: line
(please see Documentation/SubmittingPatches for explanation of what that
means).
Please resend the patch with it included so that I could apply it.
Thanks,
--
Jiri Kosina
SUSE Labs
^ permalink raw reply
* Re: Microsoft Surface Pro 3 Type Cover keyboard
From: Jiri Kosina @ 2014-11-03 13:33 UTC (permalink / raw)
To: Jarrad Whitaker; +Cc: linux-input, Alan Wu
In-Reply-To: <54492559.8000205@gmail.com>
On Fri, 24 Oct 2014, Jarrad Whitaker wrote:
> The keyboard on the Surface Pro 3 type cover does not function without
> some patching, similar to what was apparently required for the SP2
> type/touch covers.
>
> A working patch against 3.16 attached, it's an amalgamation of "some
> dude posted this on the ubuntu/arch forums and it seems to work" so
> I'm making no claims that it's kernel-quality! Just trying to give a
> better indication of what needs to be added. My C is rudimentary and
> my knowledge of the kernel limited to 'fakeroot debian/rules
> updateconfigs', sorry. :)
> Happy to test any improved version, but note I only have a type, not a
> touch cover.
>
> Patch source is
> http://winaero.com/blog/how-to-install-linux-on-surface-pro-3/, which
> in turn sources a Russian site.
Hi,
thanks. Adding Alan Wu to CC, who sent me a slightly different patch for
this issue -- see the archives of linux-input list from a few days back.
Your patch is missing at least Signed-off-by: line, and also seems to lack
the update to hid_have_special_driver[].
Could you two guys please cooperate and send me a patch that should be
applied? I don't have the device so can't really test properly myself.
Thanks,
--
Jiri Kosina
SUSE Labs
^ permalink raw reply
* Re: [PATCH 1/1] x86: Surface Pro 3 Type Cover 3
From: Jiri Kosina @ 2014-11-03 13:30 UTC (permalink / raw)
To: Alan Wu; +Cc: linux-input, linux-kernel
In-Reply-To: <1414770520-4125-1-git-send-email-alan.c.wu@gmail.com>
On Fri, 31 Oct 2014, Alan Wu wrote:
> From: alanwu <alan.c.wu@gmail.com>
>
> Surface Pro 3 Type Cover that works with Ubuntu (and possibly Arch) from this thread. Both trackpad and keyboard work after compiling my own kernel.
> http://ubuntuforums.org/showthread.php?t=2231207&page=2&s=44910e0c56047e4f93dfd9fea58121ef
>
> Signed-off-by: alanwu <alan.c.wu@gmail.com>
Hi Alan,
thanks for the patch.
For driver binding to work reliably and correctly, you also need to add
the device to hid_have_special_driver[] array in drivers/hid/hid-core.c.
Could you please fix that up and resend the patch?
> ---
> drivers/hid/hid-ids.h | 1 +
> drivers/hid/hid-microsoft.c | 2 ++
> 2 files changed, 3 insertions(+)
>
> diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
> index e23ab8b..15f32c2 100644
> --- a/drivers/hid/hid-ids.h
> +++ b/drivers/hid/hid-ids.h
> @@ -648,6 +648,7 @@
> #define USB_DEVICE_ID_MS_SURFACE_PRO_2 0x0799
> #define USB_DEVICE_ID_MS_TOUCH_COVER_2 0x07a7
> #define USB_DEVICE_ID_MS_TYPE_COVER_2 0x07a9
> +#define USB_DEVICE_ID_MS_TYPE_COVER_3 0x07dc
>
> #define USB_VENDOR_ID_MOJO 0x8282
> #define USB_DEVICE_ID_RETRO_ADAPTER 0x3201
> diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c
> index 8ba17a9..cacda43 100644
> --- a/drivers/hid/hid-microsoft.c
> +++ b/drivers/hid/hid-microsoft.c
> @@ -274,6 +274,8 @@ static const struct hid_device_id ms_devices[] = {
> .driver_data = MS_NOGET },
> { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500),
> .driver_data = MS_DUPLICATE_USAGES },
> + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3),
> + .driver_data = MS_HIDINPUT },
>
> { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT),
> .driver_data = MS_PRESENTER },
> --
> 2.1.0
>
--
Jiri Kosina
SUSE Labs
^ permalink raw reply
* Re: [patch] HID: logitech-hidpp: leaks and NULL dereferences
From: Jiri Kosina @ 2014-11-03 13:27 UTC (permalink / raw)
To: Benjamin Tissoires
Cc: Dan Carpenter, Henrik Rydberg, linux-input, kernel-janitors
In-Reply-To: <20141031134901.GB24511@mail.corp.redhat.com>
On Fri, 31 Oct 2014, Benjamin Tissoires wrote:
> > Shift the allocation down a few lines to avoid a memory leak and also
> > add a check for allocation failure.
> >
> > Fixes: 2f31c5252910 ('HID: Introduce hidpp, a module to handle Logitech hid++ devices')
> > Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
> >
>
> Ouch, I am ashamed of not having spot that :/
>
> Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Good catch. Applied, thanks.
--
Jiri Kosina
SUSE Labs
^ permalink raw reply
* Re: [PATCH 1/2] Introduces Plantronics driver to fix errant mouse events.
From: Jiri Kosina @ 2014-11-03 13:22 UTC (permalink / raw)
To: Benjamin Tissoires
Cc: Cole, JD, linux-input@vger.kernel.org, dmitry.torokhov@gmail.com,
bleung@chromium.org, Junge, Terry, Dsouza, Sunil, Wesselman, Tom
In-Reply-To: <CAN+gG=Ftj41ThcGkBouGK0zC9-RPBXQUf_iSYEGFCSuadQf5JA@mail.gmail.com>
On Fri, 31 Oct 2014, Benjamin Tissoires wrote:
> > +static int plantronics_probe(struct hid_device *hdev,
> > + const struct hid_device_id *id)
> > +{
> > + int ret;
> > +
> > + ret = hid_parse(hdev);
> > + if (ret) {
> > + hid_err(hdev, "parse failed\n");
> > + goto err;
> > + }
> > +
> > + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
> > + if (ret) {
> > + hid_err(hdev, "hw start failed\n");
> > + goto err;
> > + }
> > +
> > + return 0;
> > + err:
> > + return ret;
> > +}
>
> Actually, in your case, you can even remove the probe function.
> hid-core will do open the report and start the hardware for you.
Good catch, thanks. I have removed the superfluous .probe() and applied
(with Dmitry's Reviewed-by: added to patch no .1).
Thanks,
--
Jiri Kosina
SUSE Labs
^ permalink raw reply
* Re: [PATCH 1/3] mfd: stmpe: add pull up/down register offsets for STMPE
From: Lee Jones @ 2014-11-03 12:57 UTC (permalink / raw)
To: Linus Walleij
Cc: Dmitry Torokhov, Samuel Ortiz, linux-kernel@vger.kernel.org,
Linux Input
In-Reply-To: <CACRpkdYNBZdB14fjj0LnQ8GchaGLTgfpvxhe4J9nc3XF80dFgQ@mail.gmail.com>
On Mon, 03 Nov 2014, Linus Walleij wrote:
> On Wed, Oct 29, 2014 at 8:31 PM, Dmitry Torokhov
> <dmitry.torokhov@gmail.com> wrote:
> > On Wednesday, October 29, 2014 10:55:14 AM Linus Walleij wrote:
> >> On Mon, Oct 20, 2014 at 8:46 AM, Lee Jones <lee.jones@linaro.org> wrote:
> >> > On Sat, 18 Oct 2014, Linus Walleij wrote:
> >> >> This adds the register offsets for pull up/down for the STMPE
> >> >> 1601, 1801 and 24xx expanders. This is used to bias GPIO lines
> >> >> and keypad lines.
> >> >>
> >> >> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> >> >> ---
> >> >> Hi Sam, Lee: I think you should just ACK this so Dmitry can take the
> >> >> patch series through the input tree, where the registers need to be
> >> >> used to enable the keypad on the STMPE2401.
> >> >> ---
> >> >>
> >> >> drivers/mfd/stmpe.c | 4 ++++
> >> >> drivers/mfd/stmpe.h | 3 +++
> >> >> include/linux/mfd/stmpe.h | 2 ++
> >> >> 3 files changed, 9 insertions(+)
> >> >
> >> > Does this need to go in with the other patches in the set?
> >> >
> >> > I'm _guessing_ that, as you've sent them separately, they can be
> >> > applied separately?
> >>
> >> No sorry if it was unclear, the series need to go in toghether.
> >> So this patch adds some infrastructure to the MFD device which
> >> is then utilized by the input driver in a later patch.
> >>
> >> > This needs to go in via MFD, but for my own reference:
> >> >
> >> > Acked-by: Lee Jones <lee.jones@linaro.org>
> >>
> >> Dmitry can you merge this & the rest with Lee's ACK?
> >
> > I'd be delighted, but it _sounded_ like Lee wanted it to go though MFD?
>
> Lee, can Dmitry take these through input?
That was weird, I replied at the same as as you sent this.
Yes, it's fine.
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
--
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 1/3] mfd: stmpe: add pull up/down register offsets for STMPE
From: Lee Jones @ 2014-11-03 12:25 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: Linus Walleij, Samuel Ortiz, linux-kernel, linux-input
In-Reply-To: <20141024214206.GG19933@dtor-ws>
On Fri, 24 Oct 2014, Dmitry Torokhov wrote:
> On Mon, Oct 20, 2014 at 07:46:05AM +0100, Lee Jones wrote:
> > On Sat, 18 Oct 2014, Linus Walleij wrote:
> >
> > > This adds the register offsets for pull up/down for the STMPE
> > > 1601, 1801 and 24xx expanders. This is used to bias GPIO lines
> > > and keypad lines.
> > >
> > > Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> > > ---
> > > Hi Sam, Lee: I think you should just ACK this so Dmitry can take the
> > > patch series through the input tree, where the registers need to be
> > > used to enable the keypad on the STMPE2401.
> > > ---
> > > drivers/mfd/stmpe.c | 4 ++++
> > > drivers/mfd/stmpe.h | 3 +++
> > > include/linux/mfd/stmpe.h | 2 ++
> > > 3 files changed, 9 insertions(+)
> >
> > Does this need to go in with the other patches in the set?
> >
> > I'm _guessing_ that, as you've sent them separately, they can be
> > applied separately?
> >
> > This needs to go in via MFD, but for my own reference:
> >
> > Acked-by: Lee Jones <lee.jones@linaro.org>
>
> The new register definitions are needed for patch #3. If you insist on
> this going through MFD then please take the other 2 patches with my Ack
> through MFD tree as well I do not think we need the whole song and dance
> trying to synchronize 2 trees.
Actually, I can't see the other patches as they weren't sent to me.
Please apply them all to your tree with my Ack.
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
--
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 0/4] Touchscreen performance related fixes
From: Sebastian Andrzej Siewior @ 2014-11-03 12:17 UTC (permalink / raw)
To: Griffis, Brad, R, Vignesh, Rob Herring, Pawel Moll, Mark Rutland,
Ian Campbell, Kumar Gala, Benoit Cousson, Tony Lindgren,
Russell King, Jonathan Cameron, Dmitry Torokhov
Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald, Samuel Ortiz,
Lee Jones, Balbi, Felipe, Jan Kardell, Paul Gortmaker,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-omap@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
linux-iio@vger.kernel.org, linux-input@vger.kernel.org
In-Reply-To: <912A29987EAE174BA6CF187D7CDFA9CE26F46B2B@DLEE08.ent.ti.com>
On 10/27/2014 08:02 PM, Griffis, Brad wrote:
> On 10/27/2014 12:34 PM, Sebastian Andrzej Siewior wrote:
>> Do we really need #3 (and then #4)? Given the complexity we have already, is there any benefit by decreasing this value?
>
> I specifically requested we add ti,charge-delay to the device tree because it is THE critical value to tune for a given design. Although I think the current value of 0xB000 will be suitable for a great many designs, I expect that many users will need to adjust this value for their hardware. Details such as which touchscreen vendor is being used and how the touchscreen is connected (header vs cable) have an effect on what's appropriate here.
Oh. That is one knob I hoped we could avoid since I haven't seen it
before on other TSCs. But okay. Please make sure that there is a
message printed if the default value is used. And lets hope the user
will do something about his.
>> Would someone want to increase it? Can we safely determine a value which works for everyone?
>
> This value represents a hardware delay before checking for the pen-up event. So in the scenario where someone is seeing excessive false pen-up events they will want to increase this parameter. The downsize of making this larger is that it decreases the overall sampling speed of both the touchscreen as well as the standalone ADC samples. At one point I tried making it huge, but that made the touchscreen overly sluggish because the sampling became too slow. So there is a definite trade-off that if you make it too large the touchscreen becomes sluggish, and if you make it too small then you may see false pen-up events. The optimal value will need to be tuned for a given design.
I applied the patches from this series and did the following test on my
am335x-evm: A mug on the touchscreen (to make sure the events are
coming), evtest on the event node to see that the events and loop of
cat /sys/bus/iio/devices/iio\:device0/in_voltage4_raw
In the past I was able lock up the TSC/ADC HW that way (see commit
7ca6740cd1 ("mfd: input: iio: ti_amm335x: Rework TSC/ADC
synchronization")) for details.
With this patches applied I don't seen any TSC events once the IIO
interface is (heavily) used. Can this be fixed?
Sebastian
^ permalink raw reply
* Re: [PATCH 1/3] mfd: stmpe: add pull up/down register offsets for STMPE
From: Linus Walleij @ 2014-11-03 9:27 UTC (permalink / raw)
To: Dmitry Torokhov, Lee Jones
Cc: Samuel Ortiz, linux-kernel@vger.kernel.org, Linux Input
In-Reply-To: <58957675.Bh6LToE4gg@dtor-glaptop>
On Wed, Oct 29, 2014 at 8:31 PM, Dmitry Torokhov
<dmitry.torokhov@gmail.com> wrote:
> On Wednesday, October 29, 2014 10:55:14 AM Linus Walleij wrote:
>> On Mon, Oct 20, 2014 at 8:46 AM, Lee Jones <lee.jones@linaro.org> wrote:
>> > On Sat, 18 Oct 2014, Linus Walleij wrote:
>> >> This adds the register offsets for pull up/down for the STMPE
>> >> 1601, 1801 and 24xx expanders. This is used to bias GPIO lines
>> >> and keypad lines.
>> >>
>> >> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
>> >> ---
>> >> Hi Sam, Lee: I think you should just ACK this so Dmitry can take the
>> >> patch series through the input tree, where the registers need to be
>> >> used to enable the keypad on the STMPE2401.
>> >> ---
>> >>
>> >> drivers/mfd/stmpe.c | 4 ++++
>> >> drivers/mfd/stmpe.h | 3 +++
>> >> include/linux/mfd/stmpe.h | 2 ++
>> >> 3 files changed, 9 insertions(+)
>> >
>> > Does this need to go in with the other patches in the set?
>> >
>> > I'm _guessing_ that, as you've sent them separately, they can be
>> > applied separately?
>>
>> No sorry if it was unclear, the series need to go in toghether.
>> So this patch adds some infrastructure to the MFD device which
>> is then utilized by the input driver in a later patch.
>>
>> > This needs to go in via MFD, but for my own reference:
>> >
>> > Acked-by: Lee Jones <lee.jones@linaro.org>
>>
>> Dmitry can you merge this & the rest with Lee's ACK?
>
> I'd be delighted, but it _sounded_ like Lee wanted it to go though MFD?
Lee, can Dmitry take these through input?
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH 1/1] Input: xpad - update docs to reflect current state
From: Daniel Dressler @ 2014-11-03 8:53 UTC (permalink / raw)
To: Daniel
Cc: Jonathan Corbet, Dmitry Torokhov, Tommi Rantala, Ted Mielczarek,
Paul Gortmaker, Frank Razenberg, Benjamin Valentin, Petr Sebor,
Thomaz de Oliveira dos Reis, open list:DOCUMENTATION, open list,
linux-input
The last time this documentation was accurate was
just over 8 years ago. In this time we've added
support for two new generations of Xbox console
controllers and dozens of third-party controllers.
This patch unifies terminology and makes it explicit
which model of controller a sentence refers to.
It also expands certain sections to address the latest
versions of Xbox controllers.
Thus this documentation should now be useful to
end users and not contain out-right untruths.
Signed-off-by: Daniel Dressler <danieru.dressler@gmail.com>
---
Documentation/input/xpad.txt | 123 ++++++++++++++++++++++++++++--------------
drivers/input/joystick/xpad.c | 4 +-
2 files changed, 85 insertions(+), 42 deletions(-)
diff --git a/Documentation/input/xpad.txt b/Documentation/input/xpad.txt
index 7cc9a43..d1b23f2 100644
--- a/Documentation/input/xpad.txt
+++ b/Documentation/input/xpad.txt
@@ -1,18 +1,22 @@
-xpad - Linux USB driver for X-Box gamepads
+xpad - Linux USB driver for Xbox compatible controllers
-This is the very first release of a driver for X-Box gamepads.
-Basically, this was hacked away in just a few hours, so don't expect
-miracles.
+This driver exposes all first-party and third-party Xbox compatible
+controllers. It has a long history and has enjoyed considerable usage
+as Window's xinput library caused most PC games to focus on Xbox
+controller compatibility.
-In particular, there is currently NO support for the rumble pack.
-You won't find many ff-aware linux applications anyway.
+Due to backwards compatibility all buttons are reported as digital.
+This only effects Original Xbox controllers. All later controller models
+have only digital face buttons.
+
+Rumble is supported on some models of Xbox 360 controllers but not of
+Original Xbox controllers nor on Xbox One controllers. As of writing
+the Xbox One's rumble protocol has not been reverse engineered but in
+the future could be supported.
0. Notes
--------
-
-Driver updated for kernel 2.6.17.11. (Based on a patch for 2.6.11.4.)
-
The number of buttons/axes reported varies based on 3 things:
- if you are using a known controller
- if you are using a known dance pad
@@ -20,12 +24,16 @@ The number of buttons/axes reported varies based on 3 things:
module configuration for "Map D-PAD to buttons rather than axes for unknown
pads" (module option dpad_to_buttons)
-If you set dpad_to_buttons to 0 and you are using an unknown device (one
-not listed below), the driver will map the directional pad to axes (X/Y),
-if you said N it will map the d-pad to buttons, which is needed for dance
-style games to function correctly. The default is Y.
+If you set dpad_to_buttons to N and you are using an unknown device
+the driver will map the directional pad to axes (X/Y).
+If you said Y it will map the d-pad to buttons, which is needed for dance
+style games to function correctly. The default is Y.
+
+dpad_to_buttons has no effect for known pads. A erroneous commit message
+claimed dpad_to_buttons could be used to force behavior on known devices.
+This is not true. Both dpad_to_buttons and triggers_to_buttons only affect
+unknown controllers.
-dpad_to_buttons has no effect for known pads.
0.1 Normal Controllers
----------------------
@@ -80,17 +88,29 @@ to the list of supported devices, ensuring that it will work out of the
box in the future.
-1. USB adapter
+1. USB adapters
--------------
+All generations of Xbox controllers speak USB over the wire.
+- Original Xbox controllers use a proprietary connector and require adapters.
+- Wireless Xbox 360 controllers require a 'Xbox 360 Wireless Gaming Receiver
+ for Windows'
+- Wired Xbox 360 controllers use standard USB connectors.
+- Xbox One controllers can be wireless but speak Wi-Fi Direct and are not
+ yet supported.
+- Xbox One controllers can be wired and use standard Micro-USB connectors.
+
-Before you can actually use the driver, you need to get yourself an
-adapter cable to connect the X-Box controller to your Linux-Box. You
-can buy these online fairly cheap, or build your own.
+
+1.1 Original Xbox USB adapters
+--------------
+Using this driver with an Original Xbox controller requires an
+adapter cable to break out the proprietary connector's pins to USB.
+You can buy these online fairly cheap, or build your own.
Such a cable is pretty easy to build. The Controller itself is a USB
compound device (a hub with three ports for two expansion slots and
the controller device) with the only difference in a nonstandard connector
-(5 pins vs. 4 on standard USB connector).
+(5 pins vs. 4 on standard USB 1.0 connectors).
You just need to solder a USB connector onto the cable and keep the
yellow wire unconnected. The other pins have the same order on both
@@ -102,26 +122,41 @@ original one. You can buy an extension cable and cut that instead. That way,
you can still use the controller with your X-Box, if you have one ;)
+
2. Driver Installation
----------------------
-Once you have the adapter cable and the controller is connected, you need
-to load your USB subsystem and should cat /proc/bus/usb/devices.
-There should be an entry like the one at the end [4].
+Once you have the adapter cable, if needed, and the controller connected
+the xpad module should be auto loaded. To confirm you can cat
+/proc/bus/usb/devices. There should be an entry like the one at the end [4].
+
+
-Currently (as of version 0.0.6), the following devices are included:
- original Microsoft XBOX controller (US), vendor=0x045e, product=0x0202
- smaller Microsoft XBOX controller (US), vendor=0x045e, product=0x0289
+3. Supported Controllers
+------------------------
+For a full list of supported controllers and associated vendor and product
+IDs see the xpad_device[] array[6].
+
+As of the historic version 0.0.6 (2006-10-10) the following devices
+were supported:
+ original Microsoft XBOX controller (US), vendor=0x045e, product=0x0202
+ smaller Microsoft XBOX controller (US), vendor=0x045e, product=0x0289
original Microsoft XBOX controller (Japan), vendor=0x045e, product=0x0285
- InterAct PowerPad Pro (Germany), vendor=0x05fd, product=0x107a
- RedOctane Xbox Dance Pad (US), vendor=0x0c12, product=0x8809
+ InterAct PowerPad Pro (Germany), vendor=0x05fd, product=0x107a
+ RedOctane Xbox Dance Pad (US), vendor=0x0c12, product=0x8809
+
+Unrecognized models of Xbox controllers should function as Generic
+Xbox controllers. Unrecognized Dance Pad controllers require setting
+the module option 'dpad_to_buttons'.
+
+If you have an unrecognized controller please see 0.3 - Unknown Controllers
-The driver should work with xbox pads not listed above as well, however
-you will need to do something extra for dance pads to work.
-If you have a controller not listed above, see 0.3 - Unknown Controllers
+4. Manual Testing
+-----------------
+To test this driver's functionality you may use 'jstest'.
-If you compiled and installed the driver, test the functionality:
+For example:
> modprobe xpad
> modprobe joydev
> jstest /dev/js0
@@ -134,7 +169,8 @@ show 20 inputs (6 axes, 14 buttons).
It works? Voila, you're done ;)
-3. Thanks
+
+5. Thanks
---------
I have to thank ITO Takayuki for the detailed info on his site
@@ -145,14 +181,14 @@ His useful info and both the usb-skeleton as well as the iforce input driver
the basic functionality.
-4. References
--------------
-1. http://euc.jp/periphs/xbox-controller.ja.html (ITO Takayuki)
-2. http://xpad.xbox-scene.com/
-3. http://www.markosweb.com/www/xboxhackz.com/
+6. References
+-------------
-4. /proc/bus/usb/devices - dump from InterAct PowerPad Pro (Germany):
+[1]: http://euc.jp/periphs/xbox-controller.ja.html (ITO Takayuki)
+[2]: http://xpad.xbox-scene.com/
+[3]: http://www.markosweb.com/www/xboxhackz.com/
+[4]: /proc/bus/usb/devices - dump from InterAct PowerPad Pro (Germany):
T: Bus=01 Lev=03 Prnt=04 Port=00 Cnt=01 Dev#= 5 Spd=12 MxCh= 0
D: Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=32 #Cfgs= 1
@@ -162,7 +198,7 @@ I: If#= 0 Alt= 0 #EPs= 2 Cls=58(unk. ) Sub=42 Prot=00 Driver=(none)
E: Ad=81(I) Atr=03(Int.) MxPS= 32 Ivl= 10ms
E: Ad=02(O) Atr=03(Int.) MxPS= 32 Ivl= 10ms
-5. /proc/bus/usb/devices - dump from Redoctane Xbox Dance Pad (US):
+[5]: /proc/bus/usb/devices - dump from Redoctane Xbox Dance Pad (US):
T: Bus=01 Lev=02 Prnt=09 Port=00 Cnt=01 Dev#= 10 Spd=12 MxCh= 0
D: Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
@@ -173,7 +209,12 @@ I: If#= 0 Alt= 0 #EPs= 2 Cls=58(unk. ) Sub=42 Prot=00 Driver=xpad
E: Ad=82(I) Atr=03(Int.) MxPS= 32 Ivl=4ms
E: Ad=02(O) Atr=03(Int.) MxPS= 32 Ivl=4ms
---
+[6]: http://lxr.free-electrons.com/ident?i=xpad_device
+
+
+
+7. Historic Edits
+-----------------
Marko Friedemann <mfr@bmx-chemnitz.de>
2002-07-16
- original doc
@@ -181,3 +222,5 @@ Marko Friedemann <mfr@bmx-chemnitz.de>
Dominic Cerquetti <binary1230@yahoo.com>
2005-03-19
- added stuff for dance pads, new d-pad->axes mappings
+
+Later changes may be viewed with 'git log Documentation/input/xpad.txt'
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 2ed7905..7e2e047 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -40,8 +40,8 @@
*
* TODO:
* - fine tune axes (especially trigger axes)
- * - fix "analog" buttons (reported as digital now)
- * - get rumble working
+ * - add original xbox rumble pack support
+ * - add xbox one rumble support
* - need USB IDs for other dance pads
*
* History:
--
2.1.0
^ permalink raw reply related
* [PATCH v9 00/18] input: cyapa: instruction of cyapa patches
From: Dudley Du @ 2014-11-03 8:46 UTC (permalink / raw)
To: dmitry.torokhov@gmail.com, rydberg@euromail.se
Cc: bleung@google.com, David Solda, linux-input@vger.kernel.org,
linux-kernel@vger.kernel.org
[-- Attachment #1: Type: text/plain, Size: 4911 bytes --]
V9 patches have below updates compared with v8 patches:
1) Removed all async thread stuff from the driver.
2) Split driver into 18 patches for each function change one patch.
V8 patches have below updates compared with v7 patches:
1) [PATCH v8 01/13] - Remove the async thread for device detect in
probe routine, now the device detect process is completely done within
the device probe routine.
2) [PATCH v8 01/13] - Split the irq cmd hander function to separated
function cyapa_default_irq_cmd_handler() and set it to interface
cyapa_default_ops.irq_cmd_handler.
3) [PATCH v8 06/13] - Add cyapa->gen check in cyapa_gen3_irq_cmd_handler()
to avoid miss-enter when device protocol is still in detecting.
V7 patches have below updates compared with v6 patches:
1) [PATCH v7 01/13] - Split the irq cmd hander function to separated
function cyapa_default_irq_cmd_handler() and set it to interface
cyapa_default_ops.irq_cmd_handler.
2) [PATCH v7 06/13] - Add cyapa->gen check in cyapa_gen3_irq_cmd_handler()
to avoid miss-enter when device protocol is still in detecting.
V6 patches have below updates compared with v5 patches:
1) Remove patch 14 of the lid filtering from the cyapa driver.
V5 patches have below updates compared with v4 patches:
1) Uses get_device()/put_device() instead of kobject_get()/kobject_put();
2) Fix memories freed before debugfs entries issue;
3) Make cyapa_debugs_root valid in driver module level
in module_init()/moudle_exit() ;
4) Fix i2c_transfer() may return partial transfer issues.
5) Add cyapa->removed flag to avoid detecting thread may still running
when driver module is removed.
6) Fix the meanings of some comments and return error code not clear issue.
This patch set is aimed to re-design the cyapa driver to support
old gen3 trackpad devices and new gen5 trackpad devices in one
cyapa driver, it's for easily productions support based on
customers' requirements. And add sysfs functions and interfaces
supported that required by users and customers.
Since the earlier gen3 and the latest gen5 trackpad devices using
two different chipsets, and have different protocols and interfaces,
so if supported these two type trackpad devices in two different drivers,
then it will be difficult to manage productions and later firmware updates.
e.g.: It will cause customer don't know which one trackpad device firmware
image to use and update when it has been used and integrated
in same one productions, so here we support these two trackpad
devices in same on driver.
The new design cyapa driver contains:
cyapa.c - the core of the re-design, supply interfaces and
functions to system and read trackpad devices.
cyapa.h - header file including macros and data structure definitions.
cyapa_gen3.c - functions support for gen3 trackpad devices,
cyapa_gen5.c - functions support for gen5 trackpad devices.
Beside this introduction patch, it has 18 patches listed as below.
For these patches each one is patched based on previous one.
patch 1/18: add device resource management infrastructure supported.
patch 2/18: re-design cyapa driver with core functions and interface
to support multi-type trackpad devices.
patch 3/18: add gen3 trackpad device basic functions supported into the
re-design cyapa driver.
patch 4/18: add gen5 trackpad device basic functions supported into the
re-design cyapa driver.
patch 5/18: add power management interfaces supported for the deivce.
patch 6/18: add runtime power management interfaces supported for the device.
patch 7/18: add sysfs interfaces supported in the cyapa driver.
Including read firmware version, get production ID, read baseline,
re-calibrate trackpad baselines and do trackpad firmware update.
patch 8/18: add gen3 trackpad device's firmware update function supported.
patch 9/18: add gen3 trackpad device's read baseline function supported.
patch 10/18: add gen3 trackpad device's force re-calibrate function supported.
patch 11/18: add gen5 trackpad device's firmware update function supported.
patch 12/18: add gen5 trackpad device's read baseline function supported.
patch 13/18: add gen5 trackpad device's force re-calibrate function.
patch 14/18: add read firmware image debugfs interface supported
in the cyapa driver.
patch 15/18: add gen3 trackpad device's read firmware image function supported.
patch 16/18: add gen5 trackpad device's read firmware image function supported.
patch 17/18: add read trackpad device's sensors' raw data debugfs interface
supported in the cyapa driver.
patch 18/18: add gen5 trackpad device's read read raw function supported.
This message and any attachments may contain Cypress (or its subsidiaries) confidential information. If it has been received in error, please advise the sender and immediately delete this message.
[-- Attachment #2: winmail.dat --]
[-- Type: application/ms-tnef, Size: 7708 bytes --]
^ permalink raw reply
* [PATCH v9 17/18] input: cyapa: add read sensors raw data debugfs interface support
From: Dudley Du @ 2014-11-03 8:33 UTC (permalink / raw)
To: dmitry.torokhov, rydberg; +Cc: Dudley Du, bleung, linux-input, linux-kernel
In-Reply-To: <1415003590-30485-1-git-send-email-dudl@cypress.com>
Add read sensors' raw data from trackpad device interface supported in cyapa
driver through debugfs raw_data interface.
Through this interface, user can read difference count map of each sensors
directly from trackpad device (some customers want). And it's useful to help
users to find out the root cause when there is performance gap happened.
TEST=test on Chromebooks.
Signed-off-by: Dudley Du <dudl@cypress.com>
---
drivers/input/mouse/cyapa.c | 89 +++++++++++++++++++++++++++++++++++++++++++++
drivers/input/mouse/cyapa.h | 4 ++
2 files changed, 93 insertions(+)
diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c
index bc1d75a..e200beb 100644
--- a/drivers/input/mouse/cyapa.c
+++ b/drivers/input/mouse/cyapa.c
@@ -577,6 +577,91 @@ static const struct file_operations cyapa_read_fw_fops = {
.read = cyapa_debugfs_read_fw
};
+static int cyapa_debugfs_raw_data_open(struct inode *inode, struct file *file)
+{
+ struct cyapa *cyapa = inode->i_private;
+ int ret;
+
+ if (!cyapa)
+ return -ENODEV;
+
+ /* Start to be supported after Gen5 trackpad devices. */
+ if (cyapa->gen < CYAPA_GEN5)
+ return -ENOTSUPP;
+
+ ret = mutex_lock_interruptible(&cyapa->debugfs_mutex);
+ if (ret)
+ return ret;
+
+ if (!get_device(&cyapa->client->dev)) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ file->private_data = cyapa;
+out:
+ mutex_unlock(&cyapa->debugfs_mutex);
+ return ret;
+}
+
+static int cyapa_debugfs_raw_data_release(struct inode *inode,
+ struct file *file)
+{
+ struct cyapa *cyapa = file->private_data;
+ int ret;
+
+ if (!cyapa)
+ return 0;
+
+ ret = mutex_lock_interruptible(&cyapa->debugfs_mutex);
+ if (ret)
+ return ret;
+ file->private_data = NULL;
+ put_device(&cyapa->client->dev);
+ mutex_unlock(&cyapa->debugfs_mutex);
+
+ return 0;
+}
+
+/* Always return the sensors' latest raw data from trackpad device. */
+static ssize_t cyapa_debugfs_read_raw_data(struct file *file,
+ char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ int ret;
+ struct cyapa *cyapa = file->private_data;
+
+ ret = mutex_lock_interruptible(&cyapa->state_sync_lock);
+ if (ret)
+ return ret;
+
+ if (cyapa->ops->read_raw_data)
+ ret = cyapa->ops->read_raw_data(cyapa);
+ else
+ ret = -EPERM;
+ mutex_unlock(&cyapa->state_sync_lock);
+ if (ret)
+ return ret;
+
+ if (*ppos >= cyapa->tp_raw_data_size)
+ return 0;
+
+ if (count + *ppos > cyapa->tp_raw_data_size)
+ count = cyapa->tp_raw_data_size - *ppos;
+
+ if (copy_to_user(buffer, &cyapa->tp_raw_data[*ppos], count))
+ return -EFAULT;
+
+ *ppos += count;
+ return count;
+}
+
+static const struct file_operations cyapa_read_raw_data_fops = {
+ .open = cyapa_debugfs_raw_data_open,
+ .release = cyapa_debugfs_raw_data_release,
+ .read = cyapa_debugfs_read_raw_data
+};
+
static int cyapa_debugfs_init(struct cyapa *cyapa)
{
struct device *dev = &cyapa->client->dev;
@@ -595,6 +680,10 @@ static int cyapa_debugfs_init(struct cyapa *cyapa)
debugfs_create_file(CYAPA_DEBUGFS_READ_FW, S_IRUSR, cyapa->dentry_dev,
cyapa, &cyapa_read_fw_fops);
+ if (cyapa->gen >= CYAPA_GEN5)
+ debugfs_create_file(CYAPA_DEBUGFS_RAW_DATA, S_IRUSR,
+ cyapa->dentry_dev, cyapa, &cyapa_read_raw_data_fops);
+
return 0;
}
diff --git a/drivers/input/mouse/cyapa.h b/drivers/input/mouse/cyapa.h
index 288c7de..75b0c33 100644
--- a/drivers/input/mouse/cyapa.h
+++ b/drivers/input/mouse/cyapa.h
@@ -190,6 +190,7 @@ struct cyapa_dev_ops {
struct device_attribute *, const char *, size_t);
int (*read_fw)(struct cyapa *);
+ int (*read_raw_data)(struct cyapa *);
int (*initialize)(struct cyapa *cyapa);
@@ -298,6 +299,9 @@ struct cyapa {
struct cyapa_tsg_bin_image_head fw_img_head;
u8 *fw_image;
size_t fw_image_size;
+ /* Buffer to store sensors' raw data */
+ u8 *tp_raw_data;
+ size_t tp_raw_data_size;
const struct cyapa_dev_ops *ops;
--
1.9.1
^ permalink raw reply related
* [PATCH v9 03/18] input: cyapa: add gen3 trackpad device basic functions support
From: Dudley Du @ 2014-11-03 8:32 UTC (permalink / raw)
To: dmitry.torokhov, rydberg; +Cc: Dudley Du, bleung, linux-input, linux-kernel
In-Reply-To: <1415003590-30485-1-git-send-email-dudl@cypress.com>
Based on the cyapa core, add the gen3 trackpad device's basic functions
supported, so gen3 trackpad device can work with kernel input system.
The basic function is absolutely same as previous cyapa driver.
TEST=test on Chromebooks.
Signed-off-by: Dudley Du <dudl@cypress.com>
---
drivers/input/mouse/Makefile | 3 +-
drivers/input/mouse/cyapa.c | 90 ++++-
drivers/input/mouse/cyapa.h | 1 +
drivers/input/mouse/cyapa_gen3.c | 788 +++++++++++++++++++++++++++++++++++++++
4 files changed, 880 insertions(+), 2 deletions(-)
create mode 100644 drivers/input/mouse/cyapa_gen3.c
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
index dda507f..4bf6c83 100644
--- a/drivers/input/mouse/Makefile
+++ b/drivers/input/mouse/Makefile
@@ -8,7 +8,7 @@ obj-$(CONFIG_MOUSE_AMIGA) += amimouse.o
obj-$(CONFIG_MOUSE_APPLETOUCH) += appletouch.o
obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o
obj-$(CONFIG_MOUSE_BCM5974) += bcm5974.o
-obj-$(CONFIG_MOUSE_CYAPA) += cyapa.o
+obj-$(CONFIG_MOUSE_CYAPA) += cyapatp.o
obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o
obj-$(CONFIG_MOUSE_INPORT) += inport.o
obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o
@@ -23,6 +23,7 @@ obj-$(CONFIG_MOUSE_SYNAPTICS_I2C) += synaptics_i2c.o
obj-$(CONFIG_MOUSE_SYNAPTICS_USB) += synaptics_usb.o
obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o
+cyapatp-objs := cyapa.o cyapa_gen3.o
psmouse-objs := psmouse-base.o synaptics.o focaltech.o
psmouse-$(CONFIG_MOUSE_PS2_ALPS) += alps.o
diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c
index 5029618..cb81baf 100644
--- a/drivers/input/mouse/cyapa.c
+++ b/drivers/input/mouse/cyapa.c
@@ -234,6 +234,9 @@ static int cyapa_check_is_operational(struct cyapa *cyapa)
return ret;
switch (cyapa->gen) {
+ case CYAPA_GEN3:
+ cyapa->ops = &cyapa_gen3_ops;
+ break;
default:
return -ENODEV;
}
@@ -284,7 +287,85 @@ out:
*/
static int cyapa_get_state(struct cyapa *cyapa)
{
- return -ENODEV;
+ int ret;
+ u8 status[BL_STATUS_SIZE];
+ u8 cmd[32];
+ /* The i2c address of gen4 and gen5 trackpad device must be even. */
+ bool even_addr = ((cyapa->client->addr & 0x0001) == 0);
+ bool smbus = false;
+ int retries = 2;
+
+ cyapa->state = CYAPA_STATE_NO_DEVICE;
+
+ /*
+ * Get trackpad status by reading 3 registers starting from 0.
+ * If the device is in the bootloader, this will be BL_HEAD.
+ * If the device is in operation mode, this will be the DATA regs.
+ *
+ */
+ ret = cyapa_i2c_reg_read_block(cyapa, BL_HEAD_OFFSET, BL_STATUS_SIZE,
+ status);
+
+ /*
+ * On smbus systems in OP mode, the i2c_reg_read will fail with
+ * -ETIMEDOUT. In this case, try again using the smbus equivalent
+ * command. This should return a BL_HEAD indicating CYAPA_STATE_OP.
+ */
+ if (cyapa->smbus && (ret == -ETIMEDOUT || ret == -ENXIO)) {
+ if (!even_addr)
+ ret = cyapa_read_block(cyapa,
+ CYAPA_CMD_BL_STATUS, status);
+ smbus = true;
+ }
+ if (ret != BL_STATUS_SIZE)
+ goto error;
+
+ /*
+ * Detect trackpad protocol based on characristic registers and bits.
+ */
+ do {
+ cyapa->status[REG_OP_STATUS] = status[REG_OP_STATUS];
+ cyapa->status[REG_BL_STATUS] = status[REG_BL_STATUS];
+ cyapa->status[REG_BL_ERROR] = status[REG_BL_ERROR];
+
+ if (cyapa->gen == CYAPA_GEN_UNKNOWN ||
+ cyapa->gen == CYAPA_GEN3) {
+ ret = cyapa_gen3_ops.state_parse(cyapa,
+ status, BL_STATUS_SIZE);
+ if (ret == 0)
+ goto out_detected;
+ }
+
+ /*
+ * Cannot detect communication protocol based on current
+ * charateristic registers and bits.
+ * So write error command to do further detection.
+ * this method only valid on I2C bus.
+ * for smbus interface, it won't have overwrite issue.
+ */
+ if (!smbus) {
+ cmd[0] = 0x00;
+ cmd[1] = 0x00;
+ ret = cyapa_i2c_write(cyapa, 0, 2, cmd);
+ if (ret)
+ goto error;
+
+ msleep(50);
+
+ ret = cyapa_i2c_read(cyapa, BL_HEAD_OFFSET,
+ BL_STATUS_SIZE, status);
+ if (ret < 0)
+ goto error;
+ }
+ } while (--retries > 0 && !smbus);
+
+ goto error;
+
+out_detected:
+ return 0;
+
+error:
+ return (ret < 0) ? ret : -EAGAIN;
}
/*
@@ -421,6 +502,8 @@ u16 cyapa_pwr_cmd_to_sleep_time(u8 pwr_mode)
*/
static int cyapa_initialize(struct cyapa *cyapa)
{
+ int ret = 0;
+
cyapa->state = CYAPA_STATE_NO_DEVICE;
cyapa->gen = CYAPA_GEN_UNKNOWN;
mutex_init(&cyapa->state_sync_lock);
@@ -433,6 +516,11 @@ static int cyapa_initialize(struct cyapa *cyapa)
cyapa->suspend_sleep_time =
cyapa_pwr_cmd_to_sleep_time(cyapa->suspend_power_mode);
+ if (cyapa_gen3_ops.initialize)
+ ret = cyapa_gen3_ops.initialize(cyapa);
+ if (ret)
+ return ret;
+
return cyapa_detect(cyapa);
}
diff --git a/drivers/input/mouse/cyapa.h b/drivers/input/mouse/cyapa.h
index ee97d7c..b281dcb 100644
--- a/drivers/input/mouse/cyapa.h
+++ b/drivers/input/mouse/cyapa.h
@@ -317,5 +317,6 @@ u16 cyapa_pwr_cmd_to_sleep_time(u8 pwr_mode);
extern const char unique_str[];
+extern const struct cyapa_dev_ops cyapa_gen3_ops;
#endif
diff --git a/drivers/input/mouse/cyapa_gen3.c b/drivers/input/mouse/cyapa_gen3.c
new file mode 100644
index 0000000..bd00c6e
--- /dev/null
+++ b/drivers/input/mouse/cyapa_gen3.c
@@ -0,0 +1,788 @@
+/*
+ * Cypress APA trackpad with I2C interface
+ *
+ * Author: Dudley Du <dudl@cypress.com>
+ * Further cleanup and restructuring by:
+ * Daniel Kurtz <djkurtz@chromium.org>
+ * Benson Leung <bleung@chromium.org>
+ *
+ * Copyright (C) 2011-2014 Cypress Semiconductor, Inc.
+ * Copyright (C) 2011-2012 Google, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include "cyapa.h"
+
+
+#define GEN3_MAX_FINGERS 5
+#define GEN3_FINGER_NUM(x) (((x) >> 4) & 0x07)
+
+#define BLK_HEAD_BYTES 32
+
+/* Macro for register map group offset. */
+#define PRODUCT_ID_SIZE 16
+#define QUERY_DATA_SIZE 27
+#define REG_PROTOCOL_GEN_QUERY_OFFSET 20
+
+#define REG_OFFSET_DATA_BASE 0x0000
+#define REG_OFFSET_COMMAND_BASE 0x0028
+#define REG_OFFSET_QUERY_BASE 0x002a
+
+#define CYAPA_OFFSET_SOFT_RESET REG_OFFSET_COMMAND_BASE
+#define OP_RECALIBRATION_MASK 0x80
+#define OP_REPORT_BASELINE_MASK 0x40
+#define REG_OFFSET_MAX_BASELINE 0x0026
+#define REG_OFFSET_MIN_BASELINE 0x0027
+
+#define REG_OFFSET_POWER_MODE (REG_OFFSET_COMMAND_BASE + 1)
+#define SET_POWER_MODE_DELAY 10000 /* unit: us */
+#define SET_POWER_MODE_TRIES 5
+
+/*
+ * CYAPA trackpad device states.
+ * Used in register 0x00, bit1-0, DeviceStatus field.
+ * Other values indicate device is in an abnormal state and must be reset.
+ */
+#define CYAPA_DEV_NORMAL 0x03
+#define CYAPA_DEV_BUSY 0x01
+
+#define CYAPA_FW_BLOCK_SIZE 64
+#define CYAPA_FW_READ_SIZE 16
+#define CYAPA_FW_HDR_START 0x0780
+#define CYAPA_FW_HDR_BLOCK_COUNT 2
+#define CYAPA_FW_HDR_BLOCK_START (CYAPA_FW_HDR_START / CYAPA_FW_BLOCK_SIZE)
+#define CYAPA_FW_HDR_SIZE (CYAPA_FW_HDR_BLOCK_COUNT * \
+ CYAPA_FW_BLOCK_SIZE)
+#define CYAPA_FW_DATA_START 0x0800
+#define CYAPA_FW_DATA_BLOCK_COUNT 480
+#define CYAPA_FW_DATA_BLOCK_START (CYAPA_FW_DATA_START / CYAPA_FW_BLOCK_SIZE)
+#define CYAPA_FW_DATA_SIZE (CYAPA_FW_DATA_BLOCK_COUNT * \
+ CYAPA_FW_BLOCK_SIZE)
+#define CYAPA_FW_SIZE (CYAPA_FW_HDR_SIZE + CYAPA_FW_DATA_SIZE)
+#define CYAPA_CMD_LEN 16
+
+#define GEN3_BL_IDLE_FW_MAJ_VER_OFFSET 0x0b
+#define GEN3_BL_IDLE_FW_MIN_VER_OFFSET (GEN3_BL_IDLE_FW_MAJ_VER_OFFSET + 1)
+
+
+struct cyapa_touch {
+ /*
+ * high bits or x/y position value
+ * bit 7 - 4: high 4 bits of x position value
+ * bit 3 - 0: high 4 bits of y position value
+ */
+ u8 xy_hi;
+ u8 x_lo; /* low 8 bits of x position value. */
+ u8 y_lo; /* low 8 bits of y position value. */
+ u8 pressure;
+ /* id range is 1 - 15. It is incremented with every new touch. */
+ u8 id;
+} __packed;
+
+struct cyapa_reg_data {
+ /*
+ * bit 0 - 1: device status
+ * bit 3 - 2: power mode
+ * bit 6 - 4: reserved
+ * bit 7: interrupt valid bit
+ */
+ u8 device_status;
+ /*
+ * bit 7 - 4: number of fingers currently touching pad
+ * bit 3: valid data check bit
+ * bit 2: middle mechanism button state if exists
+ * bit 1: right mechanism button state if exists
+ * bit 0: left mechanism button state if exists
+ */
+ u8 finger_btn;
+ /* CYAPA reports up to 5 touches per packet. */
+ struct cyapa_touch touches[5];
+} __packed;
+
+static const u8 bl_activate[] = { 0x00, 0xff, 0x38, 0x00, 0x01, 0x02, 0x03,
+ 0x04, 0x05, 0x06, 0x07 };
+static const u8 bl_deactivate[] = { 0x00, 0xff, 0x3b, 0x00, 0x01, 0x02, 0x03,
+ 0x04, 0x05, 0x06, 0x07 };
+static const u8 bl_exit[] = { 0x00, 0xff, 0xa5, 0x00, 0x01, 0x02, 0x03, 0x04,
+ 0x05, 0x06, 0x07 };
+
+
+ /* for byte read/write command */
+#define CMD_RESET 0
+#define CMD_POWER_MODE 1
+#define CMD_DEV_STATUS 2
+#define CMD_REPORT_MAX_BASELINE 3
+#define CMD_REPORT_MIN_BASELINE 4
+#define SMBUS_BYTE_CMD(cmd) (((cmd) & 0x3f) << 1)
+#define CYAPA_SMBUS_RESET SMBUS_BYTE_CMD(CMD_RESET)
+#define CYAPA_SMBUS_POWER_MODE SMBUS_BYTE_CMD(CMD_POWER_MODE)
+#define CYAPA_SMBUS_DEV_STATUS SMBUS_BYTE_CMD(CMD_DEV_STATUS)
+#define CYAPA_SMBUS_MAX_BASELINE SMBUS_BYTE_CMD(CMD_REPORT_MAX_BASELINE)
+#define CYAPA_SMBUS_MIN_BASELINE SMBUS_BYTE_CMD(CMD_REPORT_MIN_BASELINE)
+
+ /* for group registers read/write command */
+#define REG_GROUP_DATA 0
+#define REG_GROUP_CMD 2
+#define REG_GROUP_QUERY 3
+#define SMBUS_GROUP_CMD(grp) (0x80 | (((grp) & 0x07) << 3))
+#define CYAPA_SMBUS_GROUP_DATA SMBUS_GROUP_CMD(REG_GROUP_DATA)
+#define CYAPA_SMBUS_GROUP_CMD SMBUS_GROUP_CMD(REG_GROUP_CMD)
+#define CYAPA_SMBUS_GROUP_QUERY SMBUS_GROUP_CMD(REG_GROUP_QUERY)
+
+ /* for register block read/write command */
+#define CMD_BL_STATUS 0
+#define CMD_BL_HEAD 1
+#define CMD_BL_CMD 2
+#define CMD_BL_DATA 3
+#define CMD_BL_ALL 4
+#define CMD_BLK_PRODUCT_ID 5
+#define CMD_BLK_HEAD 6
+#define SMBUS_BLOCK_CMD(cmd) (0xc0 | (((cmd) & 0x1f) << 1))
+
+/* register block read/write command in bootloader mode */
+#define CYAPA_SMBUS_BL_STATUS SMBUS_BLOCK_CMD(CMD_BL_STATUS)
+#define CYAPA_SMBUS_BL_HEAD SMBUS_BLOCK_CMD(CMD_BL_HEAD)
+#define CYAPA_SMBUS_BL_CMD SMBUS_BLOCK_CMD(CMD_BL_CMD)
+#define CYAPA_SMBUS_BL_DATA SMBUS_BLOCK_CMD(CMD_BL_DATA)
+#define CYAPA_SMBUS_BL_ALL SMBUS_BLOCK_CMD(CMD_BL_ALL)
+
+/* register block read/write command in operational mode */
+#define CYAPA_SMBUS_BLK_PRODUCT_ID SMBUS_BLOCK_CMD(CMD_BLK_PRODUCT_ID)
+#define CYAPA_SMBUS_BLK_HEAD SMBUS_BLOCK_CMD(CMD_BLK_HEAD)
+
+ /* for byte read/write command */
+#define CMD_RESET 0
+#define CMD_POWER_MODE 1
+#define CMD_DEV_STATUS 2
+#define CMD_REPORT_MAX_BASELINE 3
+#define CMD_REPORT_MIN_BASELINE 4
+#define SMBUS_BYTE_CMD(cmd) (((cmd) & 0x3f) << 1)
+#define CYAPA_SMBUS_RESET SMBUS_BYTE_CMD(CMD_RESET)
+#define CYAPA_SMBUS_POWER_MODE SMBUS_BYTE_CMD(CMD_POWER_MODE)
+#define CYAPA_SMBUS_DEV_STATUS SMBUS_BYTE_CMD(CMD_DEV_STATUS)
+#define CYAPA_SMBUS_MAX_BASELINE SMBUS_BYTE_CMD(CMD_REPORT_MAX_BASELINE)
+#define CYAPA_SMBUS_MIN_BASELINE SMBUS_BYTE_CMD(CMD_REPORT_MIN_BASELINE)
+
+ /* for group registers read/write command */
+#define REG_GROUP_DATA 0
+#define REG_GROUP_CMD 2
+#define REG_GROUP_QUERY 3
+#define SMBUS_GROUP_CMD(grp) (0x80 | (((grp) & 0x07) << 3))
+#define CYAPA_SMBUS_GROUP_DATA SMBUS_GROUP_CMD(REG_GROUP_DATA)
+#define CYAPA_SMBUS_GROUP_CMD SMBUS_GROUP_CMD(REG_GROUP_CMD)
+#define CYAPA_SMBUS_GROUP_QUERY SMBUS_GROUP_CMD(REG_GROUP_QUERY)
+
+ /* for register block read/write command */
+#define CMD_BL_STATUS 0
+#define CMD_BL_HEAD 1
+#define CMD_BL_CMD 2
+#define CMD_BL_DATA 3
+#define CMD_BL_ALL 4
+#define CMD_BLK_PRODUCT_ID 5
+#define CMD_BLK_HEAD 6
+#define SMBUS_BLOCK_CMD(cmd) (0xc0 | (((cmd) & 0x1f) << 1))
+
+/* register block read/write command in bootloader mode */
+#define CYAPA_SMBUS_BL_STATUS SMBUS_BLOCK_CMD(CMD_BL_STATUS)
+#define CYAPA_SMBUS_BL_HEAD SMBUS_BLOCK_CMD(CMD_BL_HEAD)
+#define CYAPA_SMBUS_BL_CMD SMBUS_BLOCK_CMD(CMD_BL_CMD)
+#define CYAPA_SMBUS_BL_DATA SMBUS_BLOCK_CMD(CMD_BL_DATA)
+#define CYAPA_SMBUS_BL_ALL SMBUS_BLOCK_CMD(CMD_BL_ALL)
+
+/* register block read/write command in operational mode */
+#define CYAPA_SMBUS_BLK_PRODUCT_ID SMBUS_BLOCK_CMD(CMD_BLK_PRODUCT_ID)
+#define CYAPA_SMBUS_BLK_HEAD SMBUS_BLOCK_CMD(CMD_BLK_HEAD)
+
+struct cyapa_cmd_len {
+ u8 cmd;
+ u8 len;
+};
+
+/* maps generic CYAPA_CMD_* code to the I2C equivalent */
+static const struct cyapa_cmd_len cyapa_i2c_cmds[] = {
+ { CYAPA_OFFSET_SOFT_RESET, 1 }, /* CYAPA_CMD_SOFT_RESET */
+ { REG_OFFSET_COMMAND_BASE + 1, 1 }, /* CYAPA_CMD_POWER_MODE */
+ { REG_OFFSET_DATA_BASE, 1 }, /* CYAPA_CMD_DEV_STATUS */
+ { REG_OFFSET_DATA_BASE, sizeof(struct cyapa_reg_data) },
+ /* CYAPA_CMD_GROUP_DATA */
+ { REG_OFFSET_COMMAND_BASE, 0 }, /* CYAPA_CMD_GROUP_CMD */
+ { REG_OFFSET_QUERY_BASE, QUERY_DATA_SIZE }, /* CYAPA_CMD_GROUP_QUERY */
+ { BL_HEAD_OFFSET, 3 }, /* CYAPA_CMD_BL_STATUS */
+ { BL_HEAD_OFFSET, 16 }, /* CYAPA_CMD_BL_HEAD */
+ { BL_HEAD_OFFSET, 16 }, /* CYAPA_CMD_BL_CMD */
+ { BL_DATA_OFFSET, 16 }, /* CYAPA_CMD_BL_DATA */
+ { BL_HEAD_OFFSET, 32 }, /* CYAPA_CMD_BL_ALL */
+ { REG_OFFSET_QUERY_BASE, PRODUCT_ID_SIZE },
+ /* CYAPA_CMD_BLK_PRODUCT_ID */
+ { REG_OFFSET_DATA_BASE, 32 }, /* CYAPA_CMD_BLK_HEAD */
+ { REG_OFFSET_MAX_BASELINE, 1 }, /* CYAPA_CMD_MAX_BASELINE */
+ { REG_OFFSET_MIN_BASELINE, 1 }, /* CYAPA_CMD_MIN_BASELINE */
+};
+
+static const struct cyapa_cmd_len cyapa_smbus_cmds[] = {
+ { CYAPA_SMBUS_RESET, 1 }, /* CYAPA_CMD_SOFT_RESET */
+ { CYAPA_SMBUS_POWER_MODE, 1 }, /* CYAPA_CMD_POWER_MODE */
+ { CYAPA_SMBUS_DEV_STATUS, 1 }, /* CYAPA_CMD_DEV_STATUS */
+ { CYAPA_SMBUS_GROUP_DATA, sizeof(struct cyapa_reg_data) },
+ /* CYAPA_CMD_GROUP_DATA */
+ { CYAPA_SMBUS_GROUP_CMD, 2 }, /* CYAPA_CMD_GROUP_CMD */
+ { CYAPA_SMBUS_GROUP_QUERY, QUERY_DATA_SIZE },
+ /* CYAPA_CMD_GROUP_QUERY */
+ { CYAPA_SMBUS_BL_STATUS, 3 }, /* CYAPA_CMD_BL_STATUS */
+ { CYAPA_SMBUS_BL_HEAD, 16 }, /* CYAPA_CMD_BL_HEAD */
+ { CYAPA_SMBUS_BL_CMD, 16 }, /* CYAPA_CMD_BL_CMD */
+ { CYAPA_SMBUS_BL_DATA, 16 }, /* CYAPA_CMD_BL_DATA */
+ { CYAPA_SMBUS_BL_ALL, 32 }, /* CYAPA_CMD_BL_ALL */
+ { CYAPA_SMBUS_BLK_PRODUCT_ID, PRODUCT_ID_SIZE },
+ /* CYAPA_CMD_BLK_PRODUCT_ID */
+ { CYAPA_SMBUS_BLK_HEAD, 16 }, /* CYAPA_CMD_BLK_HEAD */
+ { CYAPA_SMBUS_MAX_BASELINE, 1 }, /* CYAPA_CMD_MAX_BASELINE */
+ { CYAPA_SMBUS_MIN_BASELINE, 1 }, /* CYAPA_CMD_MIN_BASELINE */
+};
+
+static bool data_reporting_started;
+
+
+/*
+ * cyapa_smbus_read_block - perform smbus block read command
+ * @cyapa - private data structure of the driver
+ * @cmd - the properly encoded smbus command
+ * @len - expected length of smbus command result
+ * @values - buffer to store smbus command result
+ *
+ * Returns negative errno, else the number of bytes written.
+ *
+ * Note:
+ * In trackpad device, the memory block allocated for I2C register map
+ * is 256 bytes, so the max read block for I2C bus is 256 bytes.
+ */
+ssize_t cyapa_smbus_read_block(struct cyapa *cyapa, u8 cmd, size_t len,
+ u8 *values)
+{
+ ssize_t ret;
+ u8 index;
+ u8 smbus_cmd;
+ u8 *buf;
+ struct i2c_client *client = cyapa->client;
+
+ if (!(SMBUS_BYTE_BLOCK_CMD_MASK & cmd))
+ return -EINVAL;
+
+ if (SMBUS_GROUP_BLOCK_CMD_MASK & cmd) {
+ /* read specific block registers command. */
+ smbus_cmd = SMBUS_ENCODE_RW(cmd, SMBUS_READ);
+ ret = i2c_smbus_read_block_data(client, smbus_cmd, values);
+ goto out;
+ }
+
+ ret = 0;
+ for (index = 0; index * I2C_SMBUS_BLOCK_MAX < len; index++) {
+ smbus_cmd = SMBUS_ENCODE_IDX(cmd, index);
+ smbus_cmd = SMBUS_ENCODE_RW(smbus_cmd, SMBUS_READ);
+ buf = values + I2C_SMBUS_BLOCK_MAX * index;
+ ret = i2c_smbus_read_block_data(client, smbus_cmd, buf);
+ if (ret < 0)
+ goto out;
+ }
+
+out:
+ return ret > 0 ? len : ret;
+}
+
+s32 cyapa_read_byte(struct cyapa *cyapa, u8 cmd_idx)
+{
+ u8 cmd;
+
+ if (cyapa->smbus) {
+ cmd = cyapa_smbus_cmds[cmd_idx].cmd;
+ cmd = SMBUS_ENCODE_RW(cmd, SMBUS_READ);
+ } else {
+ cmd = cyapa_i2c_cmds[cmd_idx].cmd;
+ }
+ return i2c_smbus_read_byte_data(cyapa->client, cmd);
+}
+
+s32 cyapa_write_byte(struct cyapa *cyapa, u8 cmd_idx, u8 value)
+{
+ u8 cmd;
+
+ if (cyapa->smbus) {
+ cmd = cyapa_smbus_cmds[cmd_idx].cmd;
+ cmd = SMBUS_ENCODE_RW(cmd, SMBUS_WRITE);
+ } else {
+ cmd = cyapa_i2c_cmds[cmd_idx].cmd;
+ }
+ return i2c_smbus_write_byte_data(cyapa->client, cmd, value);
+}
+
+ssize_t cyapa_read_block(struct cyapa *cyapa, u8 cmd_idx, u8 *values)
+{
+ u8 cmd;
+ size_t len;
+
+ if (cyapa->smbus) {
+ cmd = cyapa_smbus_cmds[cmd_idx].cmd;
+ len = cyapa_smbus_cmds[cmd_idx].len;
+ return cyapa_smbus_read_block(cyapa, cmd, len, values);
+ }
+ cmd = cyapa_i2c_cmds[cmd_idx].cmd;
+ len = cyapa_i2c_cmds[cmd_idx].len;
+ return cyapa_i2c_reg_read_block(cyapa, cmd, len, values);
+}
+
+/*
+ * Determine the Gen3 trackpad device's current operating state.
+ *
+ */
+static int cyapa_gen3_state_parse(struct cyapa *cyapa, u8 *reg_data, int len)
+{
+ /*
+ * Must be in detecting and should not do data reporting.
+ * It will be reenabled when all detecting done and lauched into
+ * applicaiton mode successfully.
+ */
+ data_reporting_started = false;
+ cyapa->state = CYAPA_STATE_NO_DEVICE;
+
+ /* Parse based on Gen3 characteristic registers and bits */
+ if (reg_data[REG_BL_FILE] == BL_FILE &&
+ reg_data[REG_BL_ERROR] == BL_ERROR_NO_ERR_IDLE &&
+ (reg_data[REG_BL_STATUS] ==
+ (BL_STATUS_RUNNING | BL_STATUS_CSUM_VALID) ||
+ reg_data[REG_BL_STATUS] == BL_STATUS_RUNNING)) {
+ /*
+ * Normal state after power on or reset,
+ * REG_BL_STATUS == 0x11, firmware image checksum is valid.
+ * REG_BL_STATUS == 0x10, firmware image checksum is invalid.
+ */
+ cyapa->gen = CYAPA_GEN3;
+ cyapa->state = CYAPA_STATE_BL_IDLE;
+ } else if (reg_data[REG_BL_FILE] == BL_FILE &&
+ (reg_data[REG_BL_STATUS] & BL_STATUS_RUNNING) ==
+ BL_STATUS_RUNNING) {
+ cyapa->gen = CYAPA_GEN3;
+ if (reg_data[REG_BL_STATUS] & BL_STATUS_BUSY) {
+ cyapa->state = CYAPA_STATE_BL_BUSY;
+ } else {
+ if ((reg_data[REG_BL_ERROR] & BL_ERROR_BOOTLOADING) ==
+ BL_ERROR_BOOTLOADING)
+ cyapa->state = CYAPA_STATE_BL_ACTIVE;
+ else
+ cyapa->state = CYAPA_STATE_BL_IDLE;
+ }
+ } else if ((reg_data[REG_OP_STATUS] & OP_STATUS_SRC) &&
+ (reg_data[REG_OP_DATA1] & OP_DATA_VALID)) {
+ /*
+ * Normal state when running in operaitonal mode,
+ * may also not in full power state or
+ * busying in command process.
+ */
+ if (GEN3_FINGER_NUM(reg_data[REG_OP_DATA1]) <=
+ GEN3_MAX_FINGERS) {
+ /* Finger number data is valid. */
+ cyapa->gen = CYAPA_GEN3;
+ cyapa->state = CYAPA_STATE_OP;
+ }
+ } else if (reg_data[REG_OP_STATUS] == 0x0C &&
+ reg_data[REG_OP_DATA1] == 0x08) {
+ /* Op state when first two registers overwritten with 0x00 */
+ cyapa->gen = CYAPA_GEN3;
+ cyapa->state = CYAPA_STATE_OP;
+ } else if (reg_data[REG_BL_STATUS] &
+ (BL_STATUS_RUNNING | BL_STATUS_BUSY)) {
+ cyapa->gen = CYAPA_GEN3;
+ cyapa->state = CYAPA_STATE_BL_BUSY;
+ }
+
+ if (cyapa->gen == CYAPA_GEN3 && (cyapa->state == CYAPA_STATE_OP ||
+ cyapa->state == CYAPA_STATE_BL_IDLE ||
+ cyapa->state == CYAPA_STATE_BL_ACTIVE ||
+ cyapa->state == CYAPA_STATE_BL_BUSY))
+ return 0;
+
+ return -EAGAIN;
+}
+
+static int cyapa_gen3_bl_deactivate(struct cyapa *cyapa)
+{
+ int ret;
+
+ ret = cyapa_i2c_reg_write_block(cyapa, 0, sizeof(bl_deactivate),
+ bl_deactivate);
+ if (ret < 0)
+ return ret;
+
+ /* Wait for bootloader to switch to idle state; should take < 100ms */
+ msleep(100);
+ ret = cyapa_poll_state(cyapa, 500);
+ if (ret < 0)
+ return ret;
+ if (cyapa->state != CYAPA_STATE_BL_IDLE)
+ return -EAGAIN;
+ return 0;
+}
+
+/*
+ * Exit bootloader
+ *
+ * Send bl_exit command, then wait 50 - 100 ms to let device transition to
+ * operational mode. If this is the first time the device's firmware is
+ * running, it can take up to 2 seconds to calibrate its sensors. So, poll
+ * the device's new state for up to 2 seconds.
+ *
+ * Returns:
+ * -EIO failure while reading from device
+ * -EAGAIN device is stuck in bootloader, b/c it has invalid firmware
+ * 0 device is supported and in operational mode
+ */
+static int cyapa_gen3_bl_exit(struct cyapa *cyapa)
+{
+ int ret;
+
+ ret = cyapa_i2c_reg_write_block(cyapa, 0, sizeof(bl_exit), bl_exit);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * Wait for bootloader to exit, and operation mode to start.
+ * Normally, this takes at least 50 ms.
+ */
+ usleep_range(50000, 100000);
+ /*
+ * In addition, when a device boots for the first time after being
+ * updated to new firmware, it must first calibrate its sensors, which
+ * can take up to an additional 2 seconds. If the device power is
+ * running low, this may take even longer.
+ */
+ ret = cyapa_poll_state(cyapa, 4000);
+ if (ret < 0)
+ return ret;
+ if (cyapa->state != CYAPA_STATE_OP)
+ return -EAGAIN;
+
+ return 0;
+}
+
+/*
+ * cyapa_get_wait_time_for_pwr_cmd
+ *
+ * Compute the amount of time we need to wait after updating the touchpad
+ * power mode. The touchpad needs to consume the incoming power mode set
+ * command at the current clock rate.
+ */
+
+static u16 cyapa_get_wait_time_for_pwr_cmd(u8 pwr_mode)
+{
+ switch (pwr_mode) {
+ case PWR_MODE_FULL_ACTIVE: return 20;
+ case PWR_MODE_BTN_ONLY: return 20;
+ case PWR_MODE_OFF: return 20;
+ default: return cyapa_pwr_cmd_to_sleep_time(pwr_mode) + 50;
+ }
+}
+
+/*
+ * Set device power mode
+ *
+ * Write to the field to configure power state. Power states include :
+ * Full : Max scans and report rate.
+ * Idle : Report rate set by user specified time.
+ * ButtonOnly : No scans for fingers. When the button is triggered,
+ * a slave interrupt is asserted to notify host to wake up.
+ * Off : Only awake for i2c commands from host. No function for button
+ * or touch sensors.
+ *
+ * The power_mode command should conform to the following :
+ * Full : 0x3f
+ * Idle : Configurable from 20 to 1000ms. See note below for
+ * cyapa_sleep_time_to_pwr_cmd and cyapa_pwr_cmd_to_sleep_time
+ * ButtonOnly : 0x01
+ * Off : 0x00
+ *
+ * Device power mode can only be set when device is in operational mode.
+ */
+static int cyapa_gen3_set_power_mode(struct cyapa *cyapa, u8 power_mode,
+ u16 always_unused)
+{
+ int ret;
+ u8 power;
+ int tries = SET_POWER_MODE_TRIES;
+ u16 sleep_time;
+
+ always_unused = 0;
+ if (cyapa->state != CYAPA_STATE_OP)
+ return 0;
+
+ while (true) {
+ ret = cyapa_read_byte(cyapa, CYAPA_CMD_POWER_MODE);
+ if (ret >= 0 || --tries < 1)
+ break;
+ usleep_range(SET_POWER_MODE_DELAY, 2 * SET_POWER_MODE_DELAY);
+ }
+ if (ret < 0)
+ return ret;
+
+ /*
+ * Return early if the power mode to set is the same as the current
+ * one.
+ */
+ if ((ret & PWR_MODE_MASK) == power_mode)
+ return 0;
+
+ sleep_time = cyapa_get_wait_time_for_pwr_cmd(ret & PWR_MODE_MASK);
+ power = ret;
+ power &= ~PWR_MODE_MASK;
+ power |= power_mode & PWR_MODE_MASK;
+ while (true) {
+ ret = cyapa_write_byte(cyapa, CYAPA_CMD_POWER_MODE, power);
+ if (!ret || --tries < 1)
+ break;
+ usleep_range(SET_POWER_MODE_DELAY, 2 * SET_POWER_MODE_DELAY);
+ }
+
+ /*
+ * Wait for the newly set power command to go in at the previous
+ * clock speed (scanrate) used by the touchpad firmware. Not
+ * doing so before issuing the next command may result in errors
+ * depending on the command's content.
+ */
+ msleep(sleep_time);
+ return ret;
+}
+
+static int cyapa_gen3_get_query_data(struct cyapa *cyapa)
+{
+ u8 query_data[QUERY_DATA_SIZE];
+ int ret;
+
+ if (cyapa->state != CYAPA_STATE_OP)
+ return -EBUSY;
+
+ ret = cyapa_read_block(cyapa, CYAPA_CMD_GROUP_QUERY, query_data);
+ if (ret != QUERY_DATA_SIZE)
+ return (ret < 0) ? ret : -EIO;
+
+ memcpy(&cyapa->product_id[0], &query_data[0], 5);
+ cyapa->product_id[5] = '-';
+ memcpy(&cyapa->product_id[6], &query_data[5], 6);
+ cyapa->product_id[12] = '-';
+ memcpy(&cyapa->product_id[13], &query_data[11], 2);
+ cyapa->product_id[15] = '\0';
+
+ cyapa->fw_maj_ver = query_data[15];
+ cyapa->fw_min_ver = query_data[16];
+
+ cyapa->btn_capability = query_data[19] & CAPABILITY_BTN_MASK;
+
+ cyapa->gen = query_data[20] & 0x0f;
+
+ cyapa->max_abs_x = ((query_data[21] & 0xf0) << 4) | query_data[22];
+ cyapa->max_abs_y = ((query_data[21] & 0x0f) << 8) | query_data[23];
+
+ cyapa->physical_size_x =
+ ((query_data[24] & 0xf0) << 4) | query_data[25];
+ cyapa->physical_size_y =
+ ((query_data[24] & 0x0f) << 8) | query_data[26];
+
+ cyapa->max_z = 255;
+
+ return 0;
+}
+
+static int cyapa_gen3_bl_query_data(struct cyapa *cyapa)
+{
+ u8 bl_data[CYAPA_CMD_LEN];
+ int ret;
+
+ ret = cyapa_i2c_reg_read_block(cyapa, 0, CYAPA_CMD_LEN, bl_data);
+ if (ret != CYAPA_CMD_LEN)
+ return (ret < 0) ? ret : -EIO;
+
+ /*
+ * This value will be updated again when entered application mode.
+ * If TP failed to enter application mode, this fw version values
+ * can be used as a reference.
+ * This firmware version valid when fw image checksum is valid.
+ */
+ if (bl_data[REG_BL_STATUS] ==
+ (BL_STATUS_RUNNING | BL_STATUS_CSUM_VALID)) {
+ cyapa->fw_maj_ver = bl_data[GEN3_BL_IDLE_FW_MAJ_VER_OFFSET];
+ cyapa->fw_min_ver = bl_data[GEN3_BL_IDLE_FW_MIN_VER_OFFSET];
+ }
+
+ return 0;
+}
+
+/*
+ * Check if device is operational.
+ *
+ * An operational device is responding, has exited bootloader, and has
+ * firmware supported by this driver.
+ *
+ * Returns:
+ * -EBUSY no device or in bootloader
+ * -EIO failure while reading from device
+ * -EAGAIN device is still in bootloader
+ * if ->state = CYAPA_STATE_BL_IDLE, device has invalid firmware
+ * -EINVAL device is in operational mode, but not supported by this driver
+ * 0 device is supported
+ */
+static int cyapa_gen3_do_operational_check(struct cyapa *cyapa)
+{
+ struct device *dev = &cyapa->client->dev;
+ int ret;
+
+ switch (cyapa->state) {
+ case CYAPA_STATE_BL_ACTIVE:
+ ret = cyapa_gen3_bl_deactivate(cyapa);
+ if (ret) {
+ dev_err(dev, "failed to bl_deactivate. %d\n", ret);
+ return ret;
+ }
+
+ /* Fallthrough state */
+ case CYAPA_STATE_BL_IDLE:
+ /* Try to get firmware version in bootloader mode. */
+ cyapa_gen3_bl_query_data(cyapa);
+
+ ret = cyapa_gen3_bl_exit(cyapa);
+ if (ret) {
+ dev_err(dev, "failed to bl_exit. %d\n", ret);
+ return ret;
+ }
+
+ /* Fallthrough state */
+ case CYAPA_STATE_OP:
+ /*
+ * Reading query data before going back to the full mode
+ * may cause problems, so we set the power mode first here.
+ */
+ ret = cyapa_gen3_set_power_mode(cyapa, PWR_MODE_FULL_ACTIVE, 0);
+ if (ret)
+ dev_err(dev, "%s: set full power mode failed, (%d)\n",
+ __func__, ret);
+ ret = cyapa_gen3_get_query_data(cyapa);
+ if (ret < 0)
+ return ret;
+
+ /* Only support firmware protocol gen3 */
+ if (cyapa->gen != CYAPA_GEN3) {
+ dev_err(dev, "unsupported protocol version (%d)",
+ cyapa->gen);
+ return -EINVAL;
+ }
+
+ /* Only support product ID starting with CYTRA */
+ if (memcmp(cyapa->product_id, unique_str,
+ strlen(unique_str)) != 0) {
+ dev_err(dev, "unsupported product ID (%s)\n",
+ cyapa->product_id);
+ return -EINVAL;
+ }
+
+ data_reporting_started = true;
+ return 0;
+
+ default:
+ return -EIO;
+ }
+ return 0;
+}
+
+/*
+ * Return false, do not continue process
+ * Return true, continue process.
+ */
+static bool cyapa_gen3_irq_cmd_handler(struct cyapa *cyapa)
+{
+ /* Not gen3 irq command response, skip for continue. */
+ if (cyapa->gen != CYAPA_GEN3)
+ return true;
+
+ if (cyapa->input && data_reporting_started)
+ return true;
+
+ /*
+ * Driver in detecting or other interface function processing,
+ * so, stop cyapa_gen3_irq_handler to continue process to
+ * avoid unwanted to error detecting and processing.
+ *
+ * And also, avoid the periodicly accerted interrupts to be processed
+ * as touch inputs when gen3 failed to launch into application mode,
+ * which will cause gen3 stays in bootloader mode.
+ */
+ return false;
+}
+
+static int cyapa_gen3_irq_handler(struct cyapa *cyapa)
+{
+ struct input_dev *input = cyapa->input;
+ struct device *dev = &cyapa->client->dev;
+ struct cyapa_reg_data data;
+ int i;
+ int ret;
+ int num_fingers;
+
+ ret = cyapa_read_block(cyapa, CYAPA_CMD_GROUP_DATA, (u8 *)&data);
+ if (ret != sizeof(data)) {
+ dev_err(dev, "failed to read report data, (%d)\n", ret);
+ return -EINVAL;
+ }
+
+ if ((data.device_status & OP_STATUS_SRC) != OP_STATUS_SRC ||
+ (data.device_status & OP_STATUS_DEV) != CYAPA_DEV_NORMAL ||
+ (data.finger_btn & OP_DATA_VALID) != OP_DATA_VALID) {
+ dev_err(dev, "invalid device state bytes, %02x %02x\n",
+ data.device_status, data.finger_btn);
+ return -EINVAL;
+ }
+
+ num_fingers = (data.finger_btn >> 4) & 0x0f;
+ for (i = 0; i < num_fingers; i++) {
+ const struct cyapa_touch *touch = &data.touches[i];
+ /* Note: touch->id range is 1 to 15; slots are 0 to 14. */
+ int slot = touch->id - 1;
+
+ input_mt_slot(input, slot);
+ input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
+ input_report_abs(input, ABS_MT_POSITION_X,
+ ((touch->xy_hi & 0xf0) << 4) | touch->x_lo);
+ input_report_abs(input, ABS_MT_POSITION_Y,
+ ((touch->xy_hi & 0x0f) << 8) | touch->y_lo);
+ input_report_abs(input, ABS_MT_PRESSURE, touch->pressure);
+ }
+
+ input_mt_sync_frame(input);
+
+ if (cyapa->btn_capability & CAPABILITY_LEFT_BTN_MASK)
+ input_report_key(input, BTN_LEFT,
+ !!(data.finger_btn & OP_DATA_LEFT_BTN));
+ if (cyapa->btn_capability & CAPABILITY_MIDDLE_BTN_MASK)
+ input_report_key(input, BTN_MIDDLE,
+ !!(data.finger_btn & OP_DATA_MIDDLE_BTN));
+ if (cyapa->btn_capability & CAPABILITY_RIGHT_BTN_MASK)
+ input_report_key(input, BTN_RIGHT,
+ !!(data.finger_btn & OP_DATA_RIGHT_BTN));
+ input_sync(input);
+
+ return 0;
+}
+
+const struct cyapa_dev_ops cyapa_gen3_ops = {
+ .state_parse = cyapa_gen3_state_parse,
+ .operational_check = cyapa_gen3_do_operational_check,
+
+ .irq_handler = cyapa_gen3_irq_handler,
+ .irq_cmd_handler = cyapa_gen3_irq_cmd_handler,
+
+ .set_power_mode = cyapa_gen3_set_power_mode,
+};
--
1.9.1
^ permalink raw reply related
* [PATCH v9 01/18] input: cyapa: add device resource management infrastructure support
From: Dudley Du @ 2014-11-03 8:32 UTC (permalink / raw)
To: dmitry.torokhov, rydberg; +Cc: Dudley Du, bleung, linux-input, linux-kernel
In-Reply-To: <1415003590-30485-1-git-send-email-dudl@cypress.com>
Modify cyapa driver to support device resource management infrastructure
to reduce the mistakes of resource management.
TEST=test on Chromebooks.
Signed-off-by: Dudley Du <dudl@cypress.com>
---
drivers/input/mouse/cyapa.c | 48 ++++++++++++++++++---------------------------
1 file changed, 19 insertions(+), 29 deletions(-)
diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c
index b409c3d..b3d7a2a 100644
--- a/drivers/input/mouse/cyapa.c
+++ b/drivers/input/mouse/cyapa.c
@@ -409,11 +409,11 @@ static ssize_t cyapa_read_block(struct cyapa *cyapa, u8 cmd_idx, u8 *values)
cmd = cyapa_smbus_cmds[cmd_idx].cmd;
len = cyapa_smbus_cmds[cmd_idx].len;
return cyapa_smbus_read_block(cyapa, cmd, len, values);
- } else {
- cmd = cyapa_i2c_cmds[cmd_idx].cmd;
- len = cyapa_i2c_cmds[cmd_idx].len;
- return cyapa_i2c_reg_read_block(cyapa, cmd, len, values);
}
+
+ cmd = cyapa_i2c_cmds[cmd_idx].cmd;
+ len = cyapa_i2c_cmds[cmd_idx].len;
+ return cyapa_i2c_reg_read_block(cyapa, cmd, len, values);
}
/*
@@ -762,7 +762,7 @@ static int cyapa_create_input_dev(struct cyapa *cyapa)
if (!cyapa->physical_size_x || !cyapa->physical_size_y)
return -EINVAL;
- input = cyapa->input = input_allocate_device();
+ input = cyapa->input = devm_input_allocate_device(dev);
if (!input) {
dev_err(dev, "allocate memory for input device failed\n");
return -ENOMEM;
@@ -837,11 +837,9 @@ static int cyapa_probe(struct i2c_client *client,
return -EIO;
}
- cyapa = kzalloc(sizeof(struct cyapa), GFP_KERNEL);
- if (!cyapa) {
- dev_err(dev, "allocate memory for cyapa failed\n");
+ cyapa = devm_kzalloc(dev, sizeof(struct cyapa), GFP_KERNEL);
+ if (!cyapa)
return -ENOMEM;
- }
cyapa->gen = CYAPA_GEN3;
cyapa->client = client;
@@ -856,51 +854,43 @@ static int cyapa_probe(struct i2c_client *client,
ret = cyapa_check_is_operational(cyapa);
if (ret) {
dev_err(dev, "device not operational, %d\n", ret);
- goto err_mem_free;
+ return ret;
}
ret = cyapa_create_input_dev(cyapa);
if (ret) {
dev_err(dev, "create input_dev instance failed, %d\n", ret);
- goto err_mem_free;
+ return ret;
}
ret = cyapa_set_power_mode(cyapa, PWR_MODE_FULL_ACTIVE);
if (ret) {
dev_err(dev, "set active power failed, %d\n", ret);
- goto err_unregister_device;
+ return ret;
}
cyapa->irq = client->irq;
- ret = request_threaded_irq(cyapa->irq,
- NULL,
- cyapa_irq,
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- "cyapa",
- cyapa);
+ ret = devm_request_threaded_irq(dev,
+ cyapa->irq,
+ NULL,
+ cyapa_irq,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ "cyapa",
+ cyapa);
if (ret) {
dev_err(dev, "IRQ request failed: %d\n, ", ret);
- goto err_unregister_device;
+ return ret;
}
return 0;
-
-err_unregister_device:
- input_unregister_device(cyapa->input);
-err_mem_free:
- kfree(cyapa);
-
- return ret;
}
static int cyapa_remove(struct i2c_client *client)
{
struct cyapa *cyapa = i2c_get_clientdata(client);
- free_irq(cyapa->irq, cyapa);
- input_unregister_device(cyapa->input);
+ disable_irq(cyapa->irq);
cyapa_set_power_mode(cyapa, PWR_MODE_OFF);
- kfree(cyapa);
return 0;
}
--
1.9.1
^ permalink raw reply related
* [PATCH v9 01/18] input: cyapa: instruction of cyapa patches
From: Dudley Du @ 2014-11-03 8:32 UTC (permalink / raw)
To: dmitry.torokhov, rydberg; +Cc: Dudley Du, bleung, linux-input, linux-kernel
V9 patches have below updates compared with v8 patches:
1) Removed all async thread stuff from the driver.
2) Split driver into 18 patches for each function change one patch.
V8 patches have below updates compared with v7 patches:
1) [PATCH v8 01/13] - Remove the async thread for device detect in
probe routine, now the device detect process is completely done within
the device probe routine.
2) [PATCH v8 01/13] - Split the irq cmd hander function to separated
function cyapa_default_irq_cmd_handler() and set it to interface
cyapa_default_ops.irq_cmd_handler.
3) [PATCH v8 06/13] - Add cyapa->gen check in cyapa_gen3_irq_cmd_handler()
to avoid miss-enter when device protocol is still in detecting.
V7 patches have below updates compared with v6 patches:
1) [PATCH v7 01/13] - Split the irq cmd hander function to separated
function cyapa_default_irq_cmd_handler() and set it to interface
cyapa_default_ops.irq_cmd_handler.
2) [PATCH v7 06/13] - Add cyapa->gen check in cyapa_gen3_irq_cmd_handler()
to avoid miss-enter when device protocol is still in detecting.
V6 patches have below updates compared with v5 patches:
1) Remove patch 14 of the lid filtering from the cyapa driver.
V5 patches have below updates compared with v4 patches:
1) Uses get_device()/put_device() instead of kobject_get()/kobject_put();
2) Fix memories freed before debugfs entries issue;
3) Make cyapa_debugs_root valid in driver module level
in module_init()/moudle_exit() ;
4) Fix i2c_transfer() may return partial transfer issues.
5) Add cyapa->removed flag to avoid detecting thread may still running
when driver module is removed.
6) Fix the meanings of some comments and return error code not clear issue.
This patch set is aimed to re-design the cyapa driver to support
old gen3 trackpad devices and new gen5 trackpad devices in one
cyapa driver, it's for easily productions support based on
customers' requirements. And add sysfs functions and interfaces
supported that required by users and customers.
Since the earlier gen3 and the latest gen5 trackpad devices using
two different chipsets, and have different protocols and interfaces,
so if supported these two type trackpad devices in two different drivers,
then it will be difficult to manage productions and later firmware updates.
e.g.: It will cause customer don't know which one trackpad device firmware
image to use and update when it has been used and integrated
in same one productions, so here we support these two trackpad
devices in same on driver.
The new design cyapa driver contains:
cyapa.c - the core of the re-design, supply interfaces and
functions to system and read trackpad devices.
cyapa.h - header file including macros and data structure definitions.
cyapa_gen3.c - functions support for gen3 trackpad devices,
cyapa_gen5.c - functions support for gen5 trackpad devices.
Beside this introduction patch, it has 18 patches listed as below.
For these patches each one is patched based on previous one.
patch 1/18: add device resource management infrastructure supported.
patch 2/18: re-design cyapa driver with core functions and interface
to support multi-type trackpad devices.
patch 3/18: add gen3 trackpad device basic functions supported into the
re-design cyapa driver.
patch 4/18: add gen5 trackpad device basic functions supported into the
re-design cyapa driver.
patch 5/18: add power management interfaces supported for the deivce.
patch 6/18: add runtime power management interfaces supported for the device.
patch 7/18: add sysfs interfaces supported in the cyapa driver.
Including read firmware version, get production ID, read baseline,
re-calibrate trackpad baselines and do trackpad firmware update.
patch 8/18: add gen3 trackpad device's firmware update function supported.
patch 9/18: add gen3 trackpad device's read baseline function supported.
patch 10/18: add gen3 trackpad device's force re-calibrate function supported.
patch 11/18: add gen5 trackpad device's firmware update function supported.
patch 12/18: add gen5 trackpad device's read baseline function supported.
patch 13/18: add gen5 trackpad device's force re-calibrate function.
patch 14/18: add read firmware image debugfs interface supported
in the cyapa driver.
patch 15/18: add gen3 trackpad device's read firmware image function supported.
patch 16/18: add gen5 trackpad device's read firmware image function supported.
patch 17/18: add read trackpad device's sensors' raw data debugfs interface
supported in the cyapa driver.
patch 18/18: add gen5 trackpad device's read read raw function supported.
^ permalink raw reply
* [PATCH v9 18/18] input: cyapa: add gen5 trackpad device read raw data function support
From: Dudley Du @ 2014-11-03 8:33 UTC (permalink / raw)
To: dmitry.torokhov, rydberg; +Cc: Dudley Du, bleung, linux-input, linux-kernel
In-Reply-To: <1415003590-30485-1-git-send-email-dudl@cypress.com>
Add read raw data function supported for gen5 trackpad device,
it can be used through debugfs raw_data interface.
TEST=test on Chromebooks.
Signed-off-by: Dudley Du <dudl@cypress.com>
---
drivers/input/mouse/cyapa_gen5.c | 109 +++++++++++++++++++++++++++++++++++++++
1 file changed, 109 insertions(+)
diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c
index 35334dc..bbc2e20 100644
--- a/drivers/input/mouse/cyapa_gen5.c
+++ b/drivers/input/mouse/cyapa_gen5.c
@@ -2350,6 +2350,114 @@ resume_scanning:
return ret + err;
}
+static int cyapa_gen5_read_raw_data(struct cyapa *cyapa)
+{
+ int ret, err;
+ int raw_cap_mutual_max, raw_cap_mutual_min, raw_cap_mutual_ave;
+ int raw_cap_self_max, raw_cap_self_min, raw_cap_self_ave;
+ int offset;
+ int data_size, max, min, ave;
+ ktime_t time_mono;
+
+ offset = 0;
+ if (!cyapa->tp_raw_data) {
+ if (cyapa->state != CYAPA_STATE_GEN5_APP ||
+ !cyapa->electrodes_x || !cyapa->electrodes_y)
+ return -EINVAL;
+
+ cyapa->tp_raw_data_size = sizeof(s32) * (cyapa->electrodes_x *
+ cyapa->electrodes_y + cyapa->electrodes_x +
+ cyapa->electrodes_y) + GEN5_RAW_DATA_HEAD_SIZE;
+ /*
+ * This buffer will be hold after used until the driver is
+ * unloaded, the purpose of it is to improve the performace
+ * to avoid frequently allocate and release the buffer.
+ */
+ cyapa->tp_raw_data = devm_kzalloc(&cyapa->client->dev,
+ cyapa->tp_raw_data_size, GFP_KERNEL);
+ if (!cyapa->tp_raw_data)
+ return -ENOMEM;
+ }
+
+ /*
+ * 1. Suspend Scanning.
+ *
+ * After suspend scanning, the raw data will not be updated,
+ * so the time of the raw data is before scanning suspended.
+ */
+ time_mono = ktime_get();
+ ret = cyapa_gen5_suspend_scanning(cyapa);
+ if (ret)
+ return ret;
+
+ /* 2. Get the correct electrodes_rx number. */
+ if (cyapa->electrodes_rx == 0) {
+ /*
+ * Through the read global idac interface to get the Rx number.
+ * this value is useful to the raw data map.
+ */
+ data_size = 0;
+ err = cyapa_gen5_read_idac_data(cyapa,
+ GEN5_CMD_RETRIEVE_DATA_STRUCTURE,
+ GEN5_RETRIEVE_MUTUAL_PWC_DATA,
+ &data_size, &max, &min, &ave);
+ if (err || cyapa->electrodes_rx == 0)
+ goto resume_scanning;
+ }
+
+ /* 3. Execuate panel scan. It must be executed before read data. */
+ err = cyapa_gen5_execute_panel_scan(cyapa);
+ if (err)
+ goto resume_scanning;
+
+ /* 4. Retrieve panel scan, mutual cap raw data. */
+ offset = GEN5_RAW_DATA_HEAD_SIZE;
+ err = cyapa_gen5_read_panel_scan_raw_data(cyapa,
+ GEN5_CMD_RETRIEVE_PANEL_SCAN,
+ GEN5_PANEL_SCAN_MUTUAL_DIFFCOUNT,
+ cyapa->electrodes_x * cyapa->electrodes_y,
+ &raw_cap_mutual_max, &raw_cap_mutual_min,
+ &raw_cap_mutual_ave,
+ cyapa->tp_raw_data + offset);
+ if (err)
+ goto resume_scanning;
+
+ offset += sizeof(s32) * cyapa->electrodes_x * cyapa->electrodes_y;
+
+ /* 5. Retrieve panel scan, self cap raw data. */
+ err = cyapa_gen5_read_panel_scan_raw_data(cyapa,
+ GEN5_CMD_RETRIEVE_PANEL_SCAN,
+ GEN5_PANEL_SCAN_SELF_DIFFCOUNT,
+ cyapa->electrodes_x + cyapa->electrodes_y,
+ &raw_cap_self_max, &raw_cap_self_min,
+ &raw_cap_self_ave,
+ cyapa->tp_raw_data + offset);
+ if (err)
+ goto resume_scanning;
+
+ offset += sizeof(s32) * (cyapa->electrodes_x + cyapa->electrodes_y);
+
+resume_scanning:
+ /* 6. Resume Scanning*/
+ ret = cyapa_gen5_resume_scanning(cyapa);
+ if (ret || err)
+ return ret ? ret : err;
+
+ *((struct timeval *)&cyapa->tp_raw_data[0]) =
+ ktime_to_timeval(time_mono);
+ cyapa->tp_raw_data[16] = (u8)cyapa->electrodes_x;
+ cyapa->tp_raw_data[17] = (u8)cyapa->electrodes_y;
+ cyapa->tp_raw_data[18] = (u8)cyapa->x_origin;
+ cyapa->tp_raw_data[19] = (u8)cyapa->y_origin;
+ cyapa->tp_raw_data[20] = (u8)sizeof(s32);
+ cyapa->tp_raw_data[21] = (u8)sizeof(s32);
+ cyapa->tp_raw_data[22] = (u8)cyapa->electrodes_rx;
+ cyapa->tp_raw_data[23] = 0; /* Reserved. */
+
+ cyapa->tp_raw_data_size = offset;
+ return 0;
+}
+
static bool cyapa_gen5_sort_system_info_data(struct cyapa *cyapa,
u8 *buf, int len)
{
@@ -2762,6 +2870,7 @@ const struct cyapa_dev_ops cyapa_gen5_ops = {
.calibrate_store = cyapa_gen5_do_calibrate,
.read_fw = cyapa_gen5_read_fw,
+ .read_raw_data = cyapa_gen5_read_raw_data,
.initialize = cyapa_gen5_initialize,
--
1.9.1
^ permalink raw reply related
* [PATCH v9 16/18] input: cyapa: add gen5 trackpad device read firmware image function support
From: Dudley Du @ 2014-11-03 8:33 UTC (permalink / raw)
To: dmitry.torokhov, rydberg; +Cc: Dudley Du, bleung, linux-input, linux-kernel
In-Reply-To: <1415003590-30485-1-git-send-email-dudl@cypress.com>
Add read firmware image function supported for gen5 trackpad device,
it can be used through debugfs read_fw interface.
TEST=test on Chromebooks.
Signed-off-by: Dudley Du <dudl@cypress.com>
---
drivers/input/mouse/cyapa_gen5.c | 154 +++++++++++++++++++++++++++++++++++++++
1 file changed, 154 insertions(+)
diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c
index 7e7de12..35334dc 100644
--- a/drivers/input/mouse/cyapa_gen5.c
+++ b/drivers/input/mouse/cyapa_gen5.c
@@ -1213,6 +1213,153 @@ static int cyapa_gen5_write_fw_block(struct cyapa *cyapa,
return 0;
}
+static int cyapa_gen5_read_fw_bytes(struct cyapa *cyapa, u16 row_num, u8 *data)
+{
+ int ret;
+ u8 cmd[16];
+ size_t cmd_len;
+ u8 resp_data[CYAPA_TSG_FW_ROW_SIZE / 2 + GEN5_MIN_BL_RESP_LENGTH];
+ int resp_len;
+ u16 offset;
+ u16 cmd_crc;
+ struct cyapa_tsg_bin_image_data_record *fw_img_record;
+
+ fw_img_record = (struct cyapa_tsg_bin_image_data_record *)data;
+
+ cmd[0] = 0x04; /* Register address */
+ cmd[1] = 0x00;
+ cmd[2] = 0x0e;
+ cmd[3] = 0x00;
+ cmd[4] = 0x40; /* Report id 40h */
+ cmd[5] = 0x00;
+ cmd[6] = GEN5_SOP_KEY;
+ cmd[7] = 0x3d; /* Read application image command code */
+ cmd[8] = 0x03;
+ cmd[9] = 0x00;
+ offset = row_num * CYAPA_TSG_FW_ROW_SIZE -
+ CYAPA_TSG_START_OF_APPLICATION;
+ put_unaligned_le16(offset, &cmd[10]);
+ cmd[12] = CYAPA_TSG_IMG_READ_SIZE;
+ cmd_crc = crc_itu_t(0xffff, &cmd[6], 7);
+ put_unaligned_le16(cmd_crc, &cmd[13]); /* CRC[15:0] */
+ cmd[15] = GEN5_EOP_KEY; /* EOP = 17h */
+ cmd_len = 16;
+
+ resp_len = CYAPA_TSG_IMG_READ_SIZE + GEN5_MIN_BL_RESP_LENGTH;
+ ret = cyapa_i2c_pip_cmd_irq_sync(cyapa,
+ cmd, cmd_len,
+ resp_data, &resp_len,
+ 50, cyapa_gen5_sort_tsg_pip_bl_resp_data, true);
+ if (resp_len != (CYAPA_TSG_IMG_READ_SIZE + GEN5_MIN_BL_RESP_LENGTH) ||
+ ret || resp_data[2] != GEN5_BL_RESP_REPORT_ID ||
+ !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5]))
+ return (ret < 0) ? ret : -EAGAIN;
+
+ /* Copy first 64 bytes in the row. */
+ memcpy(&fw_img_record->record_data[0], &resp_data[8],
+ CYAPA_TSG_IMG_READ_SIZE);
+
+ if (row_num == CYAPA_TSG_IMG_APP_INTEGRITY_ROW_NUM) {
+ /* Last row's rest 64 bytes are bootloader metadata,
+ * it's not allowed to be read out, will respond with error. */
+ memset(&fw_img_record->record_data[CYAPA_TSG_IMG_READ_SIZE],
+ 0, CYAPA_TSG_IMG_READ_SIZE);
+ goto skip_last_row;
+ }
+
+ /* Read next 64 bytes in the row. */
+ offset = offset + CYAPA_TSG_IMG_READ_SIZE;
+ put_unaligned_le16(offset, &cmd[10]);
+ cmd_crc = crc_itu_t(0xffff, &cmd[6], 7);
+ put_unaligned_le16(cmd_crc, &cmd[13]); /* CRC[15:0] */
+ ret = cyapa_i2c_pip_cmd_irq_sync(cyapa,
+ cmd, cmd_len,
+ resp_data, &resp_len,
+ 500, cyapa_gen5_sort_tsg_pip_bl_resp_data, true);
+ if (resp_len != (CYAPA_TSG_IMG_READ_SIZE + GEN5_MIN_BL_RESP_LENGTH) ||
+ ret || resp_data[2] != GEN5_BL_RESP_REPORT_ID ||
+ !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5]))
+ return (ret < 0) ? ret : -EAGAIN;
+
+ /* Copy last 64 bytes in the row. */
+ memcpy(&fw_img_record->record_data[CYAPA_TSG_IMG_READ_SIZE],
+ &resp_data[8], CYAPA_TSG_IMG_READ_SIZE);
+
+skip_last_row:
+ fw_img_record->flash_array_id = 0;
+ put_unaligned_be16(row_num, &fw_img_record->row_number);
+ put_unaligned_be16(CYAPA_TSG_FW_ROW_SIZE, &fw_img_record->record_len);
+
+ return 0;
+}
+
+static int cyapa_gen5_read_fw(struct cyapa *cyapa)
+{
+ int ret;
+ int fw_img_head_size;
+ int fw_img_record_size;
+ int fw_img_size;
+ int row_index;
+ int array_index;
+ u32 img_start;
+ u16 img_len;
+ u16 img_start_row;
+ u16 img_end_row;
+ struct cyapa_tsg_bin_image_data_record app_integrity;
+ u8 *record_data;
+
+ ret = cyapa_gen5_bl_enter(cyapa);
+ if (ret)
+ return ret;
+
+ cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);
+
+ fw_img_head_size = sizeof(struct cyapa_tsg_bin_image_head);
+ fw_img_record_size = sizeof(struct cyapa_tsg_bin_image_data_record);
+
+ /* Read app integrity block data. */
+ row_index = CYAPA_TSG_IMG_APP_INTEGRITY_ROW_NUM;
+ ret = cyapa_gen5_read_fw_bytes(cyapa, row_index, (u8 *)&app_integrity);
+ if (ret)
+ return ret;
+ img_start = get_unaligned_le32(&app_integrity.record_data[16]);
+ img_len = get_unaligned_le16(&app_integrity.record_data[20]);
+ if ((img_start + img_len) % CYAPA_TSG_FW_ROW_SIZE)
+ return -EINVAL;
+ img_start_row = img_start / CYAPA_TSG_FW_ROW_SIZE;
+ img_end_row = (img_start + img_len) / CYAPA_TSG_FW_ROW_SIZE - 1;
+
+ /* Allocate memory for image. */
+ fw_img_size = fw_img_head_size +
+ (img_end_row - img_start_row + 2) * fw_img_record_size;
+ cyapa->fw_image = cyapa->fw_image ? cyapa->fw_image :
+ devm_kzalloc(&cyapa->client->dev, fw_img_size, GFP_KERNEL);
+ if (!cyapa->fw_image)
+ return -ENOMEM;
+
+ /* Set image head data. */
+ memcpy(cyapa->fw_image, &cyapa->fw_img_head, fw_img_head_size);
+
+ /* Read image blocks. */
+ for (row_index = img_start_row, array_index = 0;
+ row_index <= img_end_row;
+ row_index++, array_index++) {
+ record_data = &cyapa->fw_image[fw_img_head_size +
+ array_index * fw_img_record_size];
+ ret = cyapa_gen5_read_fw_bytes(cyapa, row_index, record_data);
+ if (ret)
+ return ret;
+ }
+
+ /* Append last app integrity block data. */
+ record_data = &cyapa->fw_image[fw_img_head_size +
+ array_index * fw_img_record_size];
+ memcpy(record_data, &app_integrity, fw_img_record_size);
+
+ cyapa->fw_image_size = fw_img_size;
+ return 0;
+}
+
static int cyapa_gen5_do_fw_update(struct cyapa *cyapa,
const struct firmware *fw)
{
@@ -2276,6 +2423,11 @@ static int cyapa_gen5_get_query_data(struct cyapa *cyapa)
if (ret || resp_len < sizeof(resp_data))
return ret;
+ cyapa->fw_img_head.head_size =
+ sizeof(struct cyapa_tsg_bin_image_head) - 1;
+ memcpy(&cyapa->fw_img_head.ttda_driver_major_version,
+ &resp_data[5], cyapa->fw_img_head.head_size);
+
product_family = get_unaligned_le16(&resp_data[7]);
if ((product_family & GEN5_PRODUCT_FAMILY_MASK) !=
GEN5_PRODUCT_FAMILY_TRACKPAD)
@@ -2609,6 +2761,8 @@ const struct cyapa_dev_ops cyapa_gen5_ops = {
.show_baseline = cyapa_gen5_show_baseline,
.calibrate_store = cyapa_gen5_do_calibrate,
+ .read_fw = cyapa_gen5_read_fw,
+
.initialize = cyapa_gen5_initialize,
.state_parse = cyapa_gen5_state_parse,
--
1.9.1
^ permalink raw reply related
* [PATCH v9 15/18] input: cyapa: add gen3 trackpad device read firmware image function support
From: Dudley Du @ 2014-11-03 8:33 UTC (permalink / raw)
To: dmitry.torokhov, rydberg; +Cc: Dudley Du, bleung, linux-input, linux-kernel
In-Reply-To: <1415003590-30485-1-git-send-email-dudl@cypress.com>
Add read firmware image function supported for gen3 trackpad device,
it can be used through debugfs read_fw interface.
TEST=test on Chromebooks.
Signed-off-by: Dudley Du <dudl@cypress.com>
---
drivers/input/mouse/cyapa_gen3.c | 67 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 67 insertions(+)
diff --git a/drivers/input/mouse/cyapa_gen3.c b/drivers/input/mouse/cyapa_gen3.c
index b477d67..f8aeb58 100644
--- a/drivers/input/mouse/cyapa_gen3.c
+++ b/drivers/input/mouse/cyapa_gen3.c
@@ -710,6 +710,36 @@ static int cyapa_gen3_write_fw_block(struct cyapa *cyapa,
return ret;
}
+/*
+ * A firmware block read command reads 16 bytes of data from flash starting
+ * from a given address. The 12-byte block read command has the format:
+ * <0xff> <CMD> <Key> <Addr>
+ *
+ * <0xff> - every command starts with 0xff
+ * <CMD> - the read command value is 0x3c
+ * <Key> - read commands include an 8-byte key: { 00 01 02 03 04 05 06 07 }
+ * <Addr> - Memory address (16-bit, big-endian)
+ *
+ * The command is followed by an i2c block read to read the 16 bytes of data.
+ */
+static int cyapa_gen3_read_fw_bytes(struct cyapa *cyapa, u16 addr, u8 *data)
+{
+ int ret;
+ u8 cmd[] = { 0xff, 0x3c, 0x00, 0x01, 0x02, 0x03, 0x04,
+ 0x05, 0x06, 0x07, addr >> 8, addr };
+
+ ret = cyapa_gen3_write_buffer(cyapa, cmd, sizeof(cmd));
+ if (ret)
+ return ret;
+
+ /* Read data buffer starting from offset 16 */
+ ret = cyapa_i2c_reg_read_block(cyapa, 16, CYAPA_FW_READ_SIZE, data);
+ if (ret != CYAPA_FW_READ_SIZE)
+ return (ret < 0) ? ret : -EIO;
+
+ return 0;
+}
+
static int cyapa_gen3_write_blocks(struct cyapa *cyapa,
size_t start_block, size_t block_count,
const u8 *image_data)
@@ -756,6 +786,41 @@ static int cyapa_gen3_do_fw_update(struct cyapa *cyapa,
return 0;
}
+/*
+ * Read the entire firmware image into ->fw_image.
+ * If the ->fw_image has already been allocated, then this function
+ * doesn't do anything and just returns 0.
+ * If an error occurs while reading the image, ->fw_image is freed, and
+ * the error is returned.
+ *
+ * The firmware is a fixed size (CYAPA_FW_SIZE), and is read out in
+ * fixed length (CYAPA_FW_READ_SIZE) chunks.
+ */
+static int cyapa_gen3_read_fw(struct cyapa *cyapa)
+{
+ int ret;
+ int addr;
+
+ ret = cyapa_gen3_bl_enter(cyapa);
+ if (ret)
+ return ret;
+
+ cyapa->fw_image = cyapa->fw_image ? cyapa->fw_image :
+ devm_kzalloc(&cyapa->client->dev, CYAPA_FW_SIZE, GFP_KERNEL);
+ if (!cyapa->fw_image)
+ return -ENOMEM;
+
+ for (addr = 0; addr < CYAPA_FW_SIZE; addr += CYAPA_FW_READ_SIZE) {
+ ret = cyapa_gen3_read_fw_bytes(cyapa, CYAPA_FW_HDR_START + addr,
+ &cyapa->fw_image[addr]);
+ if (ret)
+ return ret;
+ }
+
+ cyapa->fw_image_size = CYAPA_FW_SIZE;
+ return 0;
+}
+
static ssize_t cyapa_gen3_do_calibrate(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
@@ -1203,6 +1268,8 @@ const struct cyapa_dev_ops cyapa_gen3_ops = {
.show_baseline = cyapa_gen3_show_baseline,
.calibrate_store = cyapa_gen3_do_calibrate,
+ .read_fw = cyapa_gen3_read_fw,
+
.state_parse = cyapa_gen3_state_parse,
.operational_check = cyapa_gen3_do_operational_check,
--
1.9.1
^ permalink raw reply related
* [PATCH v9 14/18] input: cyapa: add read firmware image debugfs interface support
From: Dudley Du @ 2014-11-03 8:33 UTC (permalink / raw)
To: dmitry.torokhov, rydberg; +Cc: Dudley Du, bleung, linux-input, linux-kernel
In-Reply-To: <1415003590-30485-1-git-send-email-dudl@cypress.com>
Add read firmware image from trackpad device interface supported in cyapa
driver through debugfs read_fw interface.
Through this interface user can read out, check and backup the firmware image
of the trackpad device before any firmware update, or can use the backed image
to do firmware image recovery.
TEST=test on Chromebooks.
Signed-off-by: Dudley Du <dudl@cypress.com>
---
drivers/input/mouse/cyapa.c | 174 +++++++++++++++++++++++++++++++++++++++++++-
drivers/input/mouse/cyapa.h | 11 +++
2 files changed, 184 insertions(+), 1 deletion(-)
diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c
index 5f384ff..bc1d75a 100644
--- a/drivers/input/mouse/cyapa.c
+++ b/drivers/input/mouse/cyapa.c
@@ -14,6 +14,7 @@
* more details.
*/
+#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/input.h>
@@ -38,6 +39,9 @@
const char unique_str[] = "CYTRA";
+/* Global root node of the cyapa debugfs directory. */
+static struct dentry *cyapa_debugfs_root;
+
ssize_t cyapa_i2c_reg_read_block(struct cyapa *cyapa, u8 reg, size_t len,
u8 *values)
@@ -475,6 +479,134 @@ int cyapa_detect(struct cyapa *cyapa)
}
/*
+ **************************************************************
+ * debugfs interface
+ **************************************************************
+*/
+static int cyapa_debugfs_open(struct inode *inode, struct file *file)
+{
+ struct cyapa *cyapa = inode->i_private;
+ int ret;
+
+ if (!cyapa)
+ return -ENODEV;
+
+ ret = mutex_lock_interruptible(&cyapa->debugfs_mutex);
+ if (ret)
+ return ret;
+
+ if (!get_device(&cyapa->client->dev)) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ file->private_data = cyapa;
+
+ if (cyapa->fw_image && cyapa->fw_image_size) {
+ ret = 0;
+ goto out;
+ }
+
+ ret = mutex_lock_interruptible(&cyapa->state_sync_lock);
+ if (ret)
+ goto out;
+ /*
+ * If firmware hasn't been read yet, read it all in one pass.
+ * Subsequent opens will reuse the data in this same buffer.
+ */
+ if (cyapa->ops->read_fw) {
+ ret = cyapa->ops->read_fw(cyapa);
+
+ /*
+ * Redetect trackpad device states because read_fw will
+ * reset trackpad device into bootloader mode.
+ */
+ cyapa_detect(cyapa);
+ } else
+ ret = -EPERM;
+
+ mutex_unlock(&cyapa->state_sync_lock);
+out:
+ mutex_unlock(&cyapa->debugfs_mutex);
+ return ret;
+}
+
+static int cyapa_debugfs_release(struct inode *inode, struct file *file)
+{
+ struct cyapa *cyapa = file->private_data;
+ int ret;
+
+ if (!cyapa)
+ return 0;
+
+ ret = mutex_lock_interruptible(&cyapa->debugfs_mutex);
+ if (ret)
+ return ret;
+ file->private_data = NULL;
+ put_device(&cyapa->client->dev);
+ mutex_unlock(&cyapa->debugfs_mutex);
+
+ return 0;
+}
+
+/* Return some bytes from the buffered firmware image, starting from *ppos */
+static ssize_t cyapa_debugfs_read_fw(struct file *file, char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ struct cyapa *cyapa = file->private_data;
+
+ if (!cyapa->fw_image)
+ return -EINVAL;
+
+ if (*ppos >= cyapa->fw_image_size)
+ return 0;
+
+ if (count + *ppos > cyapa->fw_image_size)
+ count = cyapa->fw_image_size - *ppos;
+
+ if (copy_to_user(buffer, &cyapa->fw_image[*ppos], count))
+ return -EFAULT;
+
+ *ppos += count;
+ return count;
+}
+
+static const struct file_operations cyapa_read_fw_fops = {
+ .open = cyapa_debugfs_open,
+ .release = cyapa_debugfs_release,
+ .read = cyapa_debugfs_read_fw
+};
+
+static int cyapa_debugfs_init(struct cyapa *cyapa)
+{
+ struct device *dev = &cyapa->client->dev;
+
+ if (!cyapa_debugfs_root)
+ return -ENODEV;
+
+ cyapa->dentry_dev = debugfs_create_dir(kobject_name(&dev->kobj),
+ cyapa_debugfs_root);
+
+ if (!cyapa->dentry_dev)
+ return -ENODEV;
+
+ mutex_init(&cyapa->debugfs_mutex);
+
+ debugfs_create_file(CYAPA_DEBUGFS_READ_FW, S_IRUSR, cyapa->dentry_dev,
+ cyapa, &cyapa_read_fw_fops);
+
+ return 0;
+}
+
+static void cyapa_remove_debugfs(void *data)
+{
+ struct cyapa *cyapa = data;
+
+ debugfs_remove_recursive(cyapa->dentry_dev);
+ mutex_destroy(&cyapa->debugfs_mutex);
+}
+
+/*
* Sysfs Interface.
*/
@@ -1012,6 +1144,20 @@ static int cyapa_probe(struct i2c_client *client,
return ret;
}
+ ret = cyapa_debugfs_init(cyapa);
+ if (ret) {
+ dev_err(dev, "failed to create debugfs entries, (%d).\n", ret);
+ return ret;
+ }
+
+ ret = devm_add_action(dev, cyapa_remove_debugfs, cyapa);
+ if (ret) {
+ cyapa_remove_debugfs(cyapa);
+ dev_err(dev, "failed to add debugfs cleanup action, (%d)\n",
+ ret);
+ return ret;
+ }
+
#ifdef CONFIG_PM_SLEEP
if (device_can_wakeup(dev)) {
ret = sysfs_merge_group(&client->dev.kobj,
@@ -1192,7 +1338,33 @@ static struct i2c_driver cyapa_driver = {
.id_table = cyapa_id_table,
};
-module_i2c_driver(cyapa_driver);
+static int __init cyapa_init(void)
+{
+ int ret;
+
+ /* Create a global debugfs root for all cyapa devices */
+ cyapa_debugfs_root = debugfs_create_dir("cyapa", NULL);
+ if (cyapa_debugfs_root == ERR_PTR(-ENODEV))
+ cyapa_debugfs_root = NULL;
+
+ ret = i2c_add_driver(&cyapa_driver);
+ if (ret) {
+ pr_err("cyapa driver register FAILED.\n");
+ return ret;
+ }
+
+ return ret;
+}
+
+static void __exit cyapa_exit(void)
+{
+ debugfs_remove_recursive(cyapa_debugfs_root);
+
+ i2c_del_driver(&cyapa_driver);
+}
+
+module_init(cyapa_init);
+module_exit(cyapa_exit);
MODULE_DESCRIPTION("Cypress APA I2C Trackpad Driver");
MODULE_AUTHOR("Dudley Du <dudl@cypress.com>");
diff --git a/drivers/input/mouse/cyapa.h b/drivers/input/mouse/cyapa.h
index 060ac7d..288c7de 100644
--- a/drivers/input/mouse/cyapa.h
+++ b/drivers/input/mouse/cyapa.h
@@ -189,6 +189,8 @@ struct cyapa_dev_ops {
ssize_t (*calibrate_store)(struct device *,
struct device_attribute *, const char *, size_t);
+ int (*read_fw)(struct cyapa *);
+
int (*initialize)(struct cyapa *cyapa);
int (*state_parse)(struct cyapa *cyapa, u8 *reg_status, int len);
@@ -288,6 +290,15 @@ struct cyapa {
*/
struct mutex state_sync_lock;
+ /* Per-instance debugfs root */
+ struct dentry *dentry_dev;
+
+ /* Buffer to store firmware read using debugfs */
+ struct mutex debugfs_mutex;
+ struct cyapa_tsg_bin_image_head fw_img_head;
+ u8 *fw_image;
+ size_t fw_image_size;
+
const struct cyapa_dev_ops *ops;
union cyapa_cmd_states cmd_states;
--
1.9.1
^ permalink raw reply related
* [PATCH v9 13/18] input: cyapa: add gen5 trackpad device force re-calibrate function support
From: Dudley Du @ 2014-11-03 8:33 UTC (permalink / raw)
To: dmitry.torokhov, rydberg; +Cc: Dudley Du, bleung, linux-input, linux-kernel
In-Reply-To: <1415003590-30485-1-git-send-email-dudl@cypress.com>
Add force re-calibrate function supported for gen5 trackpad device,
it can be used through sysfs calibrate interface.
TEST=test on Chromebooks.
Signed-off-by: Dudley Du <dudl@cypress.com>
---
drivers/input/mouse/cyapa_gen5.c | 65 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 65 insertions(+)
diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c
index 011c8f5..7e7de12 100644
--- a/drivers/input/mouse/cyapa_gen5.c
+++ b/drivers/input/mouse/cyapa_gen5.c
@@ -1583,6 +1583,70 @@ static int cyapa_gen5_suspend_scanning(struct cyapa *cyapa)
return 0;
}
+static int cyapa_gen5_calibrate_pwcs(struct cyapa *cyapa,
+ u8 calibrate_sensing_mode_type)
+{
+ int ret;
+ u8 cmd[8];
+ u8 resp_data[6];
+ int resp_len;
+
+ /* Try to dump all bufferred data before doing command. */
+ cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);
+
+ cmd[0] = 0x04;
+ cmd[1] = 0x00;
+ cmd[2] = 0x06;
+ cmd[3] = 0x00;
+ cmd[4] = GEN5_APP_CMD_REPORT_ID;
+ cmd[5] = 0x00;
+ cmd[6] = GEN5_CMD_CALIBRATE;
+ cmd[7] = calibrate_sensing_mode_type;
+ resp_len = sizeof(resp_data);
+ ret = cyapa_i2c_pip_cmd_irq_sync(cyapa,
+ cmd, sizeof(cmd),
+ resp_data, &resp_len,
+ 5000, cyapa_gen5_sort_tsg_pip_app_resp_data, true);
+ if (ret || !VALID_CMD_RESP_HEADER(resp_data, GEN5_CMD_CALIBRATE) ||
+ !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5]))
+ return ret < 0 ? ret : -EAGAIN;
+
+ return 0;
+}
+
+static ssize_t cyapa_gen5_do_calibrate(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct cyapa *cyapa = dev_get_drvdata(dev);
+ int ret, calibrate_ret;
+
+ /* 1. Suspend Scanning*/
+ ret = cyapa_gen5_suspend_scanning(cyapa);
+ if (ret)
+ return ret;
+
+ /* 2. Do mutual capacitance fine calibrate. */
+ calibrate_ret = cyapa_gen5_calibrate_pwcs(cyapa,
+ CYAPA_SENSING_MODE_MUTUAL_CAP_FINE);
+ if (calibrate_ret)
+ goto resume_scanning;
+
+ /* 3. Do self capacitance calibrate. */
+ calibrate_ret = cyapa_gen5_calibrate_pwcs(cyapa,
+ CYAPA_SENSING_MODE_SELF_CAP);
+ if (calibrate_ret)
+ goto resume_scanning;
+
+resume_scanning:
+ /* 4. Resume Scanning*/
+ ret = cyapa_gen5_resume_scanning(cyapa);
+ if (ret || calibrate_ret)
+ return ret ? ret : calibrate_ret;
+
+ return count;
+}
+
static s32 two_complement_to_s32(s32 value, int num_bits)
{
if (value >> (num_bits - 1))
@@ -2543,6 +2607,7 @@ const struct cyapa_dev_ops cyapa_gen5_ops = {
.update_fw = cyapa_gen5_do_fw_update,
.show_baseline = cyapa_gen5_show_baseline,
+ .calibrate_store = cyapa_gen5_do_calibrate,
.initialize = cyapa_gen5_initialize,
--
1.9.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox