diff options
-rw-r--r-- | Documentation/DocBook/Makefile | 2 | ||||
-rw-r--r-- | Documentation/DocBook/ste_ff_vibra.tmpl | 217 | ||||
-rwxr-xr-x | arch/arm/mach-ux500/board-mop500.c | 6 | ||||
-rw-r--r-- | drivers/input/misc/Kconfig | 11 | ||||
-rw-r--r-- | drivers/input/misc/Makefile | 1 | ||||
-rw-r--r-- | drivers/input/misc/ste_ff_vibra.c | 223 |
6 files changed, 459 insertions, 1 deletions
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index e7bac452b3c..917cc5b8af1 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -16,7 +16,7 @@ DOCBOOKS := z8530book.xml mcabook.xml device-drivers.xml \ alsa-driver-api.xml writing-an-alsa-driver.xml \ tracepoint.xml media.xml \ ste_fm_radio.xml ste_conn.xml \ - ske_keypad.xml + ske_keypad.xml ste_ff_vibra.xml # u8500_usb_dma.xml isa_hsi.xml mcde.xml b2r2.xml shrm.xml ### diff --git a/Documentation/DocBook/ste_ff_vibra.tmpl b/Documentation/DocBook/ste_ff_vibra.tmpl new file mode 100644 index 00000000000..cf5f159bed0 --- /dev/null +++ b/Documentation/DocBook/ste_ff_vibra.tmpl @@ -0,0 +1,217 @@ +<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" + "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []> + +<book id="STE-Force-Feedback-Vibrator-API-Guide"> + <bookinfo> + <title>Force Feedback Vibrator Driver</title> + + <authorgroup> + <author> + <firstname>Marcin</firstname> + <surname>Mielczarczyk</surname> + <affiliation> + <address> + <email>marcin.mielczarczyk@tieto.com</email> + </address> + </affiliation> + </author> + </authorgroup> + + <copyright> + <year>2010</year> + <holder>ST-Ericsson</holder> + </copyright> + + <subjectset> + <subject> + <subjectterm>Linux standard functions</subjectterm> + </subject> + </subjectset> + + <legalnotice> + + <para> + This documentation is free software; you can redistribute + it and/or modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later + version. + </para> + + <para> + This program is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + </para> + + <para> + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, + MA 02111-1307 USA + </para> + + <para> + For more details see the file COPYING in the source + distribution of Linux. + </para> + </legalnotice> + </bookinfo> + + <toc></toc> + + <chapter id="intro"> + <title>Introduction</title> + <para> + This documentation describes the implementation of ST-Ericsson's + Force Feedback Vibrator driver for the ST-Ericsson Linux platforms. + </para> + </chapter> + + <chapter id="gettingstarted"> + <title>Getting Started</title> + <para> + There are no special compilation flags needed to build the + Force Feedback Vibrator driver. + </para> + + <section id="basic-tutorial"> + <title>Basic Tutorial</title> + <para> + To enable the Force Feedback Vibrator driver using Kconfig, go to + <constant> Device Drivers -> Input Device Support -> Miscellaneous devices </constant> + and enable the following: + <itemizedlist> + <listitem><para>ST-Ericsson Force Feedback Vibrator</para></listitem> + </itemizedlist> + </para> + </section> + + </chapter> + + <chapter id="concepts"> + <title>Concepts</title> + <para> + Vibrator driver registers as memless force feedback input device. + </para> + </chapter> + + <chapter id="driver-configuration"> + <title>Driver Configuration and Interaction</title> + <para> + There are no configuration parameters for Force Feedback Vibrator driver. + </para> + <section id="driver-implemented-operations"> + <title>Implemented operations in driver</title> + <para> + All available operations are provided by Memless Input Device class driver. + </para> + <para> + <table> + <title> Supported device driver operations </title> + <tgroup cols="2"><tbody> + <row><entry> open </entry> <entry> Calls ste_ff_vibra_open() function which initializaes workqueue </entry> </row> + <row><entry> close </entry> <entry> Calls ste_ff_vibra_close() function which cancels and destroys workqueue </entry> </row> + </tbody></tgroup> + </table> + </para> + </section> + <section id="driver-loading"> + <title>Driver loading parameters</title> + <para> + Not Applicable. + </para> + </section> + <section id="driver-ioctl"> + <title>Driver IO Control</title> + <para> + Not Applicable. + </para> + </section> + + <section id="driver-sysfs"> + <title>Driver Interaction with Sysfs</title> + <para> + Not Applicable. + </para> + </section> + <section id="driver-proc"> + <title>Driver Interaction using /proc filesystem</title> + <para> + Not Applicable. + </para> + </section> + + <section id="driver-other"> + <title>Other means for Driver Interaction</title> + <para> + Not Applicable. + </para> + </section> + + <section id="driver-node"> + <title>Driver Node File</title> + <para> + Force Feedback Vibrator driver provides following node files: + </para> + <variablelist> + <varlistentry> + <term>eventX - Force Feedback Vibrator node file</term> + <listitem> + <variablelist> + <varlistentry> + <term>File</term> + <listitem><para><filename>/dev/input/eventX</filename></para></listitem> + </varlistentry> + <varlistentry> + <term>Description</term> + <listitem> + <para>Node file of Force Feedback Vibrator driver</para> + </listitem> + </varlistentry> + </variablelist> + </listitem> + </varlistentry> + + </variablelist> + </section> + + + </chapter> + + + <chapter id="bugs"> + <title>Known Bugs And Assumptions</title> + <para> + <variablelist> + <varlistentry> + <term>None.</term> + <listitem> + <para> + </para> + </listitem> + </varlistentry> + + </variablelist> + + </para> + </chapter> + +<chapter id="pubfunctions"> + <title>Public Functions Provided</title> + <para> + Not Applicable. + </para> + +</chapter> + +<chapter id="internal-functions"> + <title>Internal Functions Provided</title> + <para> + This chapter contains the autogenerated documentation of the internal functions. + </para> +!Edrivers/input/misc/ste_ff_vibra.c +</chapter> + +</book> diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index a52bc7e6231..5135969510f 100755 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -1263,6 +1263,11 @@ static struct platform_device ab8500_bm_device = { }, }; +/* Force feedback vibrator device */ +static struct platform_device ste_ff_vibra_device = { + .name = "ste_ff_vibra" +}; + static struct platform_device *u8500_platform_devices[] __initdata = { /*TODO - add platform devices here */ #ifdef CONFIG_KEYPAD_U8500 @@ -1300,6 +1305,7 @@ static struct platform_device *platform_board_devs[] __initdata = { &u8500_ab8500_device, &ab8500_gpadc_device, &ab8500_bm_device, + &ste_ff_vibra_device, &ux500_musb_device, &ux500_mcde_device, &ux500_b2r2_device, diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 23140a3bb8e..be83887fbc3 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -340,4 +340,15 @@ config INPUT_PCAP To compile this driver as a module, choose M here: the module will be called pcap_keys. +config INPUT_STE_FF_VIBRA + tristate "ST-Ericsson Force Feedback Vibrator" + depends on STE_AUDIO_IO_DEV + select INPUT_FF_MEMLESS + help + This option enables support for ST-Ericsson's Vibrator which + registers as an input force feedback driver. + + To compile this driver as a module, choose M here. The module will + be called ste_ff_vibra. + endif diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 7e95a5d474d..519e770824e 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -32,4 +32,5 @@ obj-$(CONFIG_INPUT_WINBOND_CIR) += winbond-cir.o obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o obj-$(CONFIG_INPUT_YEALINK) += yealink.o +obj-$(CONFIG_INPUT_STE_FF_VIBRA) += ste_ff_vibra.o diff --git a/drivers/input/misc/ste_ff_vibra.c b/drivers/input/misc/ste_ff_vibra.c new file mode 100644 index 00000000000..606a4f2a15e --- /dev/null +++ b/drivers/input/misc/ste_ff_vibra.c @@ -0,0 +1,223 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Marcin Mielczarczyk <marcin.mielczarczyk@tieto.com> + * for ST-Ericsson + * License Terms: GNU General Public License v2 + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/input.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/workqueue.h> +#include <mach/ste_audio_io_vibrator.h> + +#define FF_VIBRA_DOWN 0x0000 /* 0 degrees */ +#define FF_VIBRA_LEFT 0x4000 /* 90 degrees */ +#define FF_VIBRA_UP 0x8000 /* 180 degrees */ +#define FF_VIBRA_RIGHT 0xC000 /* 270 degrees */ + +/** + * struct vibra_info - Vibrator information structure + * @idev: Pointer to input device structure + * @vibra_workqueue: Pointer to vibrator workqueue structure + * @vibra_work: Vibrator work + * @direction: Vibration direction + * @speed: Vibration speed + * + * Structure vibra_info holds vibrator informations + **/ +struct vibra_info { + struct input_dev *idev; + struct workqueue_struct *vibra_workqueue; + struct work_struct vibra_work; + int direction; + unsigned char speed; +}; + +/** + * vibra_play_work() - Vibrator work, sets speed and direction + * @work: Pointer to work structure + * + * This function is called from workqueue, turns on/off vibrator + **/ +static void vibra_play_work(struct work_struct *work) +{ + struct vibra_info *vinfo = container_of(work, + struct vibra_info, vibra_work); + + /* Divide by 2 because supported range by PWM is 0-100 */ + vinfo->speed /= 2; + + if (vinfo->direction > FF_VIBRA_DOWN && vinfo->direction < FF_VIBRA_UP) + /* 1 - 179 degrees, turn on left vibrator */ + ste_audioio_vibrator_pwm_control(STE_AUDIOIO_CLIENT_FF_VIBRA, + vinfo->speed, 0); + else if (vinfo->direction > FF_VIBRA_UP) + /* more than 180 degrees, turn on right vibrator */ + ste_audioio_vibrator_pwm_control(STE_AUDIOIO_CLIENT_FF_VIBRA, + 0, vinfo->speed); + else + /* 0 (down) or 180 (up) degrees, turn on 2 vibrators */ + ste_audioio_vibrator_pwm_control(STE_AUDIOIO_CLIENT_FF_VIBRA, + vinfo->speed, vinfo->speed); +} + +/** + * vibra_play() - Memless device control function + * @idev: Pointer to input device structure + * @data: Pointer to private data (not used) + * @effect: Pointer to force feedback effect structure + * + * This function controls memless device + * + * Returns: + * 0 - success + **/ +static int vibra_play(struct input_dev *idev, void *data, + struct ff_effect *effect) +{ + struct vibra_info *vinfo = input_get_drvdata(idev); + + vinfo->direction = effect->direction; + vinfo->speed = effect->u.rumble.strong_magnitude >> 8; + if (!vinfo->speed) + /* Shift weak magnitude to make it feelable on vibrator */ + vinfo->speed = effect->u.rumble.weak_magnitude >> 9; + + queue_work(vinfo->vibra_workqueue, &vinfo->vibra_work); + + return 0; +} + +/** + * ste_ff_vibra_open() - Input device open function + * @idev: Pointer to input device structure + * + * This function is called on opening input device + * + * Returns: + * -ENOMEM - no memory left + * 0 - success + **/ +static int ste_ff_vibra_open(struct input_dev *idev) +{ + struct vibra_info *vinfo = input_get_drvdata(idev); + + vinfo->vibra_workqueue = + create_singlethread_workqueue("ste_ff-ff-vibra"); + if (!vinfo->vibra_workqueue) { + dev_err(&idev->dev, "couldn't create vibra workqueue\n"); + return -ENOMEM; + } + return 0; +} + +/** + * ste_ff_vibra_close() - Input device close function + * @idev: Pointer to input device structure + * + * This function is called on closing input device + **/ +static void ste_ff_vibra_close(struct input_dev *idev) +{ + struct vibra_info *vinfo = input_get_drvdata(idev); + + cancel_work_sync(&vinfo->vibra_work); + INIT_WORK(&vinfo->vibra_work, vibra_play_work); + destroy_workqueue(vinfo->vibra_workqueue); + vinfo->vibra_workqueue = NULL; +} + +static int __devinit ste_ff_vibra_probe(struct platform_device *pdev) +{ + struct vibra_info *vinfo; + int ret; + + vinfo = kmalloc(sizeof *vinfo, GFP_KERNEL); + if (!vinfo) { + dev_err(&pdev->dev, "failed to allocate memory\n"); + return -ENOMEM; + } + + vinfo->idev = input_allocate_device(); + if (!vinfo->idev) { + dev_err(&pdev->dev, "failed to allocate input device\n"); + ret = -ENOMEM; + goto exit_vinfo_free; + } + + vinfo->idev->name = "ste-ff-vibra"; + vinfo->idev->dev.parent = pdev->dev.parent; + vinfo->idev->open = ste_ff_vibra_open; + vinfo->idev->close = ste_ff_vibra_close; + INIT_WORK(&vinfo->vibra_work, vibra_play_work); + __set_bit(FF_RUMBLE, vinfo->idev->ffbit); + + ret = input_ff_create_memless(vinfo->idev, NULL, vibra_play); + if (ret) { + dev_err(&pdev->dev, "failed to create memless device\n"); + goto exit_idev_free; + } + + ret = input_register_device(vinfo->idev); + if (ret) { + dev_err(&pdev->dev, "failed to register input device\n"); + goto exit_destroy_memless; + } + + input_set_drvdata(vinfo->idev, vinfo); + platform_set_drvdata(pdev, vinfo); + return 0; + +exit_destroy_memless: + input_ff_destroy(vinfo->idev); +exit_idev_free: + input_free_device(vinfo->idev); +exit_vinfo_free: + kfree(vinfo); + return ret; +} + +static int __devexit ste_ff_vibra_remove(struct platform_device *pdev) +{ + struct vibra_info *vinfo = platform_get_drvdata(pdev); + + /* + * Function device_release() will call input_dev_release() + * which will free ff and input device. No need to call + * input_ff_destroy() and input_free_device() explicitly. + */ + input_unregister_device(vinfo->idev); + kfree(vinfo); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver ste_ff_vibra_driver = { + .driver = { + .name = "ste_ff_vibra", + .owner = THIS_MODULE, + }, + .probe = ste_ff_vibra_probe, + .remove = __devexit_p(ste_ff_vibra_remove) +}; + +static int __init ste_ff_vibra_init(void) +{ + return platform_driver_register(&ste_ff_vibra_driver); +} +module_init(ste_ff_vibra_init); + +static void __exit ste_ff_vibra_exit(void) +{ + platform_driver_unregister(&ste_ff_vibra_driver); +} +module_exit(ste_ff_vibra_exit); + +MODULE_AUTHOR("Marcin Mielczarczyk <marcin.mielczarczyk@tieto.com>"); +MODULE_DESCRIPTION("STE Force Feedback Vibrator Driver"); +MODULE_LICENSE("GPL v2"); |