summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/DocBook/Makefile2
-rw-r--r--Documentation/DocBook/ste_ff_vibra.tmpl217
-rw-r--r--arch/arm/mach-ux500/board-mop500.c8
-rw-r--r--arch/arm/mach-ux500/devices-db8500.c2
-rw-r--r--drivers/input/misc/Kconfig10
-rw-r--r--drivers/input/misc/Makefile2
-rw-r--r--drivers/input/misc/ste_ff_vibra.c234
7 files changed, 472 insertions, 3 deletions
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index 70e985a59db..893255ea0e2 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -19,7 +19,7 @@ DOCBOOKS := z8530book.xml mcabook.xml device-drivers.xml \
tc_keypad.xml prcmu-fw-api.xml cg2900_fm_radio.xml \
synaptics_rmi4_touchp.xml db5500_keypad.xml \
u5500_LogicalMailbox.xml \
- lsm303dlh.xml ste_timed_vibra.xml ux500_usb.xml
+ lsm303dlh.xml ste_timed_vibra.xml ste_ff_vibra.xml ux500_usb.xml
###
# The build process is as follows (targets):
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 -&gt; Input Device Support -&gt; 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 ec8fed561be..3cce4118027 100644
--- a/arch/arm/mach-ux500/board-mop500.c
+++ b/arch/arm/mach-ux500/board-mop500.c
@@ -772,6 +772,11 @@ static struct platform_device ux500_backlight_device[] = {
};
#endif
+/* Force feedback vibrator device */
+static struct platform_device ste_ff_vibra_device = {
+ .name = "ste_ff_vibra"
+};
+
#ifdef CONFIG_HSI
static struct hsi_board_info __initdata u8500_hsi_devices[] = {
{
@@ -874,6 +879,7 @@ static struct platform_device *mop500_platform_devs[] __initdata = {
&u8500_sim_detect_device,
#endif
&u8500_shrm_device,
+ &ste_ff_vibra_device,
#ifdef CONFIG_U8500_MMIO
&ux500_mmio_device,
#endif
@@ -1071,6 +1077,8 @@ static void ux500_uart0_exit(void)
pr_err("pl011: uart pins_disable failed\n");
}
+
+
static struct amba_pl011_data uart0_plat = {
#ifdef CONFIG_STE_DMA40_REMOVE
.dma_filter = stedma40_filter,
diff --git a/arch/arm/mach-ux500/devices-db8500.c b/arch/arm/mach-ux500/devices-db8500.c
index f2e865d7872..08bff83cac7 100644
--- a/arch/arm/mach-ux500/devices-db8500.c
+++ b/arch/arm/mach-ux500/devices-db8500.c
@@ -30,7 +30,7 @@
#include <mach/hsi.h>
#include <mach/ste-dma40-db8500.h>
#include <trace/stm.h>
-#include <pm/pm.h>
+#include "pm/pm.h"
#include "pins-db8500.h"
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index efd55625a46..dd4bd663d7c 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -508,4 +508,14 @@ config INPUT_XEN_KBDDEV_FRONTEND
To compile this driver as a module, choose M here: the
module will be called xen-kbdfront.
+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 7b16f212884..611fef71587 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -49,4 +49,4 @@ obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o
obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o
obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND) += xen-kbdfront.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..9038e6be046
--- /dev/null
+++ b/drivers/input/misc/ste_ff_vibra.c
@@ -0,0 +1,234 @@
+/*
+ * 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);
+ struct ste_vibra_speed left_speed = {
+ .positive = 0,
+ .negative = 0,
+ };
+ struct ste_vibra_speed right_speed = {
+ .positive = 0,
+ .negative = 0,
+ };
+
+ /* 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 */
+ left_speed.positive = vinfo->speed;
+ } else if (vinfo->direction > FF_VIBRA_UP) {
+ /* more than 180 degrees, turn on right vibrator */
+ right_speed.positive = vinfo->speed;
+ } else {
+ /* 0 (down) or 180 (up) degrees, turn on 2 vibrators */
+ left_speed.positive = vinfo->speed;
+ right_speed.positive = vinfo->speed;
+ }
+
+ ste_audioio_vibrator_pwm_control(STE_AUDIOIO_CLIENT_FF_VIBRA,
+ left_speed, right_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");