linux-iio.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/4] IIO: Invensense MPU6050/MPU9150 driver submit
@ 2012-06-28 18:30 Ge Gao
  2012-07-06  9:07 ` Jonathan Cameron
  0 siblings, 1 reply; 4+ messages in thread
From: Ge Gao @ 2012-06-28 18:30 UTC (permalink / raw)
  To: linux-iio; +Cc: linux-iio-owner, Jonathan Cameron


[-- Attachment #1.1: Type: text/plain, Size: 119 bytes --]

Hi All,

                Attached is the Invensense MPU6050/9150 IIO driver submit.
Thanks.



Best Regards,



Ge GAO

[-- Attachment #1.2: Type: text/html, Size: 1565 bytes --]

[-- Attachment #2: 0001-Invensense-MPU6050-MPU9150-driver.patch --]
[-- Type: application/octet-stream, Size: 96997 bytes --]

From 6d4093a59d77a68d4972f648ea9eba69e8598159 Mon Sep 17 00:00:00 2001
From: Ge Gao <ggao@invensense.com>
Date: Thu, 28 Jun 2012 10:58:12 -0700
Subject: [PATCH 1/4]     Invensense MPU6050/MPU9150 driver.

      --MPU6050/MPU9150 driver.
      --Secondary bus for AKM8975/AKM8963/AKM8972 support.
      --kernel fix for Kfifo poll support from Jonanthan.
      --Kfifo bug fix. Need to check available space before store.
      --add new IIO type for quaternion.

Change-Id: I4023d322193fa89df8ceb84e6b95611be4264e49
Signed-off-by: Ge Gao <ggao@invensense.com>
---
 drivers/staging/iio/imu/Kconfig                    |    1 +
 drivers/staging/iio/imu/Makefile                   |    3 +
 drivers/staging/iio/imu/mpu6050/Kconfig            |   13 +
 drivers/staging/iio/imu/mpu6050/Makefile           |   11 +
 drivers/staging/iio/imu/mpu6050/README             |  296 ++++++++
 .../staging/iio/imu/mpu6050/dmpDefaultMPU6050.c    |  290 ++++++++
 drivers/staging/iio/imu/mpu6050/dmpKey.h           |  494 +++++++++++++
 drivers/staging/iio/imu/mpu6050/dmpmap.h           |  266 +++++++
 drivers/staging/iio/imu/mpu6050/inv_mpu_iio.h      |  727 ++++++++++++++++++++
 drivers/staging/iio/imu/mpu6050/inv_mpu_ring.c     |  563 +++++++++++++++
 drivers/staging/iio/imu/mpu6050/mpu.h              |  107 +++
 11 files changed, 2771 insertions(+), 0 deletions(-)
 create mode 100644 drivers/staging/iio/imu/mpu6050/Kconfig
 create mode 100644 drivers/staging/iio/imu/mpu6050/Makefile
 create mode 100644 drivers/staging/iio/imu/mpu6050/README
 create mode 100644 drivers/staging/iio/imu/mpu6050/dmpDefaultMPU6050.c
 create mode 100644 drivers/staging/iio/imu/mpu6050/dmpKey.h
 create mode 100644 drivers/staging/iio/imu/mpu6050/dmpmap.h
 create mode 100644 drivers/staging/iio/imu/mpu6050/inv_mpu_iio.h
 create mode 100644 drivers/staging/iio/imu/mpu6050/inv_mpu_ring.c
 create mode 100644 drivers/staging/iio/imu/mpu6050/mpu.h

diff --git a/drivers/staging/iio/imu/Kconfig b/drivers/staging/iio/imu/Kconfig
index 2c2f47d..e27c26e 100644
--- a/drivers/staging/iio/imu/Kconfig
+++ b/drivers/staging/iio/imu/Kconfig
@@ -14,4 +14,5 @@ config ADIS16400
 	  adis16365, adis16400 and adis16405 triaxial inertial sensors
 	  (adis16400 series also have magnetometers).
 
+source "drivers/staging/iio/imu/mpu6050/Kconfig"
 endmenu
diff --git a/drivers/staging/iio/imu/Makefile b/drivers/staging/iio/imu/Makefile
index 3400a13..920eb13 100644
--- a/drivers/staging/iio/imu/Makefile
+++ b/drivers/staging/iio/imu/Makefile
@@ -5,3 +5,6 @@
 adis16400-y             := adis16400_core.o
 adis16400-$(CONFIG_IIO_BUFFER) += adis16400_ring.o adis16400_trigger.o
 obj-$(CONFIG_ADIS16400) += adis16400.o
+
+obj-y += mpu6050/
+
diff --git a/drivers/staging/iio/imu/mpu6050/Kconfig b/drivers/staging/iio/imu/mpu6050/Kconfig
new file mode 100644
index 0000000..c4fa2c2
--- /dev/null
+++ b/drivers/staging/iio/imu/mpu6050/Kconfig
@@ -0,0 +1,13 @@
+#
+# inv-mpu-6050 drivers for Invensense MPU devices and combos
+#
+
+config INV_MPU6050_IIO
+	tristate "Invensense MPU6050 devices"
+	depends on I2C && SYSFS && IIO && IIO_KFIFO_BUF && !INV_MPU && !INV_MPU_IIO
+	default n
+	help
+	  This driver supports the Invensense MPU6050/MPU9150 devices. It also
+	  supports AKM8975/AKM8963/AKM8972 in the secondary bus.
+	  This driver can be built as a module. The module will be called
+	  inv-mpu6050-iio.
diff --git a/drivers/staging/iio/imu/mpu6050/Makefile b/drivers/staging/iio/imu/mpu6050/Makefile
new file mode 100644
index 0000000..1a5e746
--- /dev/null
+++ b/drivers/staging/iio/imu/mpu6050/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for Invensense inv-mpu6050-iio device.
+#
+
+obj-$(CONFIG_INV_MPU6050_IIO) += inv-mpu6050-iio.o
+
+inv-mpu6050-iio-objs := inv_mpu_core.o
+inv-mpu6050-iio-objs += inv_mpu_ring.o
+inv-mpu6050-iio-objs += inv_mpu_misc.o
+inv-mpu6050-iio-objs += dmpDefaultMPU6050.o
+
diff --git a/drivers/staging/iio/imu/mpu6050/README b/drivers/staging/iio/imu/mpu6050/README
new file mode 100644
index 0000000..806a956
--- /dev/null
+++ b/drivers/staging/iio/imu/mpu6050/README
@@ -0,0 +1,296 @@
+Kernel driver inv-mpu-iio
+Author: Invensense <http://invensense.com>
+
+Description
+-----------
+This document describes how to install the Invensense device driver into a
+Linux kernel. At the moment, this driver supports the
+MPU6050/MPU9150. The slave address of these four chips are
+0x68 or 0x69. However, the actual slave address depends on the board
+configuration. The driver does not assume anything about it.
+
+Files included in this package:
+Kconfig
+Makefile
+inv_mpu_core.c
+inv_mpu_misc.c
+inv_mpu_iio.h
+inv_mpu_ring.c
+dmpDefaultMPU6050.c
+dmpkey.h
+dmpmap.h
+mpu.h
+Including the driver in the Linux kernel
+----------------------------------------
+mpu.h should be added to "kernel/include/linux".
+Other files listed should be added to the drivers/staging/iio/imu/mpu
+directory (or another directory of your choosing). When building the
+kernel, the driver will not appear in menuconfig without modifications
+similar to those below:
+
+modify "drivers/staging/iio/imu/Kconfig" like
+source "drivers/staging/iio/imu/mpu/Kconfig"
+
+modify "drivers/staging/iio/imu/Makefile"
+obj-y += mpu/
+
+Board and Platform Data
+-----------------------
+The board file needs to be modified to register the device on an I2C bus. An
+i2c_board_info instance must be defined as seen below. The hardcoded value of
+140 corresponds to the GPIO input pin wired to the device's interrupt pin.
+This pin will most likely be different for your platform.
+platform data is for orientation matrix,  and secondary bus situations.
+For MPU9150, it is regarded as a MPU9150 and AKM8975 in the secondary.
+So the secondary i2c address must be filled.
+-----------------------------------------------------------------
+The board file is arch/arm/mach-omap2/board-omap4panda.c for panda board or
+modify the board file in your system as below:
+--------------------------------------------------------
+For AKM8963 in the secondary i2c bus of MPU6050,
+static struct mpu_platform_data gyro_platform_data = {
+	.int_config  = 0x10,
+	.level_shifter = 0,
+	.orientation = {  -1,  0,  0,
+			   0,  1,  0,
+			   0,  0, -1 },
+	.sec_slave_type = SECONDARY_SLAVE_TYPE_COMPASS,
+	.sec_slave_id   = COMPASS_ID_AK8963,
+	.secondary_i2c_addr = 0x0E
+};
+-----------------------------------------------------------
+For MPU9150, the secondary i2c bus address must be filled as below.
+static struct mpu_platform_data gyro_platform_data = {
+	.int_config  = 0x10,
+	.level_shifter = 0,
+	.orientation = {  -1,  0,  0,
+			   0,  1,  0,
+			   0,  0, -1 },
+	.sec_slave_type = SECONDARY_SLAVE_TYPE_COMPASS,
+	.sec_slave_id   = COMPASS_ID_AK8975,
+	.secondary_i2c_addr = 0x0E
+};
+-----------------------------------------------------------
+for MPU6050
+static struct i2c_board_info __initdata single_chip_board_info[] = {
+	{
+		I2C_BOARD_INFO("mpu6050", 0x68),
+		.irq = (IH_GPIO_BASE + MPUIRQ_GPIO),
+		.platform_data = &gyro_platform_data,
+	},
+};
+for MPU9150
+arch/arm/mach-omap2/board-omap4panda.c
+static struct i2c_board_info __initdata single_chip_board_info[] = {
+	{
+		I2C_BOARD_INFO("mpu9150", 0x68),
+		.irq = (IH_GPIO_BASE + MPUIRQ_GPIO),
+		.platform_data = &gyro_platform_data,
+	},
+};
+
+In the _i2c_init function, the device is registered in the following manner:
+
+arch/arm/mach-omap2/board-omap4panda.c
+    in static int __init omap4_panda_i2c_init(void)
+omap_register_i2c_bus(4, 400, single_chip_board_info, ARRAY_SIZE(single_chip_board_info));
+
+IIO subsystem
+----------------------------------------------
+successful installation will create two directories under /sys/bus/iio/devices
+iio:device0
+trigger0
+Under /dev/ diretory, a file "iio:device0" will also be created(or iio:deviceX, if
+you have more than one iio devices).
+Communicating with the driver in userspace
+------------------------------------------
+Upon installation, the driver generates several files in sysfs. If your
+platform is configured as detailed above, navigate to the following path to
+find these files:
+/sys/bus/iio/devices/iio:device0
+
+The list below provides a brief description for each file.
+--------------------------------------
+For MPU6050:
+temperature (Read-only)
+Read temperature data directly from the temperature register.
+
+sampling_frequency (Read/write)
+Configure the ADC sampling rate and FIFO output rate.
+
+sampling_frequency_available(read-only)
+show commonly used frequency
+
+clock_source (Read-only)
+Check which clock-source is used by the chip.
+
+power_state (Read/write)
+turn on/off the power supply
+
+self_test (read-only)
+read this entry trigger self test. The return value is D.
+D is the success/fail.
+For different chip, the result is different for success/fail.
+1 means success 0 means fail. The LSB of D is for gyro; the bit
+next to LSB of D is for accel. The bit 2 of D is for compass result.
+
+key (read-only)
+show the key value of this driver. Used by MPL.
+
+gyro_matrix (read-only)
+show the orient matrix obtained from board file.
+
+gyro_enable (read/write)
+enable/disable gyro functionality. affect raw_gyro. turn off this will
+shut down gyro and save power.
+
+accl_enable (read/write)
+enable/disable accelerometer functionality. affect raw_accl.
+turn off this will shut down accel and save power.
+
+firmware_loaded (read/write)
+Flag indicate the whether firmware is loaded or not in the DMP engine.
+0 means no firmware loaded. 1 means firmware is already loaded . This
+flag can only be written as 0. 1 is updated internally.
+
+dmp_on(read/write)
+This entry controls whether to run DMP or not. To enable DMP ,
+firmware_loaded must be 1. write 1 to enable DMP and write 0 to disable dmp.
+
+dmp_in_on(read/write)
+This entry controls whether dmp interrupt is on/off. firmware_loaded must
+be 1. sometimes, it is desirable that interrupt is off while DMP is running.
+
+dmp_event_int_on(read/write)
+This entry controls whether dmp event interrupt is on/off. Setting this on
+would turn off the data interrupt and turn on the event interrupt. No data
+interrupt would be generated. Only when event happens, does an interrupt
+generate. This can be used in power saving mode when system is waiting for
+a special event to wake up.
+
+dmp_firmware (write only binary file)
+This is the entry that firmware code is loaded into. If the action is succeful,
+firmware_loaded will be updated as 1. In order to load new firmware,
+firmware_loaded flag should be set 0.
+
+lpa_mode(read-write)
+Low power  accelerometer mode
+lpa_freq(read-write)
+low power acceleromter frequency.
+
+accel_matrix
+orient matrix for accel
+
+flick_lower,
+flick_upper,
+flick_counter,
+flick_message_on,
+flick_int_on,
+flick_axis,
+Flick related entry
+
+pedometer_time
+pedometer_steps,
+Pedometer related entry
+
+event_flick
+event_tap
+event_orientation
+event_display_orientation
+event related entry. These entry must use poll to read.
+
+tap_on
+control tap function of DMP
+
+dmp_int_on
+turn on/off dmp interrupt.
+
+dmp_output_rate
+control dmp output rate when dmp is on.
+
+tap_time
+tap_min_count
+tap_threshold
+tap related entries. control various parameters of tap function.
+
+orientation_on
+turn on/off orientation function of DMP.
+
+display_orientation_on
+turn on/off display orientation function of DMP.
+
+quaternion_on
+turn on/off quaterniion data output. must use DMP.
+-------------------------------------------------------------------
+for MPU9150 and secondary compass
+MPU9150 has every entry MPU6050 has. It has additional entries:
+
+compass_enable (read/write)
+enable this will enable compass function.
+
+compass_matrix (read-only)
+compass orient matrix
+----------------------------------------------------------------------------------
+low power accelerometer mode
+Lower power accelerometer mode is a special mode. It works only for accelerometer.
+It has two entries, lpa_mode and lpa_freq. Only MPU6050 and MPU9150 has this mode.
+To run low power accel mode, set lpa_mode to 1, set lpa_freq to 0~3, which corresponds
+to 1.25Hz, 5Hz, 20Hz, 40Hz. "gyro_enable" and "compass_enable" must be zero. "dmp_on"
+must be zero.
+-----------------------------------------------------------------------------------
+dmp event.
+dmp event is event out by the DMP unit inside MPU. Only MPU6050 and MPU9150 supports this.
+There are four sysfs entreis, event_flick, event_tap and event_orientation and
+event_display_orientation. These four events must
+be polled before read. The proper method to poll sysfs is:
+1. open file.
+2. dummy read.
+3. poll.
+4. once the poll passed, use fopen and fread to read the sysfs entry.
+5. interpret the data.
+------------------------------------------------------------------------------
+If streaming to a userspace application, the recommended way to access gyro/accel/compass
+data is via /dev/iio:device0. Follow these steps to get constant readings from
+the driver:
+
+1. Write a 1 to power_state to turn on the chip. This is the default setting
+   after installing the driver.
+2. Write the desired output rate to fifo_rate.
+3. write 1 to enable to turn on the event.
+4. Read /dev/iio:device0 to get a string of gyro/accel/compass data.
+5. Parse this string to obtain each gyro/accel/compass element.
+6. If dmp firmware code is loaded, using "dmp_on" to enable/disable dmp .
+7. If compass is enabled, output will have compass data.
+===========================================================================
+                    Recommended sysfs entry setup senquence
+1. without DMP firmware
+1.1 set "power_state" to 1,
+1.2 change scale and fifo rate value to your need.
+1.3 change gyro_enable and accle_enable and compass_enable to your needs. For example,
+if you want gyro only, set accl_enable to 0 or set accl_enable to zero and compass_enable to zero.
+If you want accel only, set gyro_enable to 0 or set gyro_enable to zero and compass_enable to zero.
+If you want compass only, disable gyro and accel.
+1.4 set "enable" to 1. you will get output you want.
+
+2. With DMP firmware
+2.1 set "power_state" to 1,
+2.2 write "0" to firmware_loaded if it is not zero already.
+2.3 load firmware into "dmp_firmware" as a whole. Don't split the DMP firmware image.
+2.4 make sure firmware_loaded is 1 after loading.
+2.5 make other configurations similar to the situation as without DMP firmware.
+2.6 set dmp_on to 1.
+2.7 set "enable" to 1.
+=======================================================
+The enable function is using enable entry under "/sys/bus/iio/devices/iio:device0/buffer"
+==========================================================
+test applications:
+Test application is mpu_iio
+------------------------------------------
+To run with MPU9150/MPU6050:
+using the following command:
+for orientation/tap/flick/display orientation event:
+mpu_iio  -c 10 -l 3 -p
+for normal data print
+mpu_iio  -c 10 -l 3 -r
+----------------------------------------
+Please use mpu_iio.c and iio_utils.h as the sample code for your development.
diff --git a/drivers/staging/iio/imu/mpu6050/dmpDefaultMPU6050.c b/drivers/staging/iio/imu/mpu6050/dmpDefaultMPU6050.c
new file mode 100644
index 0000000..5803643
--- /dev/null
+++ b/drivers/staging/iio/imu/mpu6050/dmpDefaultMPU6050.c
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) 2012 Invensense, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include "dmpKey.h"
+#include "dmpmap.h"
+
+#define CFG_27                  (2745)
+#define CFG_20                  (2078)
+#define CFG_23                  (2748)
+#define CFG_FIFO_ON_EVENT       (2694)
+#define CFG_ORIENT_IRQ_1        (2533)
+#define CGNOTICE_INTR           (2636)
+#define X_GRT_Y_TMP             (1318)
+#define CFG_DR_INT              (1029)
+#define CFG_AUTH                (1035)
+#define FCFG_1                  (1062)
+#define SKIP_X_GRT_Y_TMP        (1319)
+#define SKIP_END_COMPARE        (1395)
+#define FCFG_3                  (1110)
+#define FCFG_2                  (1066)
+#define END_COMPARE_Y_X_TMP2    (1415)
+#define CFG_DISPLAY_ORIENT_INT  (1706)
+#define FCFG_7                  (1076)
+#define FCFG_6                  (1128)
+#define NO_ORIENT_INTERRUPT     (1725)
+#define CFG_8                   (2723)
+#define CFG_15                  (2731)
+#define CFG_16                  (2749)
+#define END_COMPARE_Y_X_TMP     (1367)
+#define CFG_6                   (2756)
+#define END_ORIENT_1            (1709)
+#define END_COMPARE_Y_X         (1444)
+#define CFG_LP_QUAT             (2717)
+#define END_ORIENT              (1738)
+#define CFG_FLICK_IN            (2589)
+#define CFG_7                   (1221)
+#define CFG_MOTION_BIAS         (1224)
+#define X_GRT_Y                 (1368)
+#define TEMPLABEL               (2178)
+#define NOT_TIME_MINUS_1        (1528)
+#define END_COMPARE_Y_X_TMP3    (1394)
+#define X_GRT_Y_TMP2            (1339)
+
+#define D_0_22                  (22+512)
+#define D_0_24                  (24+512)
+
+#define D_0_36                  (36)
+#define D_0_52                  (52)
+#define D_0_96                  (96)
+#define D_0_104                 (104)
+#define D_0_108                 (108)
+#define D_0_163                 (163)
+#define D_0_188                 (188)
+#define D_0_192                 (192)
+#define D_0_224                 (224)
+#define D_0_228                 (228)
+#define D_0_232                 (232)
+#define D_0_236                 (236)
+
+#define D_1_2                   (256 + 2)
+#define D_1_4                   (256 + 4)
+#define D_1_8                   (256 + 8)
+#define D_1_10                  (256 + 10)
+#define D_1_24                  (256 + 24)
+#define D_1_28                  (256 + 28)
+#define D_1_36                  (256 + 36)
+#define D_1_40                  (256 + 40)
+#define D_1_44                  (256 + 44)
+#define D_1_72                  (256 + 72)
+#define D_1_74                  (256 + 74)
+#define D_1_79                  (256 + 79)
+#define D_1_88                  (256 + 88)
+#define D_1_90                  (256 + 90)
+#define D_1_92                  (256 + 92)
+#define D_1_96                  (256 + 96)
+#define D_1_98                  (256 + 98)
+#define D_1_106                 (256 + 106)
+#define D_1_108                 (256 + 108)
+#define D_1_112                 (256 + 112)
+#define D_1_128                 (256 + 144)
+#define D_1_152                 (256 + 12)
+#define D_1_160                 (256 + 160)
+#define D_1_176                 (256 + 176)
+#define D_1_178                 (256 + 178)
+#define D_1_218                 (256 + 218)
+#define D_1_232                 (256 + 232)
+#define D_1_236                 (256 + 236)
+#define D_1_240                 (256 + 240)
+#define D_1_244                 (256 + 244)
+#define D_1_250                 (256 + 250)
+#define D_1_252                 (256 + 252)
+#define D_2_12                  (512 + 12)
+#define D_2_96                  (512 + 96)
+#define D_2_108                 (512 + 108)
+#define D_2_208                 (512 + 208)
+#define D_2_224                 (512 + 224)
+#define D_2_236                 (512 + 236)
+#define D_2_244                 (512 + 244)
+#define D_2_248                 (512 + 248)
+#define D_2_252                 (512 + 252)
+
+#define CPASS_BIAS_X            (35 * 16 + 4)
+#define CPASS_BIAS_Y            (35 * 16 + 8)
+#define CPASS_BIAS_Z            (35 * 16 + 12)
+#define CPASS_MTX_00            (36 * 16)
+#define CPASS_MTX_01            (36 * 16 + 4)
+#define CPASS_MTX_02            (36 * 16 + 8)
+#define CPASS_MTX_10            (36 * 16 + 12)
+#define CPASS_MTX_11            (37 * 16)
+#define CPASS_MTX_12            (37 * 16 + 4)
+#define CPASS_MTX_20            (37 * 16 + 8)
+#define CPASS_MTX_21            (37 * 16 + 12)
+#define CPASS_MTX_22            (43 * 16 + 12)
+#define D_ACT0                  (40 * 16)
+#define D_ACSX                  (40 * 16 + 4)
+#define D_ACSY                  (40 * 16 + 8)
+#define D_ACSZ                  (40 * 16 + 12)
+
+#define FLICK_MSG               (45 * 16 + 4)
+#define FLICK_COUNTER           (45 * 16 + 8)
+#define FLICK_LOWER             (45 * 16 + 12)
+#define FLICK_UPPER             (46 * 16 + 12)
+
+#define D_AUTH_OUT               (992)
+#define D_AUTH_IN                (996)
+#define D_AUTH_A                 (1000)
+#define D_AUTH_B                 (1004)
+
+#define D_PEDSTD_BP_B          (768 + 0x1C)
+#define D_PEDSTD_HP_A          (768 + 0x78)
+#define D_PEDSTD_HP_B          (768 + 0x7C)
+#define D_PEDSTD_BP_A4         (768 + 0x40)
+#define D_PEDSTD_BP_A3         (768 + 0x44)
+#define D_PEDSTD_BP_A2         (768 + 0x48)
+#define D_PEDSTD_BP_A1         (768 + 0x4C)
+#define D_PEDSTD_INT_THRSH     (768 + 0x68)
+#define D_PEDSTD_CLIP          (768 + 0x6C)
+#define D_PEDSTD_SB            (768 + 0x28)
+#define D_PEDSTD_SB_TIME       (768 + 0x2C)
+#define D_PEDSTD_PEAKTHRSH     (768 + 0x98)
+#define D_PEDSTD_TIML          (768 + 0x2A)
+#define D_PEDSTD_TIMH          (768 + 0x2E)
+#define D_PEDSTD_PEAK          (768 + 0X94)
+#define D_PEDSTD_STEPCTR       (768 + 0x60)
+#define D_PEDSTD_TIMECTR       (964)
+#define D_PEDSTD_DECI          (768 + 0xA0)
+
+#define D_HOST_NO_MOT          (976)
+
+static const struct tKeyLabel dmpTConfig[] = {
+	{KEY_CFG_27,                    CFG_27},
+	{KEY_CFG_20,                    CFG_20},
+	{KEY_CFG_23,                    CFG_23},
+	{KEY_CFG_FIFO_ON_EVENT,         CFG_FIFO_ON_EVENT},
+	{KEY_CFG_ORIENT_IRQ_1,          CFG_ORIENT_IRQ_1},
+	{KEY_CGNOTICE_INTR,             CGNOTICE_INTR},
+	{KEY_X_GRT_Y_TMP,               X_GRT_Y_TMP},
+	{KEY_CFG_DR_INT,                CFG_DR_INT},
+	{KEY_CFG_AUTH,                  CFG_AUTH},
+	{KEY_FCFG_1,                    FCFG_1},
+	{KEY_SKIP_X_GRT_Y_TMP,          SKIP_X_GRT_Y_TMP},
+	{KEY_SKIP_END_COMPARE,          SKIP_END_COMPARE},
+	{KEY_FCFG_3,                    FCFG_3},
+	{KEY_FCFG_2,                    FCFG_2},
+	{KEY_END_COMPARE_Y_X_TMP2,      END_COMPARE_Y_X_TMP2},
+	{KEY_CFG_DISPLAY_ORIENT_INT,    CFG_DISPLAY_ORIENT_INT},
+	{KEY_FCFG_7,                    FCFG_7},
+	{KEY_FCFG_6,                    FCFG_6},
+	{KEY_NO_ORIENT_INTERRUPT,       NO_ORIENT_INTERRUPT},
+	{KEY_CFG_8,                     CFG_8},
+	{KEY_CFG_15,                    CFG_15},
+	{KEY_CFG_16,                    CFG_16},
+	{KEY_END_COMPARE_Y_X_TMP,       END_COMPARE_Y_X_TMP},
+	{KEY_CFG_6,                     CFG_6},
+	{KEY_END_ORIENT_1,              END_ORIENT_1},
+	{KEY_END_COMPARE_Y_X,           END_COMPARE_Y_X},
+	{KEY_CFG_LP_QUAT,               CFG_LP_QUAT},
+	{KEY_END_ORIENT,                END_ORIENT},
+	{KEY_CFG_FLICK_IN,              CFG_FLICK_IN},
+	{KEY_CFG_7,                     CFG_7},
+	{KEY_CFG_MOTION_BIAS,           CFG_MOTION_BIAS},
+	{KEY_X_GRT_Y,                   X_GRT_Y},
+	{KEY_TEMPLABEL,                 TEMPLABEL},
+	{KEY_NOT_TIME_MINUS_1,          NOT_TIME_MINUS_1},
+	{KEY_END_COMPARE_Y_X_TMP3,      END_COMPARE_Y_X_TMP3},
+	{KEY_X_GRT_Y_TMP2,              X_GRT_Y_TMP2},
+	{KEY_D_0_22,                D_0_22},
+	{KEY_D_0_96,                D_0_96},
+	{KEY_D_0_104,               D_0_104},
+	{KEY_D_0_108,               D_0_108},
+	{KEY_D_1_36,               D_1_36},
+	{KEY_D_1_40,               D_1_40},
+	{KEY_D_1_44,               D_1_44},
+	{KEY_D_1_72,               D_1_72},
+	{KEY_D_1_74,               D_1_74},
+	{KEY_D_1_79,               D_1_79},
+	{KEY_D_1_88,               D_1_88},
+	{KEY_D_1_90,               D_1_90},
+	{KEY_D_1_92,               D_1_92},
+	{KEY_D_1_160,               D_1_160},
+	{KEY_D_1_176,               D_1_176},
+	{KEY_D_1_218,               D_1_218},
+	{KEY_D_1_232,               D_1_232},
+	{KEY_D_1_250,               D_1_250},
+	{KEY_DMP_TAPW_MIN,          DMP_TAPW_MIN},
+	{KEY_DMP_TAP_THR_X,         DMP_TAP_THX},
+	{KEY_DMP_TAP_THR_Y,         DMP_TAP_THY},
+	{KEY_DMP_TAP_THR_Z,         DMP_TAP_THZ},
+	{KEY_DMP_SH_TH_Y,           DMP_SH_TH_Y},
+	{KEY_DMP_SH_TH_X,           DMP_SH_TH_X},
+	{KEY_DMP_SH_TH_Z,           DMP_SH_TH_Z},
+	{KEY_DMP_ORIENT,            DMP_ORIENT},
+	{KEY_D_AUTH_OUT,            D_AUTH_OUT},
+	{KEY_D_AUTH_IN,             D_AUTH_IN},
+	{KEY_D_AUTH_A,              D_AUTH_A},
+	{KEY_D_AUTH_B,              D_AUTH_B},
+	{KEY_CPASS_BIAS_X,          CPASS_BIAS_X},
+	{KEY_CPASS_BIAS_Y,          CPASS_BIAS_Y},
+	{KEY_CPASS_BIAS_Z,          CPASS_BIAS_Z},
+	{KEY_CPASS_MTX_00,          CPASS_MTX_00},
+	{KEY_CPASS_MTX_01,          CPASS_MTX_01},
+	{KEY_CPASS_MTX_02,          CPASS_MTX_02},
+	{KEY_CPASS_MTX_10,          CPASS_MTX_10},
+	{KEY_CPASS_MTX_11,          CPASS_MTX_11},
+	{KEY_CPASS_MTX_12,          CPASS_MTX_12},
+	{KEY_CPASS_MTX_20,          CPASS_MTX_20},
+	{KEY_CPASS_MTX_21,          CPASS_MTX_21},
+	{KEY_CPASS_MTX_22,          CPASS_MTX_22},
+	{KEY_D_ACT0,                D_ACT0},
+	{KEY_D_ACSX,                D_ACSX},
+	{KEY_D_ACSY,                D_ACSY},
+	{KEY_D_ACSZ,                D_ACSZ},
+	{KEY_FLICK_MSG,             FLICK_MSG},
+	{KEY_FLICK_COUNTER,         FLICK_COUNTER},
+	{KEY_FLICK_LOWER,           FLICK_LOWER},
+	{KEY_FLICK_UPPER,           FLICK_UPPER},
+	{KEY_D_PEDSTD_BP_B, D_PEDSTD_BP_B},
+	{KEY_D_PEDSTD_HP_A, D_PEDSTD_HP_A},
+	{KEY_D_PEDSTD_HP_B, D_PEDSTD_HP_B},
+	{KEY_D_PEDSTD_BP_A4, D_PEDSTD_BP_A4},
+	{KEY_D_PEDSTD_BP_A3, D_PEDSTD_BP_A3},
+	{KEY_D_PEDSTD_BP_A2, D_PEDSTD_BP_A2},
+	{KEY_D_PEDSTD_BP_A1, D_PEDSTD_BP_A1},
+	{KEY_D_PEDSTD_INT_THRSH, D_PEDSTD_INT_THRSH},
+	{KEY_D_PEDSTD_CLIP, D_PEDSTD_CLIP},
+	{KEY_D_PEDSTD_SB, D_PEDSTD_SB},
+	{KEY_D_PEDSTD_SB_TIME, D_PEDSTD_SB_TIME},
+	{KEY_D_PEDSTD_PEAKTHRSH, D_PEDSTD_PEAKTHRSH},
+	{KEY_D_PEDSTD_TIML,      D_PEDSTD_TIML},
+	{KEY_D_PEDSTD_TIMH,      D_PEDSTD_TIMH},
+	{KEY_D_PEDSTD_PEAK,      D_PEDSTD_PEAK},
+	{KEY_D_PEDSTD_STEPCTR,   D_PEDSTD_STEPCTR},
+	{KEY_D_PEDSTD_TIMECTR,  D_PEDSTD_TIMECTR},
+	{KEY_D_PEDSTD_DECI,  D_PEDSTD_DECI},
+	{KEY_D_HOST_NO_MOT,  D_HOST_NO_MOT}
+};
+#define NUM_LOCAL_KEYS (sizeof(dmpTConfig)/sizeof(dmpTConfig[0]))
+
+static struct tKeyLabel keys[NUM_KEYS];
+
+unsigned short inv_dmp_get_address(unsigned short key)
+{
+	static int isSorted;
+	if (!isSorted) {
+		int kk;
+		for (kk = 0; kk < NUM_KEYS; ++kk) {
+			keys[kk].addr = 0xffff;
+			keys[kk].key = kk;
+		}
+		for (kk = 0; kk < NUM_LOCAL_KEYS; ++kk)
+			keys[dmpTConfig[kk].key].addr = dmpTConfig[kk].addr;
+		isSorted = 1;
+	}
+	if (key >= NUM_KEYS)
+		return 0xffff;
+	return keys[key].addr;
+}
+/**
+ *  @}
+ */
diff --git a/drivers/staging/iio/imu/mpu6050/dmpKey.h b/drivers/staging/iio/imu/mpu6050/dmpKey.h
new file mode 100644
index 0000000..e8e1951
--- /dev/null
+++ b/drivers/staging/iio/imu/mpu6050/dmpKey.h
@@ -0,0 +1,494 @@
+/*
+ * Copyright (C) 2012 Invensense, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+#ifndef DMPKEY_H__
+#define DMPKEY_H__
+
+#define KEY_CFG_25                  (0)
+#define KEY_CFG_24                  (KEY_CFG_25 + 1)
+#define KEY_CFG_26                  (KEY_CFG_24 + 1)
+#define KEY_CFG_27                  (KEY_CFG_26 + 1)
+#define KEY_CFG_21                  (KEY_CFG_27 + 1)
+#define KEY_CFG_20                  (KEY_CFG_21 + 1)
+#define KEY_CFG_TAP4                (KEY_CFG_20 + 1)
+#define KEY_CFG_TAP5                (KEY_CFG_TAP4 + 1)
+#define KEY_CFG_TAP6                (KEY_CFG_TAP5 + 1)
+#define KEY_CFG_TAP7                (KEY_CFG_TAP6 + 1)
+#define KEY_CFG_TAP0                (KEY_CFG_TAP7 + 1)
+#define KEY_CFG_TAP1                (KEY_CFG_TAP0 + 1)
+#define KEY_CFG_TAP2                (KEY_CFG_TAP1 + 1)
+#define KEY_CFG_TAP3                (KEY_CFG_TAP2 + 1)
+#define KEY_CFG_TAP_QUANTIZE        (KEY_CFG_TAP3 + 1)
+#define KEY_CFG_TAP_JERK            (KEY_CFG_TAP_QUANTIZE + 1)
+#define KEY_CFG_DR_INT              (KEY_CFG_TAP_JERK + 1)
+#define KEY_CFG_AUTH                (KEY_CFG_DR_INT + 1)
+#define KEY_CFG_TAP_SAVE_ACCB       (KEY_CFG_AUTH + 1)
+#define KEY_CFG_TAP_CLEAR_STICKY    (KEY_CFG_TAP_SAVE_ACCB + 1)
+#define KEY_CFG_FIFO_ON_EVENT       (KEY_CFG_TAP_CLEAR_STICKY + 1)
+#define KEY_FCFG_ACCEL_INPUT        (KEY_CFG_FIFO_ON_EVENT + 1)
+#define KEY_FCFG_ACCEL_INIT         (KEY_FCFG_ACCEL_INPUT + 1)
+#define KEY_CFG_23                  (KEY_FCFG_ACCEL_INIT + 1)
+#define KEY_FCFG_1                  (KEY_CFG_23 + 1)
+#define KEY_FCFG_3                  (KEY_FCFG_1 + 1)
+#define KEY_FCFG_2                  (KEY_FCFG_3 + 1)
+#define KEY_CFG_3D                  (KEY_FCFG_2 + 1)
+#define KEY_CFG_3B                  (KEY_CFG_3D + 1)
+#define KEY_CFG_3C                  (KEY_CFG_3B + 1)
+#define KEY_FCFG_5                  (KEY_CFG_3C + 1)
+#define KEY_FCFG_4                  (KEY_FCFG_5 + 1)
+#define KEY_FCFG_7                  (KEY_FCFG_4 + 1)
+#define KEY_FCFG_FSCALE             (KEY_FCFG_7 + 1)
+#define KEY_FCFG_AZ                 (KEY_FCFG_FSCALE + 1)
+#define KEY_FCFG_6                  (KEY_FCFG_AZ + 1)
+#define KEY_FCFG_LSB4               (KEY_FCFG_6 + 1)
+#define KEY_CFG_12                  (KEY_FCFG_LSB4 + 1)
+#define KEY_CFG_14                  (KEY_CFG_12 + 1)
+#define KEY_CFG_15                  (KEY_CFG_14 + 1)
+#define KEY_CFG_16                  (KEY_CFG_15 + 1)
+#define KEY_CFG_18                  (KEY_CFG_16 + 1)
+#define KEY_CFG_6                   (KEY_CFG_18 + 1)
+#define KEY_CFG_7                   (KEY_CFG_6 + 1)
+#define KEY_CFG_4                   (KEY_CFG_7 + 1)
+#define KEY_CFG_5                   (KEY_CFG_4 + 1)
+#define KEY_CFG_2                   (KEY_CFG_5 + 1)
+#define KEY_CFG_3                   (KEY_CFG_2 + 1)
+#define KEY_CFG_1                   (KEY_CFG_3 + 1)
+#define KEY_CFG_EXTERNAL            (KEY_CFG_1 + 1)
+#define KEY_CFG_8                   (KEY_CFG_EXTERNAL + 1)
+#define KEY_CFG_9                   (KEY_CFG_8 + 1)
+#define KEY_CFG_ORIENT_3            (KEY_CFG_9 + 1)
+#define KEY_CFG_ORIENT_2            (KEY_CFG_ORIENT_3 + 1)
+#define KEY_CFG_ORIENT_1            (KEY_CFG_ORIENT_2 + 1)
+#define KEY_CFG_GYRO_SOURCE         (KEY_CFG_ORIENT_1 + 1)
+#define KEY_CFG_ORIENT_IRQ_1        (KEY_CFG_GYRO_SOURCE + 1)
+#define KEY_CFG_ORIENT_IRQ_2        (KEY_CFG_ORIENT_IRQ_1 + 1)
+#define KEY_CFG_ORIENT_IRQ_3        (KEY_CFG_ORIENT_IRQ_2 + 1)
+#define KEY_FCFG_MAG_VAL            (KEY_CFG_ORIENT_IRQ_3 + 1)
+#define KEY_FCFG_MAG_MOV            (KEY_FCFG_MAG_VAL + 1)
+#define KEY_CFG_LP_QUAT             (KEY_FCFG_MAG_MOV + 1)
+
+/* MPU6050 keys */
+#define KEY_CFG_ACCEL_FILTER        (KEY_CFG_LP_QUAT + 1)
+#define KEY_CFG_MOTION_BIAS         (KEY_CFG_ACCEL_FILTER + 1)
+#define KEY_TEMPLABEL               (KEY_CFG_MOTION_BIAS + 1)
+
+#define KEY_D_0_22                  (KEY_TEMPLABEL + 1)
+#define KEY_D_0_24                  (KEY_D_0_22 + 1)
+#define KEY_D_0_36                  (KEY_D_0_24 + 1)
+#define KEY_D_0_52                  (KEY_D_0_36 + 1)
+#define KEY_D_0_96                  (KEY_D_0_52 + 1)
+#define KEY_D_0_104                 (KEY_D_0_96 + 1)
+#define KEY_D_0_108                 (KEY_D_0_104 + 1)
+#define KEY_D_0_163                 (KEY_D_0_108 + 1)
+#define KEY_D_0_188                 (KEY_D_0_163 + 1)
+#define KEY_D_0_192                 (KEY_D_0_188 + 1)
+#define KEY_D_0_224                 (KEY_D_0_192 + 1)
+#define KEY_D_0_228                 (KEY_D_0_224 + 1)
+#define KEY_D_0_232                 (KEY_D_0_228 + 1)
+#define KEY_D_0_236                 (KEY_D_0_232 + 1)
+
+#define KEY_DMP_PREVPTAT            (KEY_D_0_236 + 1)
+#define KEY_D_1_2                   (KEY_DMP_PREVPTAT + 1)
+#define KEY_D_1_4                   (KEY_D_1_2 + 1)
+#define KEY_D_1_8                   (KEY_D_1_4 + 1)
+#define KEY_D_1_10                  (KEY_D_1_8 + 1)
+#define KEY_D_1_24                  (KEY_D_1_10 + 1)
+#define KEY_D_1_28                  (KEY_D_1_24 + 1)
+#define KEY_D_1_36                  (KEY_D_1_28 + 1)
+#define KEY_D_1_40                  (KEY_D_1_36 + 1)
+#define KEY_D_1_44                  (KEY_D_1_40 + 1)
+#define KEY_D_1_72                  (KEY_D_1_44 + 1)
+#define KEY_D_1_74                  (KEY_D_1_72 + 1)
+#define KEY_D_1_79                  (KEY_D_1_74 + 1)
+#define KEY_D_1_88                  (KEY_D_1_79 + 1)
+#define KEY_D_1_90                  (KEY_D_1_88 + 1)
+#define KEY_D_1_92                  (KEY_D_1_90 + 1)
+#define KEY_D_1_96                  (KEY_D_1_92 + 1)
+#define KEY_D_1_98                  (KEY_D_1_96 + 1)
+#define KEY_D_1_100                 (KEY_D_1_98 + 1)
+#define KEY_D_1_106                 (KEY_D_1_100 + 1)
+#define KEY_D_1_108                 (KEY_D_1_106 + 1)
+#define KEY_D_1_112                 (KEY_D_1_108 + 1)
+#define KEY_D_1_128                 (KEY_D_1_112 + 1)
+#define KEY_D_1_152                 (KEY_D_1_128 + 1)
+#define KEY_D_1_160                 (KEY_D_1_152 + 1)
+#define KEY_D_1_168                 (KEY_D_1_160 + 1)
+#define KEY_D_1_175                 (KEY_D_1_168 + 1)
+#define KEY_D_1_176                 (KEY_D_1_175 + 1)
+#define KEY_D_1_178                 (KEY_D_1_176 + 1)
+#define KEY_D_1_179                 (KEY_D_1_178 + 1)
+#define KEY_D_1_218                 (KEY_D_1_179 + 1)
+#define KEY_D_1_232                 (KEY_D_1_218 + 1)
+#define KEY_D_1_236                 (KEY_D_1_232 + 1)
+#define KEY_D_1_240                 (KEY_D_1_236 + 1)
+#define KEY_D_1_244                 (KEY_D_1_240 + 1)
+#define KEY_D_1_250                 (KEY_D_1_244 + 1)
+#define KEY_D_1_252                 (KEY_D_1_250 + 1)
+#define KEY_D_2_12                  (KEY_D_1_252 + 1)
+#define KEY_D_2_96                  (KEY_D_2_12 + 1)
+#define KEY_D_2_108                 (KEY_D_2_96 + 1)
+#define KEY_D_2_208                 (KEY_D_2_108 + 1)
+#define KEY_FLICK_MSG               (KEY_D_2_208 + 1)
+#define KEY_FLICK_COUNTER           (KEY_FLICK_MSG + 1)
+#define KEY_FLICK_LOWER             (KEY_FLICK_COUNTER + 1)
+#define KEY_CFG_FLICK_IN            (KEY_FLICK_LOWER + 1)
+#define KEY_FLICK_UPPER             (KEY_CFG_FLICK_IN + 1)
+#define KEY_CGNOTICE_INTR           (KEY_FLICK_UPPER + 1)
+#define KEY_D_2_224                 (KEY_CGNOTICE_INTR + 1)
+#define KEY_D_2_244                 (KEY_D_2_224 + 1)
+#define KEY_D_2_248                 (KEY_D_2_244 + 1)
+#define KEY_D_2_252                 (KEY_D_2_248 + 1)
+
+#define KEY_D_GYRO_BIAS_X               (KEY_D_2_252 + 1)
+#define KEY_D_GYRO_BIAS_Y               (KEY_D_GYRO_BIAS_X + 1)
+#define KEY_D_GYRO_BIAS_Z               (KEY_D_GYRO_BIAS_Y + 1)
+#define KEY_D_GYRO_ENABLE               (KEY_D_GYRO_BIAS_Z + 1)
+#define KEY_D_ACCEL_ENABLE              (KEY_D_GYRO_ENABLE + 1)
+#define KEY_D_QUAT_ENABLE               (KEY_D_ACCEL_ENABLE + 1)
+#define KEY_D_CR_TIME_G                 (KEY_D_QUAT_ENABLE + 1)
+#define KEY_D_CR_TIME_A                 (KEY_D_CR_TIME_G + 1)
+#define KEY_D_CR_TIME_Q                 (KEY_D_CR_TIME_A + 1)
+#define KEY_D_CS_TAX                    (KEY_D_CR_TIME_Q + 1)
+#define KEY_D_CS_TAY                    (KEY_D_CS_TAX + 1)
+#define KEY_D_CS_TAZ                    (KEY_D_CS_TAY + 1)
+
+#define KEY_D_CS_TGX                    (KEY_D_CS_TAZ + 1)
+#define KEY_D_CS_TGY                    (KEY_D_CS_TGX + 1)
+#define KEY_D_CS_TGZ                    (KEY_D_CS_TGY + 1)
+#define KEY_D_CS_TQ0                    (KEY_D_CS_TGZ + 1)
+#define KEY_D_CS_TQ1                    (KEY_D_CS_TQ0 + 1)
+#define KEY_D_CS_TQ2                    (KEY_D_CS_TQ1 + 1)
+#define KEY_D_CS_TQ3                    (KEY_D_CS_TQ2 + 1)
+
+/* Compass keys */
+#define KEY_CPASS_BIAS_X            (KEY_D_CS_TQ3 + 1)
+#define KEY_CPASS_BIAS_Y            (KEY_CPASS_BIAS_X + 1)
+#define KEY_CPASS_BIAS_Z            (KEY_CPASS_BIAS_Y + 1)
+#define KEY_CPASS_MTX_00            (KEY_CPASS_BIAS_Z + 1)
+#define KEY_CPASS_MTX_01            (KEY_CPASS_MTX_00 + 1)
+#define KEY_CPASS_MTX_02            (KEY_CPASS_MTX_01 + 1)
+#define KEY_CPASS_MTX_10            (KEY_CPASS_MTX_02 + 1)
+#define KEY_CPASS_MTX_11            (KEY_CPASS_MTX_10 + 1)
+#define KEY_CPASS_MTX_12            (KEY_CPASS_MTX_11 + 1)
+#define KEY_CPASS_MTX_20            (KEY_CPASS_MTX_12 + 1)
+#define KEY_CPASS_MTX_21            (KEY_CPASS_MTX_20 + 1)
+#define KEY_CPASS_MTX_22            (KEY_CPASS_MTX_21 + 1)
+
+/* Gesture Keys */
+#define KEY_DMP_TAPW_MIN            (KEY_CPASS_MTX_22 + 1)
+#define KEY_DMP_TAP_THR_X           (KEY_DMP_TAPW_MIN + 1)
+#define KEY_DMP_TAP_THR_Y           (KEY_DMP_TAP_THR_X + 1)
+#define KEY_DMP_TAP_THR_Z           (KEY_DMP_TAP_THR_Y + 1)
+#define KEY_DMP_SH_TH_Y             (KEY_DMP_TAP_THR_Z + 1)
+#define KEY_DMP_SH_TH_X             (KEY_DMP_SH_TH_Y + 1)
+#define KEY_DMP_SH_TH_Z             (KEY_DMP_SH_TH_X + 1)
+#define KEY_DMP_ORIENT              (KEY_DMP_SH_TH_Z + 1)
+#define KEY_D_ACT0                  (KEY_DMP_ORIENT + 1)
+#define KEY_D_ACSX                  (KEY_D_ACT0 + 1)
+#define KEY_D_ACSY                  (KEY_D_ACSX + 1)
+#define KEY_D_ACSZ                  (KEY_D_ACSY + 1)
+
+#define KEY_X_GRT_Y_TMP             (KEY_D_ACSZ + 1)
+#define KEY_SKIP_X_GRT_Y_TMP        (KEY_X_GRT_Y_TMP + 1)
+#define KEY_SKIP_END_COMPARE        (KEY_SKIP_X_GRT_Y_TMP + 1)
+#define KEY_END_COMPARE_Y_X_TMP2    (KEY_SKIP_END_COMPARE + 1)
+#define KEY_CFG_DISPLAY_ORIENT_INT  (KEY_END_COMPARE_Y_X_TMP2 + 1)
+#define KEY_NO_ORIENT_INTERRUPT     (KEY_CFG_DISPLAY_ORIENT_INT + 1)
+#define KEY_END_COMPARE_Y_X_TMP     (KEY_NO_ORIENT_INTERRUPT + 1)
+#define KEY_END_ORIENT_1            (KEY_END_COMPARE_Y_X_TMP + 1)
+#define KEY_END_COMPARE_Y_X         (KEY_END_ORIENT_1 + 1)
+#define KEY_END_ORIENT              (KEY_END_COMPARE_Y_X + 1)
+#define KEY_X_GRT_Y                 (KEY_END_ORIENT + 1)
+#define KEY_NOT_TIME_MINUS_1        (KEY_X_GRT_Y + 1)
+#define KEY_END_COMPARE_Y_X_TMP3    (KEY_NOT_TIME_MINUS_1 + 1)
+#define KEY_X_GRT_Y_TMP2            (KEY_END_COMPARE_Y_X_TMP3 + 1)
+
+/* Authenticate Keys */
+#define KEY_D_AUTH_OUT              (KEY_X_GRT_Y_TMP2 + 1)
+#define KEY_D_AUTH_IN               (KEY_D_AUTH_OUT + 1)
+#define KEY_D_AUTH_A                (KEY_D_AUTH_IN + 1)
+#define KEY_D_AUTH_B                (KEY_D_AUTH_A + 1)
+
+/* Pedometer standalone only keys */
+#define KEY_D_PEDSTD_BP_B           (KEY_D_AUTH_B + 1)
+#define KEY_D_PEDSTD_HP_A           (KEY_D_PEDSTD_BP_B + 1)
+#define KEY_D_PEDSTD_HP_B           (KEY_D_PEDSTD_HP_A + 1)
+#define KEY_D_PEDSTD_BP_A4          (KEY_D_PEDSTD_HP_B + 1)
+#define KEY_D_PEDSTD_BP_A3          (KEY_D_PEDSTD_BP_A4 + 1)
+#define KEY_D_PEDSTD_BP_A2          (KEY_D_PEDSTD_BP_A3 + 1)
+#define KEY_D_PEDSTD_BP_A1          (KEY_D_PEDSTD_BP_A2 + 1)
+#define KEY_D_PEDSTD_INT_THRSH      (KEY_D_PEDSTD_BP_A1 + 1)
+#define KEY_D_PEDSTD_CLIP           (KEY_D_PEDSTD_INT_THRSH + 1)
+#define KEY_D_PEDSTD_SB             (KEY_D_PEDSTD_CLIP + 1)
+#define KEY_D_PEDSTD_SB_TIME        (KEY_D_PEDSTD_SB + 1)
+#define KEY_D_PEDSTD_PEAKTHRSH      (KEY_D_PEDSTD_SB_TIME + 1)
+#define KEY_D_PEDSTD_TIML           (KEY_D_PEDSTD_PEAKTHRSH + 1)
+#define KEY_D_PEDSTD_TIMH           (KEY_D_PEDSTD_TIML + 1)
+#define KEY_D_PEDSTD_PEAK           (KEY_D_PEDSTD_TIMH + 1)
+#define KEY_D_PEDSTD_TIMECTR        (KEY_D_PEDSTD_PEAK + 1)
+#define KEY_D_PEDSTD_STEPCTR        (KEY_D_PEDSTD_TIMECTR + 1)
+#define KEY_D_PEDSTD_WALKTIME       (KEY_D_PEDSTD_STEPCTR + 1)
+#define KEY_D_PEDSTD_DECI           (KEY_D_PEDSTD_WALKTIME + 1)
+
+/*Host Based No Motion*/
+#define KEY_D_HOST_NO_MOT           (KEY_D_PEDSTD_DECI + 1)
+
+/* EIS keys */
+#define KEY_P_EIS_FIFO_FOOTER       (KEY_D_HOST_NO_MOT + 1)
+#define KEY_P_EIS_FIFO_YSHIFT       (KEY_P_EIS_FIFO_FOOTER + 1)
+#define KEY_P_EIS_DATA_RATE         (KEY_P_EIS_FIFO_YSHIFT + 1)
+#define KEY_P_EIS_FIFO_XSHIFT       (KEY_P_EIS_DATA_RATE + 1)
+#define KEY_P_EIS_FIFO_SYNC         (KEY_P_EIS_FIFO_XSHIFT + 1)
+#define KEY_P_EIS_FIFO_ZSHIFT       (KEY_P_EIS_FIFO_SYNC + 1)
+#define KEY_P_EIS_FIFO_READY        (KEY_P_EIS_FIFO_ZSHIFT + 1)
+#define KEY_DMP_FOOTER              (KEY_P_EIS_FIFO_READY + 1)
+#define KEY_DMP_INTX_HC             (KEY_DMP_FOOTER + 1)
+#define KEY_DMP_INTX_PH             (KEY_DMP_INTX_HC + 1)
+#define KEY_DMP_INTX_SH             (KEY_DMP_INTX_PH + 1)
+#define KEY_DMP_AINV_SH             (KEY_DMP_INTX_SH + 1)
+#define KEY_DMP_A_INV_XH            (KEY_DMP_AINV_SH + 1)
+#define KEY_DMP_AINV_PH             (KEY_DMP_A_INV_XH + 1)
+#define KEY_DMP_CTHX_H              (KEY_DMP_AINV_PH + 1)
+#define KEY_DMP_CTHY_H              (KEY_DMP_CTHX_H + 1)
+#define KEY_DMP_CTHZ_H              (KEY_DMP_CTHY_H + 1)
+#define KEY_DMP_NCTHX_H             (KEY_DMP_CTHZ_H + 1)
+#define KEY_DMP_NCTHY_H             (KEY_DMP_NCTHX_H + 1)
+#define KEY_DMP_NCTHZ_H             (KEY_DMP_NCTHY_H + 1)
+#define KEY_DMP_CTSQ_XH             (KEY_DMP_NCTHZ_H + 1)
+#define KEY_DMP_CTSQ_YH             (KEY_DMP_CTSQ_XH + 1)
+#define KEY_DMP_CTSQ_ZH             (KEY_DMP_CTSQ_YH + 1)
+#define KEY_DMP_INTX_H              (KEY_DMP_CTSQ_ZH + 1)
+#define KEY_DMP_INTY_H              (KEY_DMP_INTX_H + 1)
+#define KEY_DMP_INTZ_H              (KEY_DMP_INTY_H + 1)
+#define KEY_DMP_HPX_H               (KEY_DMP_INTZ_H + 1)
+#define KEY_DMP_HPY_H               (KEY_DMP_HPX_H + 1)
+#define KEY_DMP_HPZ_H               (KEY_DMP_HPY_H + 1)
+
+/* Stream keys */
+#define KEY_STREAM_P_GYRO_Z         (KEY_DMP_HPZ_H + 1)
+#define KEY_STREAM_P_GYRO_Y         (KEY_STREAM_P_GYRO_Z + 1)
+#define KEY_STREAM_P_GYRO_X         (KEY_STREAM_P_GYRO_Y + 1)
+#define KEY_STREAM_P_TEMP           (KEY_STREAM_P_GYRO_X + 1)
+#define KEY_STREAM_P_AUX_Y          (KEY_STREAM_P_TEMP + 1)
+#define KEY_STREAM_P_AUX_X          (KEY_STREAM_P_AUX_Y + 1)
+#define KEY_STREAM_P_AUX_Z          (KEY_STREAM_P_AUX_X + 1)
+#define KEY_STREAM_P_ACCEL_Y        (KEY_STREAM_P_AUX_Z + 1)
+#define KEY_STREAM_P_ACCEL_X        (KEY_STREAM_P_ACCEL_Y + 1)
+#define KEY_STREAM_P_FOOTER         (KEY_STREAM_P_ACCEL_X + 1)
+#define KEY_STREAM_P_ACCEL_Z        (KEY_STREAM_P_FOOTER + 1)
+
+#define NUM_KEYS                    (KEY_STREAM_P_ACCEL_Z + 1)
+
+struct tKeyLabel  {
+	unsigned short key;
+	unsigned short addr;
+};
+
+#define DINA0A 0x0a
+#define DINA22 0x22
+#define DINA42 0x42
+#define DINA5A 0x5a
+
+#define DINA06 0x06
+#define DINA0E 0x0e
+#define DINA16 0x16
+#define DINA1E 0x1e
+#define DINA26 0x26
+#define DINA2E 0x2e
+#define DINA36 0x36
+#define DINA3E 0x3e
+#define DINA46 0x46
+#define DINA4E 0x4e
+#define DINA56 0x56
+#define DINA5E 0x5e
+#define DINA66 0x66
+#define DINA6E 0x6e
+#define DINA76 0x76
+#define DINA7E 0x7e
+
+#define DINA00 0x00
+#define DINA08 0x08
+#define DINA10 0x10
+#define DINA18 0x18
+#define DINA20 0x20
+#define DINA28 0x28
+#define DINA30 0x30
+#define DINA38 0x38
+#define DINA40 0x40
+#define DINA48 0x48
+#define DINA50 0x50
+#define DINA58 0x58
+#define DINA60 0x60
+#define DINA68 0x68
+#define DINA70 0x70
+#define DINA78 0x78
+
+#define DINA04 0x04
+#define DINA0C 0x0c
+#define DINA14 0x14
+#define DINA1C 0x1C
+#define DINA24 0x24
+#define DINA2C 0x2c
+#define DINA34 0x34
+#define DINA3C 0x3c
+#define DINA44 0x44
+#define DINA4C 0x4c
+#define DINA54 0x54
+#define DINA5C 0x5c
+#define DINA64 0x64
+#define DINA6C 0x6c
+#define DINA74 0x74
+#define DINA7C 0x7c
+
+#define DINA01 0x01
+#define DINA09 0x09
+#define DINA11 0x11
+#define DINA19 0x19
+#define DINA21 0x21
+#define DINA29 0x29
+#define DINA31 0x31
+#define DINA39 0x39
+#define DINA41 0x41
+#define DINA49 0x49
+#define DINA51 0x51
+#define DINA59 0x59
+#define DINA61 0x61
+#define DINA69 0x69
+#define DINA71 0x71
+#define DINA79 0x79
+
+#define DINA25 0x25
+#define DINA2D 0x2d
+#define DINA35 0x35
+#define DINA3D 0x3d
+#define DINA4D 0x4d
+#define DINA55 0x55
+#define DINA5D 0x5D
+#define DINA6D 0x6d
+#define DINA75 0x75
+#define DINA7D 0x7d
+
+#define DINADC 0xdc
+#define DINAF2 0xf2
+#define DINAAB 0xab
+#define DINAAA 0xaa
+#define DINAF1 0xf1
+#define DINADF 0xdf
+#define DINADA 0xda
+#define DINAB1 0xb1
+#define DINAB9 0xb9
+#define DINAF3 0xf3
+#define DINA8B 0x8b
+#define DINAA3 0xa3
+#define DINA91 0x91
+#define DINAB6 0xb6
+#define DINAB4 0xb4
+
+
+#define DINC00 0x00
+#define DINC01 0x01
+#define DINC02 0x02
+#define DINC03 0x03
+#define DINC08 0x08
+#define DINC09 0x09
+#define DINC0A 0x0a
+#define DINC0B 0x0b
+#define DINC10 0x10
+#define DINC11 0x11
+#define DINC12 0x12
+#define DINC13 0x13
+#define DINC18 0x18
+#define DINC19 0x19
+#define DINC1A 0x1a
+#define DINC1B 0x1b
+
+#define DINC20 0x20
+#define DINC21 0x21
+#define DINC22 0x22
+#define DINC23 0x23
+#define DINC28 0x28
+#define DINC29 0x29
+#define DINC2A 0x2a
+#define DINC2B 0x2b
+#define DINC30 0x30
+#define DINC31 0x31
+#define DINC32 0x32
+#define DINC33 0x33
+#define DINC38 0x38
+#define DINC39 0x39
+#define DINC3A 0x3a
+#define DINC3B 0x3b
+
+#define DINC40 0x40
+#define DINC41 0x41
+#define DINC42 0x42
+#define DINC43 0x43
+#define DINC48 0x48
+#define DINC49 0x49
+#define DINC4A 0x4a
+#define DINC4B 0x4b
+#define DINC50 0x50
+#define DINC51 0x51
+#define DINC52 0x52
+#define DINC53 0x53
+#define DINC58 0x58
+#define DINC59 0x59
+#define DINC5A 0x5a
+#define DINC5B 0x5b
+
+#define DINC60 0x60
+#define DINC61 0x61
+#define DINC62 0x62
+#define DINC63 0x63
+#define DINC68 0x68
+#define DINC69 0x69
+#define DINC6A 0x6a
+#define DINC6B 0x6b
+#define DINC70 0x70
+#define DINC71 0x71
+#define DINC72 0x72
+#define DINC73 0x73
+#define DINC78 0x78
+#define DINC79 0x79
+#define DINC7A 0x7a
+#define DINC7B 0x7b
+#define DIND40 0x40
+#define DINA80 0x80
+#define DINA90 0x90
+#define DINAA0 0xa0
+#define DINAC9 0xc9
+#define DINACB 0xcb
+#define DINACD 0xcd
+#define DINACF 0xcf
+#define DINAC8 0xc8
+#define DINACA 0xca
+#define DINACC 0xcc
+#define DINACE 0xce
+#define DINAD8 0xd8
+#define DINADD 0xdd
+#define DINAF8 0xf0
+#define DINAFE 0xfe
+
+#define DINBF8 0xf8
+#define DINAC0 0xb0
+#define DINAC1 0xb1
+#define DINAC2 0xb4
+#define DINAC3 0xb5
+#define DINAC4 0xb8
+#define DINAC5 0xb9
+#define DINBC0 0xc0
+#define DINBC2 0xc2
+#define DINBC4 0xc4
+#define DINBC6 0xc6
+
+#endif
diff --git a/drivers/staging/iio/imu/mpu6050/dmpmap.h b/drivers/staging/iio/imu/mpu6050/dmpmap.h
new file mode 100644
index 0000000..420e19d
--- /dev/null
+++ b/drivers/staging/iio/imu/mpu6050/dmpmap.h
@@ -0,0 +1,266 @@
+/*
+* Copyright (C) 2012 Invensense, Inc.
+*
+* This software is licensed under the terms of the GNU General Public
+* License version 2, as published by the Free Software Foundation, and
+* may be copied, distributed, and modified under those terms.
+*
+* 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.
+*
+*/
+
+#ifndef DMPMAP_H
+#define DMPMAP_H
+
+#define DMP_PTAT    0
+#define DMP_XGYR    2
+#define DMP_YGYR    4
+#define DMP_ZGYR    6
+#define DMP_XACC    8
+#define DMP_YACC    10
+#define DMP_ZACC    12
+#define DMP_ADC1    14
+#define DMP_ADC2    16
+#define DMP_ADC3    18
+#define DMP_BIASUNC    20
+#define DMP_FIFORT    22
+#define DMP_INVGSFH    24
+#define DMP_INVGSFL    26
+#define DMP_1H    28
+#define DMP_1L    30
+#define DMP_BLPFSTCH    32
+#define DMP_BLPFSTCL    34
+#define DMP_BLPFSXH    36
+#define DMP_BLPFSXL    38
+#define DMP_BLPFSYH    40
+#define DMP_BLPFSYL    42
+#define DMP_BLPFSZH    44
+#define DMP_BLPFSZL    46
+#define DMP_BLPFMTC    48
+#define DMP_SMC    50
+#define DMP_BLPFMXH    52
+#define DMP_BLPFMXL    54
+#define DMP_BLPFMYH    56
+#define DMP_BLPFMYL    58
+#define DMP_BLPFMZH    60
+#define DMP_BLPFMZL    62
+#define DMP_BLPFC    64
+#define DMP_SMCTH    66
+#define DMP_0H2    68
+#define DMP_0L2    70
+#define DMP_BERR2H    72
+#define DMP_BERR2L    74
+#define DMP_BERR2NH    76
+#define DMP_SMCINC    78
+#define DMP_ANGVBXH    80
+#define DMP_ANGVBXL    82
+#define DMP_ANGVBYH    84
+#define DMP_ANGVBYL    86
+#define DMP_ANGVBZH    88
+#define DMP_ANGVBZL    90
+#define DMP_BERR1H    92
+#define DMP_BERR1L    94
+#define DMP_ATCH    96
+#define DMP_BIASUNCSF    98
+#define DMP_ACT2H    100
+#define DMP_ACT2L    102
+#define DMP_GSFH    104
+#define DMP_GSFL    106
+#define DMP_GH    108
+#define DMP_GL    110
+#define DMP_0_5H    112
+#define DMP_0_5L    114
+#define DMP_0_0H    116
+#define DMP_0_0L    118
+#define DMP_1_0H    120
+#define DMP_1_0L    122
+#define DMP_1_5H    124
+#define DMP_1_5L    126
+#define DMP_TMP1AH    128
+#define DMP_TMP1AL    130
+#define DMP_TMP2AH    132
+#define DMP_TMP2AL    134
+#define DMP_TMP3AH    136
+#define DMP_TMP3AL    138
+#define DMP_TMP4AH    140
+#define DMP_TMP4AL    142
+#define DMP_XACCW    144
+#define DMP_TMP5    146
+#define DMP_XACCB    148
+#define DMP_TMP8    150
+#define DMP_YACCB    152
+#define DMP_TMP9    154
+#define DMP_ZACCB    156
+#define DMP_TMP10    158
+#define DMP_DZH    160
+#define DMP_DZL    162
+#define DMP_XGCH    164
+#define DMP_XGCL    166
+#define DMP_YGCH    168
+#define DMP_YGCL    170
+#define DMP_ZGCH    172
+#define DMP_ZGCL    174
+#define DMP_YACCW    176
+#define DMP_TMP7    178
+#define DMP_AFB1H    180
+#define DMP_AFB1L    182
+#define DMP_AFB2H    184
+#define DMP_AFB2L    186
+#define DMP_MAGFBH    188
+#define DMP_MAGFBL    190
+#define DMP_QT1H    192
+#define DMP_QT1L    194
+#define DMP_QT2H    196
+#define DMP_QT2L    198
+#define DMP_QT3H    200
+#define DMP_QT3L    202
+#define DMP_QT4H    204
+#define DMP_QT4L    206
+#define DMP_CTRL1H    208
+#define DMP_CTRL1L    210
+#define DMP_CTRL2H    212
+#define DMP_CTRL2L    214
+#define DMP_CTRL3H    216
+#define DMP_CTRL3L    218
+#define DMP_CTRL4H    220
+#define DMP_CTRL4L    222
+#define DMP_CTRLS1    224
+#define DMP_CTRLSF1    226
+#define DMP_CTRLS2    228
+#define DMP_CTRLSF2    230
+#define DMP_CTRLS3    232
+#define DMP_CTRLSFNLL    234
+#define DMP_CTRLS4    236
+#define DMP_CTRLSFNL2    238
+#define DMP_CTRLSFNL    240
+#define DMP_TMP30    242
+#define DMP_CTRLSFJT    244
+#define DMP_TMP31    246
+#define DMP_TMP11    248
+#define DMP_CTRLSF2_2    250
+#define DMP_TMP12    252
+#define DMP_CTRLSF1_2    254
+#define DMP_PREVPTAT    256
+#define DMP_ACCZB    258
+#define DMP_ACCXB    264
+#define DMP_ACCYB    266
+#define DMP_1HB    272
+#define DMP_1LB    274
+#define DMP_0H    276
+#define DMP_0L    278
+#define DMP_ASR22H    280
+#define DMP_ASR22L    282
+#define DMP_ASR6H    284
+#define DMP_ASR6L    286
+#define DMP_TMP13    288
+#define DMP_TMP14    290
+#define DMP_FINTXH    292
+#define DMP_FINTXL    294
+#define DMP_FINTYH    296
+#define DMP_FINTYL    298
+#define DMP_FINTZH    300
+#define DMP_FINTZL    302
+#define DMP_TMP1BH    304
+#define DMP_TMP1BL    306
+#define DMP_TMP2BH    308
+#define DMP_TMP2BL    310
+#define DMP_TMP3BH    312
+#define DMP_TMP3BL    314
+#define DMP_TMP4BH    316
+#define DMP_TMP4BL    318
+#define DMP_STXG    320
+#define DMP_ZCTXG    322
+#define DMP_STYG    324
+#define DMP_ZCTYG    326
+#define DMP_STZG    328
+#define DMP_ZCTZG    330
+#define DMP_CTRLSFJT2    332
+#define DMP_CTRLSFJTCNT    334
+#define DMP_PVXG    336
+#define DMP_TMP15    338
+#define DMP_PVYG    340
+#define DMP_TMP16    342
+#define DMP_PVZG    344
+#define DMP_TMP17    346
+#define DMP_MNMFLAGH    352
+#define DMP_MNMFLAGL    354
+#define DMP_MNMTMH    356
+#define DMP_MNMTML    358
+#define DMP_MNMTMTHRH    360
+#define DMP_MNMTMTHRL    362
+#define DMP_MNMTHRH    364
+#define DMP_MNMTHRL    366
+#define DMP_ACCQD4H    368
+#define DMP_ACCQD4L    370
+#define DMP_ACCQD5H    372
+#define DMP_ACCQD5L    374
+#define DMP_ACCQD6H    376
+#define DMP_ACCQD6L    378
+#define DMP_ACCQD7H    380
+#define DMP_ACCQD7L    382
+#define DMP_ACCQD0H    384
+#define DMP_ACCQD0L    386
+#define DMP_ACCQD1H    388
+#define DMP_ACCQD1L    390
+#define DMP_ACCQD2H    392
+#define DMP_ACCQD2L    394
+#define DMP_ACCQD3H    396
+#define DMP_ACCQD3L    398
+#define DMP_XN2H    400
+#define DMP_XN2L    402
+#define DMP_XN1H    404
+#define DMP_XN1L    406
+#define DMP_YN2H    408
+#define DMP_YN2L    410
+#define DMP_YN1H    412
+#define DMP_YN1L    414
+#define DMP_YH    416
+#define DMP_YL    418
+#define DMP_B0H    420
+#define DMP_B0L    422
+#define DMP_A1H    424
+#define DMP_A1L    426
+#define DMP_A2H    428
+#define DMP_A2L    430
+#define DMP_SEM1    432
+#define DMP_FIFOCNT    434
+#define DMP_SH_TH_X    436
+#define DMP_PACKET    438
+#define DMP_SH_TH_Y    440
+#define DMP_FOOTER    442
+#define DMP_SH_TH_Z    444
+#define DMP_TEMP29    448
+#define DMP_TEMP30    450
+#define DMP_XACCB_PRE    452
+#define DMP_XACCB_PREL    454
+#define DMP_YACCB_PRE    456
+#define DMP_YACCB_PREL    458
+#define DMP_ZACCB_PRE    460
+#define DMP_ZACCB_PREL    462
+#define DMP_TMP22    464
+#define DMP_TAP_TIMER    466
+#define DMP_TAP_THX    468
+#define DMP_TAP_THY    472
+#define DMP_TAP_THZ    476
+#define DMP_TAPW_MIN    478
+#define DMP_TMP25    480
+#define DMP_TMP26    482
+#define DMP_TMP27    484
+#define DMP_TMP28    486
+#define DMP_ORIENT    488
+#define DMP_THRSH    490
+#define DMP_ENDIANH    492
+#define DMP_ENDIANL    494
+#define DMP_BLPFNMTCH    496
+#define DMP_BLPFNMTCL    498
+#define DMP_BLPFNMXH    500
+#define DMP_BLPFNMXL    502
+#define DMP_BLPFNMYH    504
+#define DMP_BLPFNMYL    506
+#define DMP_BLPFNMZH    508
+#define DMP_BLPFNMZL    510
+
+#endif
diff --git a/drivers/staging/iio/imu/mpu6050/inv_mpu_iio.h b/drivers/staging/iio/imu/mpu6050/inv_mpu_iio.h
new file mode 100644
index 0000000..0958d4a
--- /dev/null
+++ b/drivers/staging/iio/imu/mpu6050/inv_mpu_iio.h
@@ -0,0 +1,727 @@
+/*
+* Copyright (C) 2012 Invensense, Inc.
+*
+* This software is licensed under the terms of the GNU General Public
+* License version 2, as published by the Free Software Foundation, and
+* may be copied, distributed, and modified under those terms.
+*
+* 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.
+*
+*/
+
+#ifndef _INV_MPU_IIO_H_
+#define _INV_MPU_IIO_H_
+
+#include <linux/i2c.h>
+#include <linux/kfifo.h>
+#include <linux/miscdevice.h>
+#include <linux/input.h>
+#include <linux/spinlock.h>
+#include "./mpu.h"
+#include "../../iio.h"
+#include "../../buffer.h"
+#include "dmpKey.h"
+/**
+ *  struct inv_reg_map_s - Notable slave registers.
+ *  @sample_rate_div:	Divider applied to gyro output rate.
+ *  @lpf:		Configures internal LPF.
+ *  @bank_sel:		Selects between memory banks.
+ *  @user_ctrl:		Enables/resets the FIFO.
+ *  @fifo_en:		Determines which data will appear in FIFO.
+ *  @gyro_config:	gyro config register.
+ *  @accl_config:	accel config register
+ *  @fifo_count_h:	Upper byte of FIFO count.
+ *  @fifo_r_w:		FIFO register.
+ *  @raw_gyro		Address of first gyro register.
+ *  @raw_accl		Address of first accel register.
+ *  @temperature	temperature register
+ *  @int_enable:	Interrupt enable register.
+ *  @int_status:	Interrupt flags.
+ *  @pwr_mgmt_1:	Controls chip's power state and clock source.
+ *  @pwr_mgmt_2:	Controls power state of individual sensors.
+ *  @mem_start_addr:	Address of first memory read.
+ *  @mem_r_w:		Access to memory.
+ *  @prgm_strt_addrh	firmware program start address register
+ */
+struct inv_reg_map_s {
+	unsigned char sample_rate_div;
+	unsigned char lpf;
+	unsigned char bank_sel;
+	unsigned char user_ctrl;
+	unsigned char fifo_en;
+	unsigned char gyro_config;
+	unsigned char accl_config;
+	unsigned char fifo_count_h;
+	unsigned char fifo_r_w;
+	unsigned char raw_gyro;
+	unsigned char raw_accl;
+	unsigned char temperature;
+	unsigned char int_enable;
+	unsigned char int_status;
+	unsigned char pwr_mgmt_1;
+	unsigned char pwr_mgmt_2;
+	unsigned char mem_start_addr;
+	unsigned char mem_r_w;
+	unsigned char prgm_strt_addrh;
+};
+/*device enum */
+enum inv_devices {
+	INV_MPU6050,
+	INV_MPU9150,
+	INV_NUM_PARTS
+};
+
+/**
+ *  struct test_setup_t - set up parameters for self test.
+ *  @gyro_sens: sensitity for gyro.
+ *  @sample_rate: sample rate, i.e, fifo rate.
+ *  @lpf:	low pass filter.
+ *  @fsr:	full scale range.
+ *  @accl_fs:	accel full scale range.
+ *  @accl_sens:	accel sensitivity
+ */
+struct test_setup_t {
+	int gyro_sens;
+	int sample_rate;
+	int lpf;
+	int fsr;
+	int accl_fs;
+	unsigned int accl_sens[3];
+};
+
+/**
+ *  struct inv_hw_s - Other important hardware information.
+ *  @num_reg:	Number of registers on device.
+ *  @name:      name of the chip
+ */
+struct inv_hw_s {
+	unsigned char num_reg;
+	unsigned char *name;
+};
+
+/**
+ *  struct inv_chip_config_s - Cached chip configuration data.
+ *  @fsr:		Full scale range.
+ *  @lpf:		Digital low pass filter frequency.
+ *  @clk_src:		Clock source.
+ *  @accl_fs:		accel full scale range.
+ *  @self_test_run_once flag for self test run ever.
+ *  @has_compass:	has compass or not.
+ *  @enable:		master enable to enable output
+ *  @accl_enable:	enable accel functionality
+ *  @accl_fifo_enable:	enable accel data output
+ *  @gyro_enable:	enable gyro functionality
+ *  @gyro_fifo_enable:	enable gyro data output
+ *  @compass_enable:	enable compass
+ *  @compass_fifo_enable: enable compass data output
+ *  @is_asleep:		1 if chip is powered down.
+ *  @dmp_on:		dmp is on/off.
+ *  @dmp_int_on:        dmp interrupt on/off.
+ *  @dmp_event_int_on:  dmp event interrupt on/off.
+ *  @orientation_on:	dmp is on/off.
+ *  @firmware_loaded:	flag indicate firmware loaded or not.
+ *  @lpa_mod:		low power mode.
+ *  @tap_on:		tap on/off.
+ *  @flick_int_on:	flick interrupt on/off.
+ *  @quaternion_on:	send quaternion data on/off.
+ *  @display_orient_on:	display orientation on/off.
+ *  @lpa_freq:		low power frequency
+ *  @prog_start_addr:	firmware program start address.
+ *  @dmp_output_rate:   dmp output rate.
+ *  @fifo_rate:		FIFO update rate.
+ */
+struct inv_chip_config_s {
+	unsigned int fsr:2;
+	unsigned int lpf:3;
+	unsigned int clk_src:1;
+	unsigned int accl_fs:2;
+	unsigned int self_test_run_once:1;
+	unsigned int has_compass:1;
+	unsigned int enable:1;
+	unsigned int accl_enable:1;
+	unsigned int accl_fifo_enable:1;
+	unsigned int gyro_enable:1;
+	unsigned int gyro_fifo_enable:1;
+	unsigned int compass_enable:1;
+	unsigned int compass_fifo_enable:1;
+	unsigned int is_asleep:1;
+	unsigned int dmp_on:1;
+	unsigned int dmp_int_on:1;
+	unsigned int dmp_event_int_on:1;
+	unsigned int orientation_on:1;
+	unsigned int firmware_loaded:1;
+	unsigned int lpa_mode:1;
+	unsigned int tap_on:1;
+	unsigned int flick_int_on:1;
+	unsigned int quaternion_on:1;
+	unsigned int display_orient_on:1;
+	unsigned short lpa_freq;
+	unsigned short  prog_start_addr;
+	unsigned short fifo_rate;
+	unsigned short dmp_output_rate;
+};
+
+/**
+ *  struct inv_chip_info_s - Chip related information.
+ *  @product_id:	Product id.
+ *  @product_revision:	Product revision.
+ *  @silicon_revision:	Silicon revision.
+ *  @software_revision:	software revision.
+ *  @multi:		accel specific multiplier.
+ *  @compass_sens:	compass sensitivity.
+ *  @gyro_sens_trim:	Gyro sensitivity trim factor.
+ *  @accl_sens_trim:    accel sensitivity trim factor.
+ */
+struct inv_chip_info_s {
+	unsigned char product_id;
+	unsigned char product_revision;
+	unsigned char silicon_revision;
+	unsigned char software_revision;
+	unsigned char multi;
+	unsigned char compass_sens[3];
+	unsigned long gyro_sens_trim;
+	unsigned long accl_sens_trim;
+};
+
+/**
+ *  struct inv_flick_s structure to store flick data.
+ *  @lower:	lower bound of flick.
+ *  @upper:     upper bound of flick.
+ *  @counter:	counter of flick.
+ *  @msg_on;    message to carry flick
+ *  @axis:      axis of flick
+ */
+struct inv_flick_s {
+	int lower;
+	int upper;
+	int counter;
+	int msg_on;
+	int axis;
+};
+
+enum inv_channel_num {
+	INV_CHANNEL_NUM_GYRO = 4,
+	INV_CHANNEL_NUM_GYRO_ACCL = 7,
+	INV_CHANNEL_NUM_GYRO_ACCL_QUANTERNION = 11,
+	INV_CHANNEL_NUM_GYRO_ACCL_QUANTERNION_MAGN = 14,
+};
+
+/**
+ *  struct inv_tap_s structure to store tap data.
+ *  @min_count:  minimum taps counted.
+ *  @thresh:    tap threshold.
+ *  @time:	tap time.
+ */
+struct inv_tap_s {
+	unsigned short min_count;
+	unsigned short thresh;
+	unsigned short time;
+};
+struct inv_mpu_slave;
+/**
+ *  struct inv_mpu_iio_s - Driver state variables.
+ *  @chip_config:	Cached attribute information.
+ *  @chip_info:		Chip information from read-only registers.
+ *  @trig;              iio trigger.
+ *  @flick:		flick data structure
+ *  @tap:               tap data structure
+ *  @reg:		Map of important registers.
+ *  @hw:		Other hardware-specific information.
+ *  @chip_type:		chip type.
+ *  @time_stamp_lock:	spin lock to time stamp.
+ *  @client:		i2c client handle.
+ *  @plat_data:		platform data.
+ *  @mpu_slave:		mpu slave handle.
+ *  int (*set_power_state)(struct inv_mpu_iio_s *, int on): function ptr
+ *  int (*switch_gyro_engine)(struct inv_mpu_iio_s *, int on): function ptr
+ *  int (*switch_accl_engine)(struct inv_mpu_iio_s *, int on): function ptr
+ *  int (*init_config)(struct iio_dev *indio_dev): function ptr
+ * void (*setup_reg)(struct inv_reg_map_s *reg): function ptr
+ *  @timestamps:        kfifo queue to store time stamp.
+ *  @compass_st_upper:  compass self test upper limit.
+ *  @compass_st_lower:  compass self test lower limit.
+ *  @irq:               irq number store.
+ *  @accel_bias:        accel bias store.
+ *  @gyro_bias:         gyro bias store.
+ *  @raw_gyro:          raw gyro data.
+ *  @raw_accel:         raw accel data.
+ *  @raw_compass:       raw compass.
+ *  @compass_scale:     compass scale.
+ *  @i2c_addr:          i2c address.
+ *  @compass_divider:   slow down compass rate.
+ *  @compass_counter:   slow down compass rate.
+ *  @sample_divider:    sample divider for dmp.
+ *  @fifo_divider:      fifo divider for dmp.
+ *  @orient_data:       orientation data.
+ *  @display_orient_data:display orient data.
+ *  @tap_data:          tap data.
+ *  @num_channels:      number of channels for current chip.
+ *  @sl_handle:         Handle to I2C port.
+ *  @irq_dur_ns:        duration between each irq.
+ *  @last_isr_time:     last isr time.
+ */
+struct inv_mpu_iio_s {
+#define TIMESTAMP_FIFO_SIZE 16
+	struct inv_chip_config_s chip_config;
+	struct inv_chip_info_s chip_info;
+	struct iio_trigger  *trig;
+	struct inv_flick_s flick;
+	struct inv_tap_s   tap;
+	struct inv_reg_map_s reg;
+	const struct inv_hw_s *hw;
+	enum   inv_devices chip_type;
+	spinlock_t time_stamp_lock;
+	struct i2c_client *client;
+	struct mpu_platform_data plat_data;
+	struct inv_mpu_slave *mpu_slave;
+	int (*set_power_state)(struct inv_mpu_iio_s *, bool on);
+	int (*switch_gyro_engine)(struct inv_mpu_iio_s *, bool on);
+	int (*switch_accl_engine)(struct inv_mpu_iio_s *, bool on);
+	int (*init_config)(struct iio_dev *indio_dev);
+	void (*setup_reg)(struct inv_reg_map_s *reg);
+	DECLARE_KFIFO(timestamps, long long, TIMESTAMP_FIFO_SIZE);
+	const short *compass_st_upper;
+	const short *compass_st_lower;
+	short irq;
+	int accel_bias[3];
+	int gyro_bias[3];
+	short raw_gyro[3];
+	short raw_accel[3];
+	short raw_compass[3];
+	unsigned char compass_scale;
+	unsigned char i2c_addr;
+	unsigned char compass_divider;
+	unsigned char compass_counter;
+	unsigned char sample_divider;
+	unsigned char fifo_divider;
+	unsigned char orient_data;
+	unsigned char display_orient_data;
+	unsigned char tap_data;
+	enum inv_channel_num num_channels;
+	void *sl_handle;
+	unsigned int irq_dur_ns;
+	long long last_isr_time;
+#ifdef CONFIG_INV_TESTING
+	unsigned long i2c_readcount;
+	unsigned long i2c_writecount;
+#endif
+};
+
+/* produces an unique identifier for each device based on the
+   combination of product version and product revision */
+struct prod_rev_map_t {
+	unsigned short mpl_product_key;
+	unsigned char silicon_rev;
+	unsigned short gyro_trim;
+	unsigned short accel_trim;
+};
+
+/**
+ *  struct inv_mpu_slave - MPU slave structure.
+ *  @suspend:		suspend operation.
+ *  @resume:		resume operation.
+ *  @setup:		setup chip. initialization.
+ *  @combine_data:	combine raw data into meaningful data.
+ *  @get_mode:		get current chip mode.
+ *  @set_lpf            set low pass filter.
+ *  @set_fs             set full scale
+ */
+struct inv_mpu_slave {
+	int (*suspend)(struct inv_mpu_iio_s *);
+	int (*resume)(struct inv_mpu_iio_s *);
+	int (*setup)(struct inv_mpu_iio_s *);
+	int (*combine_data)(unsigned char *in, short *out);
+	int (*get_mode)(struct inv_mpu_iio_s *);
+	int (*set_lpf)(struct inv_mpu_iio_s *, int rate);
+	int (*set_fs)(struct inv_mpu_iio_s *, int fs);
+};
+
+/* AKM definitions */
+#define REG_AKM_ID               0x00
+#define REG_AKM_STATUS           0x02
+#define REG_AKM_MEASURE_DATA     0x03
+#define REG_AKM_MODE             0x0A
+#define REG_AKM_ST_CTRL          0x0C
+#define REG_AKM_SENSITIVITY      0x10
+#define REG_AKM8963_CNTL1        0x0A
+
+#define DATA_AKM_ID              0x48
+#define DATA_AKM_MODE_PW_DN      0x00
+#define DATA_AKM_MODE_PW_SM      0x01
+#define DATA_AKM_MODE_PW_ST      0x08
+#define DATA_AKM_MODE_PW_FR      0x0F
+#define DATA_AKM_SELF_TEST       0x40
+#define DATA_AKM_DRDY            0x01
+#define DATA_AKM8963_BIT         0x10
+#define DATA_AKM_STAT_MASK       0x0C
+
+#define DATA_AKM8975_SCALE       9830
+#define DATA_AKM8972_SCALE       19661
+#define DATA_AKM8963_SCALE0      19661
+#define DATA_AKM8963_SCALE1      4915
+#define AKM8963_SCALE_SHIFT      4
+#define NUM_BYTES_COMPASS_SLAVE  8
+
+/*register and associated bit definition*/
+#define REG_YGOFFS_TC           0x1
+#define BIT_I2C_MST_VDDIO		0x80
+
+#define REG_XA_OFFS_L_TC        0x7
+#define REG_PRODUCT_ID          0xC
+#define REG_ST_GCT_X            0xD
+#define REG_SAMPLE_RATE_DIV     0x19
+#define REG_CONFIG              0x1A
+
+#define REG_GYRO_CONFIG         0x1B
+#define BITS_SELF_TEST_EN		0xE0
+
+#define REG_ACCEL_CONFIG	0x1C
+
+#define REG_FIFO_EN             0x23
+#define BIT_ACCEL_OUT			0x08
+#define BITS_GYRO_OUT			0x70
+
+
+#define REG_I2C_MST_CTRL        0x24
+#define BIT_WAIT_FOR_ES			0x40
+
+#define REG_I2C_SLV0_ADDR       0x25
+#define BIT_I2C_READ			0x80
+
+#define REG_I2C_SLV0_REG        0x26
+
+#define REG_I2C_SLV0_CTRL       0x27
+#define BIT_SLV_EN			0x80
+
+#define REG_I2C_SLV1_ADDR       0x28
+#define REG_I2C_SLV1_REG        0x29
+#define REG_I2C_SLV1_CTRL       0x2A
+#define REG_I2C_SLV4_CTRL       0x34
+
+#define REG_INT_PIN_CFG         0x37
+#define BIT_BYPASS_EN			0x2
+
+#define REG_INT_ENABLE          0x38
+#define BIT_DATA_RDY_EN			0x01
+#define BIT_DMP_INT_EN			0x02
+
+#define REG_DMP_INT_STATUS      0x39
+#define REG_INT_STATUS          0x3A
+#define REG_RAW_ACCEL           0x3B
+#define REG_TEMPERATURE         0x41
+#define REG_RAW_GYRO            0x43
+#define REG_EXT_SENS_DATA_00    0x49
+#define REG_I2C_SLV1_DO         0x64
+
+#define REG_I2C_MST_DELAY_CTRL  0x67
+#define BIT_SLV0_DLY_EN			0x01
+#define BIT_SLV1_DLY_EN			0x02
+
+#define REG_USER_CTRL           0x6A
+#define BIT_FIFO_RST			0x04
+#define BIT_DMP_RST			0x08
+#define BIT_I2C_MST_EN			0x20
+#define BIT_FIFO_EN			0x40
+#define BIT_DMP_EN			0x80
+
+#define REG_PWR_MGMT_1          0x6B
+#define BIT_H_RESET			0x80
+#define BIT_SLEEP			0x40
+#define BIT_CYCLE			0x20
+
+#define REG_PWR_MGMT_2          0x6C
+#define BIT_PWR_ACCL_STBY		0x38
+#define BIT_PWR_GYRO_STBY		0x07
+#define BIT_LPA_FREQ			0xC0
+
+#define REG_BANK_SEL            0x6D
+#define REG_MEM_START_ADDR      0x6E
+#define REG_MEM_RW              0x6F
+#define REG_PRGM_STRT_ADDRH     0x70
+#define REG_FIFO_COUNT_H        0x72
+#define REG_FIFO_R_W            0x74
+
+/* data definitions */
+#define DMP_START_ADDR           0x400
+#define DMP_MASK_TAP             0x3f
+#define DMP_MASK_DIS_ORIEN       0xC0
+#define DMP_DIS_ORIEN_SHIFT      6
+
+#define BYTES_FOR_DMP            16
+#define QUATERNION_BYTES         16
+#define BYTES_PER_SENSOR         6
+#define FIFO_COUNT_BYTE          2
+#define FIFO_THRESHOLD           500
+#define POWER_UP_TIME            100
+#define SENSOR_UP_TIME           30
+#define MPU_MEM_BANK_SIZE        256
+#define MPU6050_TEMP_OFFSET	 2462307L
+#define MPU6050_TEMP_SCALE       2977653L
+#define MPU_TEMP_SHIFT           16
+#define LPA_FREQ_SHIFT           6
+#define COMPASS_RATE_SCALE       10
+#define MAX_GYRO_FS_PARAM        3
+#define MAX_ACCL_FS_PARAM        3
+#define MAX_LPA_FREQ_PARAM       3
+#define THREE_AXIS               3
+#define GYRO_CONFIG_FSR_SHIFT    3
+#define ACCL_CONFIG_FSR_SHIFT    3
+#define GYRO_DPS_SCALE           250
+#define MEM_ADDR_PROD_REV        0x6
+#define SOFT_PROD_VER_BYTES      5
+#define CRC_FIRMWARE_SEED        0
+
+/* init parameters */
+#define INIT_FIFO_RATE           50
+#define INIT_DUR_TIME           ((1000 / INIT_FIFO_RATE) * 1000 * 1000)
+#define INIT_TAP_THRESHOLD       100
+#define INIT_TAP_TIME            100
+#define INIT_TAP_MIN_COUNT       2
+#define MPL_PROD_KEY(ver, rev) (ver * 100 + rev)
+#define NUM_OF_PROD_REVS (ARRAY_SIZE(prod_rev_map))
+/*---- MPU6050 Silicon Revisions ----*/
+#define MPU_SILICON_REV_A2                    1       /* MPU6050A2 Device */
+#define MPU_SILICON_REV_B1                    2       /* MPU6050B1 Device */
+
+#define BIT_PRFTCH_EN                         0x40
+#define BIT_CFG_USER_BANK                     0x20
+#define BITS_MEM_SEL                          0x1f
+
+#define TIME_STAMP_TOR                        5
+#define MAX_CATCH_UP                          5
+#define DEFAULT_ACCL_TRIM                     16384
+#define MAX_FIFO_RATE                         1000
+#define MIN_FIFO_RATE                         4
+#define ONE_K_HZ                              1000
+
+/* flick related defines */
+#define DATA_INT                              2097
+#define DATA_MSG_ON                           262144
+#define FLICK_INT_STATUS                      8
+
+/*tap related defines */
+#define INV_TAP                               0x08
+#define INV_NUM_TAP_AXES                      3
+
+#define INV_TAP_AXIS_X_POS                    0x20
+#define INV_TAP_AXIS_X_NEG                    0x10
+#define INV_TAP_AXIS_Y_POS                    0x08
+#define INV_TAP_AXIS_Y_NEG                    0x04
+#define INV_TAP_AXIS_Z_POS                    0x02
+#define INV_TAP_AXIS_Z_NEG                    0x01
+#define INV_TAP_ALL_DIRECTIONS                0x3f
+
+#define INV_TAP_AXIS_X                        0x1
+#define INV_TAP_AXIS_Y                        0x2
+#define INV_TAP_AXIS_Z                        0x4
+
+#define INV_TAP_AXIS_ALL                      \
+		(INV_TAP_AXIS_X            |   \
+		INV_TAP_AXIS_Y             |   \
+		INV_TAP_AXIS_Z)
+
+#define INT_SRC_TAP    0x01
+#define INT_SRC_ORIENT 0x02
+#define INT_SRC_DISPLAY_ORIENT  0x08
+#define INT_SRC_SHAKE           0x10
+
+
+/*orientation related */
+#define INV_X_UP                          0x01
+#define INV_X_DOWN                        0x02
+#define INV_Y_UP                          0x04
+#define INV_Y_DOWN                        0x08
+#define INV_Z_UP                          0x10
+#define INV_Z_DOWN                        0x20
+#define INV_ORIENTATION_ALL               0x3F
+
+#define INV_ORIENTATION_FLIP              0x40
+#define INV_X_AXIS_INDEX                  0x00
+#define INV_Y_AXIS_INDEX                  0x01
+#define INV_Z_AXIS_INDEX                  0x02
+
+#define INV_ELEMENT_1                     0x0001
+#define INV_ELEMENT_2                     0x0002
+#define INV_ELEMENT_3                     0x0004
+#define INV_ELEMENT_4                     0x0008
+#define INV_ELEMENT_5                     0x0010
+#define INV_ELEMENT_6                     0x0020
+#define INV_ELEMENT_7                     0x0040
+#define INV_ELEMENT_8                     0x0080
+#define INV_ALL                           0xFFFF
+#define INV_ELEMENT_MASK                  0x00FF
+#define INV_GYRO_ACC_MASK                 0x007E
+/* scan element definition */
+enum inv_mpu_scan {
+	INV_MPU_SCAN_QUAT_R = 0,
+	INV_MPU_SCAN_QUAT_X,
+	INV_MPU_SCAN_QUAT_Y,
+	INV_MPU_SCAN_QUAT_Z,
+	INV_MPU_SCAN_GYRO_X,
+	INV_MPU_SCAN_GYRO_Y,
+	INV_MPU_SCAN_GYRO_Z,
+	INV_MPU_SCAN_ACCL_X,
+	INV_MPU_SCAN_ACCL_Y,
+	INV_MPU_SCAN_ACCL_Z,
+	INV_MPU_SCAN_MAGN_X,
+	INV_MPU_SCAN_MAGN_Y,
+	INV_MPU_SCAN_MAGN_Z,
+	INV_MPU_SCAN_TIMESTAMP,
+};
+
+enum inv_filter_e {
+	INV_FILTER_256HZ_NOLPF2 = 0,
+	INV_FILTER_188HZ,
+	INV_FILTER_98HZ,
+	INV_FILTER_42HZ,
+	INV_FILTER_20HZ,
+	INV_FILTER_10HZ,
+	INV_FILTER_5HZ,
+	INV_FILTER_2100HZ_NOLPF,
+	NUM_FILTER
+};
+
+enum inv_slave_mode {
+	INV_MODE_SUSPEND,
+	INV_MODE_NORMAL,
+};
+
+/*==== MPU6050B1 MEMORY ====*/
+enum MPU_MEMORY_BANKS {
+	MEM_RAM_BANK_0 = 0,
+	MEM_RAM_BANK_1,
+	MEM_RAM_BANK_2,
+	MEM_RAM_BANK_3,
+	MEM_RAM_BANK_4,
+	MEM_RAM_BANK_5,
+	MEM_RAM_BANK_6,
+	MEM_RAM_BANK_7,
+	MEM_RAM_BANK_8,
+	MEM_RAM_BANK_9,
+	MEM_RAM_BANK_10,
+	MEM_RAM_BANK_11,
+	MPU_MEM_NUM_RAM_BANKS,
+	MPU_MEM_OTP_BANK_0 = 16
+};
+
+/* IIO attribute address */
+enum MPU_IIO_ATTR_ADDR {
+	ATTR_DMP_FLICK_LOWER,
+	ATTR_DMP_FLICK_UPPER,
+	ATTR_DMP_FLICK_COUNTER,
+	ATTR_DMP_FLICK_INT_ON,
+	ATTR_DMP_FLICK_AXIS,
+	ATTR_DMP_FLICK_MSG_ON,
+	ATTR_DMP_PEDOMETER_STEPS,
+	ATTR_DMP_PEDOMETER_TIME,
+	ATTR_DMP_TAP_THRESHOLD,
+	ATTR_DMP_TAP_MIN_COUNT,
+	ATTR_DMP_TAP_ON,
+	ATTR_DMP_TAP_TIME,
+	ATTR_DMP_ON,
+	ATTR_DMP_INT_ON,
+	ATTR_DMP_EVENT_INT_ON,
+	ATTR_DMP_OUTPUT_RATE,
+	ATTR_DMP_ORIENTATION_ON,
+	ATTR_DMP_QUATERNION_ON,
+	ATTR_DMP_DISPLAY_ORIENTATION_ON,
+	ATTR_LPA_MODE,
+	ATTR_LPA_FREQ,
+	ATTR_CLK_SRC,
+	ATTR_SELF_TEST,
+	ATTR_KEY,
+	ATTR_GYRO_MATRIX,
+	ATTR_ACCL_MATRIX,
+	ATTR_COMPASS_MATRIX,
+	ATTR_GYRO_ENABLE,
+	ATTR_ACCL_ENABLE,
+	ATTR_COMPASS_ENABLE,
+	ATTR_POWER_STATE,
+	ATTR_FIRMWARE_LOADED,
+#ifdef CONFIG_INV_TESTING
+	ATTR_I2C_COUNTERS,
+	ATTR_REG_WRITE,
+#endif
+};
+
+enum inv_accl_fs_e {
+	INV_FS_02G = 0,
+	INV_FS_04G,
+	INV_FS_08G,
+	INV_FS_16G,
+	NUM_ACCL_FSR
+};
+
+enum inv_fsr_e {
+	INV_FSR_250DPS = 0,
+	INV_FSR_500DPS,
+	INV_FSR_1000DPS,
+	INV_FSR_2000DPS,
+	NUM_FSR
+};
+
+enum inv_clock_sel_e {
+	INV_CLK_INTERNAL = 0,
+	INV_CLK_PLL,
+	NUM_CLK
+};
+
+ssize_t inv_dmp_firmware_write(struct file *fp, struct kobject *kobj,
+	struct bin_attribute *attr, char *buf, loff_t pos, size_t size);
+ssize_t inv_dmp_firmware_read(struct file *filp,
+				struct kobject *kobj,
+				struct bin_attribute *bin_attr,
+				char *buf, loff_t off, size_t count);
+
+int inv_mpu_configure_ring(struct iio_dev *indio_dev);
+int inv_mpu_probe_trigger(struct iio_dev *indio_dev);
+void inv_mpu_unconfigure_ring(struct iio_dev *indio_dev);
+void inv_mpu_remove_trigger(struct iio_dev *indio_dev);
+int inv_get_silicon_rev_mpu6050(struct inv_mpu_iio_s *st);
+int set_inv_enable(struct iio_dev *indio_dev, bool enable);
+int inv_set_interrupt_on_gesture_event(struct inv_mpu_iio_s *st, bool on);
+int inv_send_quaternion(struct inv_mpu_iio_s *st, bool on);
+int inv_set_display_orient_interrupt_dmp(struct inv_mpu_iio_s *st, bool on);
+int inv_enable_orientation_dmp(struct inv_mpu_iio_s *st, bool on);
+int inv_set_fifo_rate(struct inv_mpu_iio_s *st, unsigned short fifo_rate);
+unsigned short inv_dmp_get_address(unsigned short key);
+int inv_q30_mult(int a, int b);
+int inv_set_tap_threshold_dmp(struct inv_mpu_iio_s *st,
+				unsigned int axis, unsigned short threshold);
+int inv_set_min_taps_dmp(struct inv_mpu_iio_s *st, unsigned short min_taps);
+int  inv_set_tap_time_dmp(struct inv_mpu_iio_s *st, unsigned short time);
+int inv_enable_tap_dmp(struct inv_mpu_iio_s *st, bool on);
+int inv_i2c_read_base(struct inv_mpu_iio_s *st, unsigned short i2c_addr,
+	unsigned char reg, unsigned short length, unsigned char *data);
+int inv_i2c_single_write_base(struct inv_mpu_iio_s *st,
+	unsigned short i2c_addr, unsigned char reg, unsigned char data);
+int inv_do_test(struct inv_mpu_iio_s *st, int self_test_flag,
+		int *gyro_result, int *accl_result);
+int mpu_memory_write(struct i2c_adapter *i2c_adap,
+			    unsigned char mpu_addr,
+			    unsigned short mem_addr,
+			    unsigned int len, unsigned char const *data);
+int mpu_memory_read(struct i2c_adapter *i2c_adap,
+			   unsigned char mpu_addr,
+			   unsigned short mem_addr,
+			   unsigned int len, unsigned char *data);
+int inv_hw_self_test(struct inv_mpu_iio_s *st);
+
+#define mem_w(a, b, c) mpu_memory_write(st->sl_handle,\
+			st->i2c_addr, a, b, c)
+#define mem_w_key(key, b, c) mpu_memory_write(st->sl_handle,\
+			st->i2c_addr, inv_dmp_get_address(key), b, c)
+#define inv_i2c_read(st, reg, len, data) \
+	inv_i2c_read_base(st, st->i2c_addr, reg, len, data)
+#define inv_i2c_single_write(st, reg, data) \
+	inv_i2c_single_write_base(st, st->i2c_addr, reg, data)
+#define inv_secondary_read(reg, len, data) \
+	inv_i2c_read_base(st, st->plat_data.secondary_i2c_addr, reg, len, data)
+#define inv_secondary_write(reg, data) \
+	inv_i2c_single_write_base(st, st->plat_data.secondary_i2c_addr, \
+		reg, data)
+#endif  /* #ifndef _INV_MPU_IIO_H_ */
+
diff --git a/drivers/staging/iio/imu/mpu6050/inv_mpu_ring.c b/drivers/staging/iio/imu/mpu6050/inv_mpu_ring.c
new file mode 100644
index 0000000..528da5f
--- /dev/null
+++ b/drivers/staging/iio/imu/mpu6050/inv_mpu_ring.c
@@ -0,0 +1,563 @@
+/*
+* Copyright (C) 2012 Invensense, Inc.
+*
+* This software is licensed under the terms of the GNU General Public
+* License version 2, as published by the Free Software Foundation, and
+* may be copied, distributed, and modified under those terms.
+*
+* 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.
+*
+*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/sysfs.h>
+#include <linux/jiffies.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/kfifo.h>
+#include <linux/poll.h>
+#include <linux/miscdevice.h>
+#include "inv_mpu_iio.h"
+#include "../../iio.h"
+#include "../../kfifo_buf.h"
+#include "../../trigger_consumer.h"
+#include "../../sysfs.h"
+
+static void inv_scan_query(struct iio_dev *indio_dev)
+{
+	struct inv_mpu_iio_s  *st = iio_priv(indio_dev);
+	struct iio_buffer *ring = indio_dev->buffer;
+
+	if (iio_scan_mask_query(indio_dev, ring, INV_MPU_SCAN_GYRO_X) ||
+	    iio_scan_mask_query(indio_dev, ring, INV_MPU_SCAN_GYRO_Y) ||
+	    iio_scan_mask_query(indio_dev, ring, INV_MPU_SCAN_GYRO_Z))
+		st->chip_config.gyro_fifo_enable = 1;
+	else
+		st->chip_config.gyro_fifo_enable = 0;
+
+	if (iio_scan_mask_query(indio_dev, ring, INV_MPU_SCAN_ACCL_X) ||
+	    iio_scan_mask_query(indio_dev, ring, INV_MPU_SCAN_ACCL_Y) ||
+	    iio_scan_mask_query(indio_dev, ring, INV_MPU_SCAN_ACCL_Z))
+		st->chip_config.accl_fifo_enable = 1;
+	else
+		st->chip_config.accl_fifo_enable = 0;
+
+	if (iio_scan_mask_query(indio_dev, ring, INV_MPU_SCAN_MAGN_X) ||
+	    iio_scan_mask_query(indio_dev, ring, INV_MPU_SCAN_MAGN_Y) ||
+	    iio_scan_mask_query(indio_dev, ring, INV_MPU_SCAN_MAGN_Z))
+		st->chip_config.compass_fifo_enable = 1;
+	else
+		st->chip_config.compass_fifo_enable = 0;
+}
+
+/**
+ *  reset_fifo_itg() - Reset FIFO related registers.
+ *  @st:	Device driver instance.
+ */
+static int reset_fifo_itg(struct iio_dev *indio_dev)
+{
+	struct inv_reg_map_s *reg;
+	int result;
+	unsigned char val;
+	struct inv_mpu_iio_s  *st = iio_priv(indio_dev);
+	reg = &st->reg;
+
+	inv_scan_query(indio_dev);
+	/* disable interrupt */
+	result = inv_i2c_single_write(st, reg->int_enable, 0);
+	if (result) {
+		pr_err("int_enable write failed\n");
+		return result;
+	}
+	/* disable the sensor output to FIFO */
+	result = inv_i2c_single_write(st, reg->fifo_en, 0);
+	if (result)
+		goto reset_fifo_fail;
+	/* disable fifo reading */
+	result = inv_i2c_single_write(st, reg->user_ctrl, 0);
+	if (result)
+		goto reset_fifo_fail;
+
+	if (st->chip_config.dmp_on) {
+		val = (BIT_FIFO_RST | BIT_DMP_RST);
+		result = inv_i2c_single_write(st, reg->user_ctrl, val);
+		if (result)
+			goto reset_fifo_fail;
+		st->last_isr_time = iio_get_time_ns();
+		if (st->chip_config.dmp_int_on) {
+			result = inv_i2c_single_write(st, reg->int_enable,
+							BIT_DMP_INT_EN);
+			if (result)
+				return result;
+		}
+		val = (BIT_DMP_EN | BIT_FIFO_EN);
+		if (st->chip_config.compass_enable)
+			val |= BIT_I2C_MST_EN;
+		result = inv_i2c_single_write(st, reg->user_ctrl, val);
+		if (result)
+			goto reset_fifo_fail;
+	} else {
+		/* reset FIFO and possibly reset I2C*/
+		val = BIT_FIFO_RST;
+		result = inv_i2c_single_write(st, reg->user_ctrl, val);
+		if (result)
+			goto reset_fifo_fail;
+		st->last_isr_time = iio_get_time_ns();
+		/* enable interrupt */
+		if (st->chip_config.accl_fifo_enable ||
+		    st->chip_config.gyro_fifo_enable ||
+		    st->chip_config.compass_enable) {
+			result = inv_i2c_single_write(st, reg->int_enable,
+						BIT_DATA_RDY_EN);
+			if (result)
+				return result;
+		}
+		/* enable FIFO reading and I2C master interface*/
+		val = BIT_FIFO_EN;
+		if (st->chip_config.compass_enable)
+			val |= BIT_I2C_MST_EN;
+		result = inv_i2c_single_write(st, reg->user_ctrl, val);
+		if (result)
+			goto reset_fifo_fail;
+		/* enable sensor output to FIFO */
+		val = 0;
+		if (st->chip_config.gyro_fifo_enable)
+			val |= BITS_GYRO_OUT;
+		if (st->chip_config.accl_fifo_enable)
+			val |= BIT_ACCEL_OUT;
+		result = inv_i2c_single_write(st, reg->fifo_en, val);
+		if (result)
+			goto reset_fifo_fail;
+	}
+	return 0;
+reset_fifo_fail:
+	if (st->chip_config.dmp_on)
+		val = BIT_DMP_INT_EN;
+	else
+		val = BIT_DATA_RDY_EN;
+	inv_i2c_single_write(st, reg->int_enable, val);
+	pr_err("reset fifo failed\n");
+	return result;
+}
+
+/**
+ *  inv_reset_fifo() - Reset FIFO related registers.
+ *  @st:	Device driver instance.
+ */
+static int inv_reset_fifo(struct iio_dev *indio_dev)
+{
+	return reset_fifo_itg(indio_dev);
+}
+
+/**
+ *  set_inv_enable() - Reset FIFO related registers.
+ *			This also powers on the chip if needed.
+ *  @st:	Device driver instance.
+ *  @fifo_enable: enable/disable
+ */
+int set_inv_enable(struct iio_dev *indio_dev,
+			bool enable) {
+	struct inv_mpu_iio_s *st = iio_priv(indio_dev);
+	struct inv_reg_map_s *reg;
+	int result;
+
+	if (st->chip_config.is_asleep)
+		return -EINVAL;
+	reg = &st->reg;
+	if (enable) {
+		result = inv_reset_fifo(indio_dev);
+		if (result)
+			return result;
+	} else {
+		result = inv_i2c_single_write(st, reg->fifo_en, 0);
+		if (result)
+			return result;
+		/* disable fifo reading */
+		result = inv_i2c_single_write(st, reg->int_enable, 0);
+		if (result)
+			return result;
+		result = inv_i2c_single_write(st, reg->user_ctrl, 0);
+		if (result)
+			return result;
+	}
+	st->chip_config.enable = !!enable;
+
+	return 0;
+}
+
+/**
+ *  inv_clear_kfifo() - clear time stamp fifo
+ *  @st:	Device driver instance.
+ */
+void inv_clear_kfifo(struct inv_mpu_iio_s *st)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&st->time_stamp_lock, flags);
+	kfifo_reset(&st->timestamps);
+	spin_unlock_irqrestore(&st->time_stamp_lock, flags);
+}
+
+/**
+ *  inv_irq_handler() - Cache a timestamp at each data ready interrupt.
+ */
+static irqreturn_t inv_irq_handler(int irq, void *dev_id)
+{
+	struct inv_mpu_iio_s *st;
+	long long timestamp;
+	int catch_up;
+	unsigned int time_since_last_irq;
+
+	st = (struct inv_mpu_iio_s *)dev_id;
+	timestamp = iio_get_time_ns();
+	time_since_last_irq = (unsigned int)(timestamp
+		- st->last_isr_time);
+	spin_lock(&st->time_stamp_lock);
+	catch_up = 0;
+	while ((time_since_last_irq > st->irq_dur_ns * 2) &&
+	       (catch_up < MAX_CATCH_UP) &&
+	       (!st->chip_config.lpa_mode) &&
+	       (!st->chip_config.dmp_on)) {
+		st->last_isr_time += st->irq_dur_ns;
+		kfifo_in(&st->timestamps,
+			 &st->last_isr_time, 1);
+		time_since_last_irq = ((unsigned int)(timestamp
+			- st->last_isr_time));
+		catch_up++;
+	}
+	kfifo_in(&st->timestamps, &timestamp, 1);
+	st->last_isr_time = timestamp;
+	spin_unlock(&st->time_stamp_lock);
+
+	return IRQ_WAKE_THREAD;
+}
+
+static int put_scan_to_buf(struct iio_dev *indio_dev, unsigned char *d,
+				short *s, int scan_index, int d_ind) {
+	struct iio_buffer *ring = indio_dev->buffer;
+	int st;
+	int i;
+	for (i = 0; i < 3; i++) {
+		st = iio_scan_mask_query(indio_dev, ring, scan_index + i);
+		if (st) {
+			memcpy(&d[d_ind], &s[i], sizeof(s[i]));
+			d_ind += sizeof(s[i]);
+		}
+	}
+	return d_ind;
+}
+
+static int put_scan_to_buf_q(struct iio_dev *indio_dev, unsigned char *d,
+				int *s, int scan_index, int d_ind) {
+	struct iio_buffer *ring = indio_dev->buffer;
+	int st;
+	int i;
+	for (i = 0; i < 4; i++) {
+		st = iio_scan_mask_query(indio_dev, ring, scan_index + i);
+		if (st) {
+			memcpy(&d[d_ind], &s[i], sizeof(s[i]));
+			d_ind += sizeof(s[i]);
+		}
+	}
+	return d_ind;
+}
+
+static int inv_report_gyro_accl_compass(struct iio_dev *indio_dev,
+					unsigned char *data, s64 t)
+{
+	struct inv_mpu_iio_s *st = iio_priv(indio_dev);
+	struct iio_buffer *ring = indio_dev->buffer;
+	short g[THREE_AXIS], a[THREE_AXIS], c[THREE_AXIS];
+	int q[4];
+	int result, ind, d_ind;
+	s64 buf[8];
+	unsigned int word;
+	unsigned char d[8];
+	unsigned char *tmp;
+	int source;
+	struct inv_chip_config_s *conf;
+
+	conf = &st->chip_config;
+	ind = 0;
+	if (conf->quaternion_on & conf->dmp_on) {
+		q[0] = be32_to_cpup((__be32 *)(&data[ind]));
+		q[1] = be32_to_cpup((__be32 *)(&data[ind + 4]));
+		q[2] = be32_to_cpup((__be32 *)(&data[ind + 8]));
+		q[3] = be32_to_cpup((__be32 *)(&data[ind + 12]));
+		ind += QUATERNION_BYTES;
+	}
+	if (conf->accl_fifo_enable | conf->dmp_on) {
+		a[0] = be16_to_cpup((__be16 *)(&data[ind]));
+		a[1] = be16_to_cpup((__be16 *)(&data[ind + 2]));
+		a[2] = be16_to_cpup((__be16 *)(&data[ind + 4]));
+
+		a[0] *= st->chip_info.multi;
+		a[1] *= st->chip_info.multi;
+		a[2] *= st->chip_info.multi;
+		st->raw_accel[0] = a[0];
+		st->raw_accel[1] = a[1];
+		st->raw_accel[2] = a[2];
+		ind += BYTES_PER_SENSOR;
+	}
+	if (conf->gyro_fifo_enable | conf->dmp_on) {
+		g[0] = be16_to_cpup((__be16 *)(&data[ind]));
+		g[1] = be16_to_cpup((__be16 *)(&data[ind + 2]));
+		g[2] = be16_to_cpup((__be16 *)(&data[ind + 4]));
+
+		st->raw_gyro[0] = g[0];
+		st->raw_gyro[1] = g[1];
+		st->raw_gyro[2] = g[2];
+		ind += BYTES_PER_SENSOR;
+	}
+	if (conf->dmp_on) {
+		word = (unsigned int)(be32_to_cpup((unsigned int *)&data[ind]));
+		source = ((word >> 16) & 0xff);
+		if (source) {
+			st->tap_data = (DMP_MASK_TAP & (word & 0xff));
+			st->orient_data = ((word >> 8) & 0xff);
+			st->display_orient_data =
+			((DMP_MASK_DIS_ORIEN & (word & 0xff)) >>
+			  DMP_DIS_ORIEN_SHIFT);
+		}
+
+		/* report tap information */
+		if (source & INT_SRC_TAP)
+			sysfs_notify(&indio_dev->dev.kobj, NULL, "event_tap");
+		/* report orientation information */
+		if (source & INT_SRC_ORIENT)
+			sysfs_notify(&indio_dev->dev.kobj, NULL,
+				     "event_orientation");
+		/* report orientation information */
+		if (source & INT_SRC_DISPLAY_ORIENT)
+			sysfs_notify(&indio_dev->dev.kobj, NULL,
+				     "event_display_orientation");
+	}
+	/*divider and counter is used to decrease the speed of read in
+		high frequency sample rate*/
+	if (conf->compass_fifo_enable) {
+		c[0] = 0;
+		c[1] = 0;
+		c[2] = 0;
+		if (st->compass_divider == st->compass_counter) {
+			/*read from external sensor data register */
+			result = inv_i2c_read(st, REG_EXT_SENS_DATA_00,
+					      NUM_BYTES_COMPASS_SLAVE, d);
+			/* d[7] is status 2 register */
+			/*for AKM8975, bit 2 and 3 should be all be zero*/
+			/* for AMK8963, bit 3 should be zero*/
+			if ((DATA_AKM_DRDY == d[0]) &&
+			    (0 == (d[7] & DATA_AKM_STAT_MASK)) &&
+			    (!result)) {
+				unsigned char *sens;
+				sens = st->chip_info.compass_sens;
+				c[0] = (short)((d[2] << 8) | d[1]);
+				c[1] = (short)((d[4] << 8) | d[3]);
+				c[2] = (short)((d[6] << 8) | d[5]);
+				c[0] = (short)(((int)c[0] *
+					       (sens[0] + 128)) >> 8);
+				c[1] = (short)(((int)c[1] *
+					       (sens[1] + 128)) >> 8);
+				c[2] = (short)(((int)c[2] *
+					       (sens[2] + 128)) >> 8);
+				st->raw_compass[0] = c[0];
+				st->raw_compass[1] = c[1];
+				st->raw_compass[2] = c[2];
+			}
+			st->compass_counter = 0;
+		} else if (st->compass_divider != 0) {
+			st->compass_counter++;
+		}
+	}
+
+	tmp = (unsigned char *)buf;
+	d_ind = 0;
+	if (conf->quaternion_on & conf->dmp_on)
+		d_ind = put_scan_to_buf_q(indio_dev, tmp, q,
+				INV_MPU_SCAN_QUAT_R, d_ind);
+	if (conf->gyro_fifo_enable)
+		d_ind = put_scan_to_buf(indio_dev, tmp, g,
+				INV_MPU_SCAN_GYRO_X, d_ind);
+	if (conf->accl_fifo_enable)
+		d_ind = put_scan_to_buf(indio_dev, tmp, a,
+				INV_MPU_SCAN_ACCL_X, d_ind);
+	if (conf->compass_fifo_enable)
+		d_ind = put_scan_to_buf(indio_dev, tmp, c,
+				INV_MPU_SCAN_MAGN_X, d_ind);
+	if (ring->scan_timestamp)
+		buf[(d_ind + 7) / 8] = t;
+	ring->access->store_to(indio_dev->buffer, (u8 *)buf, t);
+
+	return 0;
+}
+
+/**
+ *  inv_read_fifo() - Transfer data from FIFO to ring buffer.
+ */
+irqreturn_t inv_read_fifo(int irq, void *dev_id)
+{
+
+	struct inv_mpu_iio_s *st = (struct inv_mpu_iio_s *)dev_id;
+	struct iio_dev *indio_dev = iio_priv_to_dev(st);
+	size_t bytes_per_datum;
+	int result;
+	unsigned char data[BYTES_FOR_DMP + QUATERNION_BYTES];
+	unsigned short fifo_count;
+	unsigned int copied;
+	s64 timestamp;
+	struct inv_reg_map_s *reg;
+	s64 buf[8];
+	unsigned char *tmp;
+	reg = &st->reg;
+	if (!(st->chip_config.accl_fifo_enable |
+		st->chip_config.gyro_fifo_enable |
+		st->chip_config.dmp_on |
+		st->chip_config.compass_fifo_enable))
+		goto end_session;
+	if (st->chip_config.dmp_on && st->chip_config.flick_int_on) {
+		/*dmp interrupt status */
+		inv_i2c_read(st, REG_DMP_INT_STATUS, 1, data);
+		if (data[0] & FLICK_INT_STATUS)
+			sysfs_notify(&indio_dev->dev.kobj, NULL, "event_flick");
+	}
+	if (st->chip_config.lpa_mode) {
+		result = inv_i2c_read(st, reg->raw_accl,
+				      BYTES_PER_SENSOR, data);
+		if (result)
+			goto end_session;
+		inv_report_gyro_accl_compass(indio_dev, data,
+					     iio_get_time_ns());
+		goto end_session;
+	}
+
+	if (st->chip_config.dmp_on)
+		if (st->chip_config.quaternion_on)
+			bytes_per_datum = BYTES_FOR_DMP + QUATERNION_BYTES;
+		else
+			bytes_per_datum = BYTES_FOR_DMP;
+	else
+		bytes_per_datum = (st->chip_config.accl_fifo_enable +
+		st->chip_config.gyro_fifo_enable)*BYTES_PER_SENSOR;
+	fifo_count = 0;
+	if (bytes_per_datum != 0) {
+		result = inv_i2c_read(st, reg->fifo_count_h,
+				FIFO_COUNT_BYTE, data);
+		if (result)
+			goto end_session;
+		fifo_count = be16_to_cpup((__be16 *)(&data[0]));
+		if (fifo_count < bytes_per_datum)
+			goto end_session;
+		/* fifo count can't be odd number */
+		if (fifo_count & 1)
+			goto flush_fifo;
+		if (fifo_count >  FIFO_THRESHOLD)
+			goto flush_fifo;
+		/* Timestamp mismatch. */
+		if (kfifo_len(&st->timestamps) <
+			fifo_count / bytes_per_datum)
+			goto flush_fifo;
+		if (kfifo_len(&st->timestamps) >
+			fifo_count / bytes_per_datum + TIME_STAMP_TOR) {
+			if (st->chip_config.dmp_on) {
+				result = kfifo_to_user(&st->timestamps,
+				&timestamp, sizeof(timestamp), &copied);
+				if (result)
+					goto flush_fifo;
+			} else {
+				goto flush_fifo;
+			}
+		}
+	} else {
+		result = kfifo_to_user(&st->timestamps,
+			&timestamp, sizeof(timestamp), &copied);
+		if (result)
+			goto flush_fifo;
+	}
+	tmp = (char *)buf;
+	while ((bytes_per_datum != 0) && (fifo_count >= bytes_per_datum)) {
+		result = inv_i2c_read(st, reg->fifo_r_w, bytes_per_datum,
+			data);
+		if (result)
+			goto flush_fifo;
+
+		result = kfifo_to_user(&st->timestamps,
+			&timestamp, sizeof(timestamp), &copied);
+		if (result)
+			goto flush_fifo;
+		inv_report_gyro_accl_compass(indio_dev, data, timestamp);
+		fifo_count -= bytes_per_datum;
+	}
+	if (bytes_per_datum == 0)
+		inv_report_gyro_accl_compass(indio_dev, data, timestamp);
+end_session:
+	return IRQ_HANDLED;
+flush_fifo:
+	/* Flush HW and SW FIFOs. */
+	inv_reset_fifo(indio_dev);
+	inv_clear_kfifo(st);
+	return IRQ_HANDLED;
+}
+
+void inv_mpu_unconfigure_ring(struct iio_dev *indio_dev)
+{
+	struct inv_mpu_iio_s *st = iio_priv(indio_dev);
+	free_irq(st->client->irq, st);
+	iio_kfifo_free(indio_dev->buffer);
+};
+
+int inv_postenable(struct iio_dev *indio_dev)
+{
+	return set_inv_enable(indio_dev, true);
+
+}
+
+int inv_predisable(struct iio_dev *indio_dev)
+{
+	return set_inv_enable(indio_dev, false);
+}
+
+static const struct iio_buffer_setup_ops inv_mpu_ring_setup_ops = {
+	.preenable = &iio_sw_buffer_preenable,
+	.postenable = &inv_postenable,
+	.predisable = &inv_predisable,
+};
+
+int inv_mpu_configure_ring(struct iio_dev *indio_dev)
+{
+	int ret;
+	struct inv_mpu_iio_s *st = iio_priv(indio_dev);
+	struct iio_buffer *ring;
+
+	ring = iio_kfifo_allocate(indio_dev);
+	if (!ring)
+		return -ENOMEM;
+	indio_dev->buffer = ring;
+	/* setup ring buffer */
+	ring->scan_timestamp = true;
+	indio_dev->setup_ops = &inv_mpu_ring_setup_ops;
+	/*scan count double count timestamp. should subtract 1. but
+	number of channels still includes timestamp*/
+	ret = request_threaded_irq(st->client->irq, inv_irq_handler,
+				   inv_read_fifo,
+				   IRQF_TRIGGER_RISING | IRQF_SHARED,
+				   "inv_irq", st);
+	if (ret)
+		goto error_iio_sw_rb_free;
+
+	return 0;
+error_iio_sw_rb_free:
+	iio_kfifo_free(indio_dev->buffer);
+	return ret;
+}
+/**
+ *  @}
+ */
+
diff --git a/drivers/staging/iio/imu/mpu6050/mpu.h b/drivers/staging/iio/imu/mpu6050/mpu.h
new file mode 100644
index 0000000..5105fb2
--- /dev/null
+++ b/drivers/staging/iio/imu/mpu6050/mpu.h
@@ -0,0 +1,107 @@
+/*
+* Copyright (C) 2012 Invensense, Inc.
+*
+* This software is licensed under the terms of the GNU General Public
+* License version 2, as published by the Free Software Foundation, and
+* may be copied, distributed, and modified under those terms.
+*
+* 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.
+*
+*/
+
+/**
+ *  @addtogroup  DRIVERS
+ *  @brief       Hardware drivers.
+ *
+ *  @{
+ *      @file    mpu.h
+ *      @brief   mpu definition
+ */
+
+#ifndef __MPU_H_
+#define __MPU_H_
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#endif
+
+enum secondary_slave_type {
+	SECONDARY_SLAVE_TYPE_NONE,
+	SECONDARY_SLAVE_TYPE_ACCEL,
+	SECONDARY_SLAVE_TYPE_COMPASS,
+	SECONDARY_SLAVE_TYPE_PRESSURE,
+
+	SECONDARY_SLAVE_TYPE_TYPES
+};
+
+enum ext_slave_id {
+	ID_INVALID = 0,
+	GYRO_ID_MPU3050,
+	GYRO_ID_MPU6050A2,
+	GYRO_ID_MPU6050B1,
+	GYRO_ID_MPU6050B1_NO_ACCEL,
+	GYRO_ID_ITG3500,
+
+	ACCEL_ID_LIS331,
+	ACCEL_ID_LSM303DLX,
+	ACCEL_ID_LIS3DH,
+	ACCEL_ID_KXSD9,
+	ACCEL_ID_KXTF9,
+	ACCEL_ID_BMA150,
+	ACCEL_ID_BMA222,
+	ACCEL_ID_BMA250,
+	ACCEL_ID_ADXL34X,
+	ACCEL_ID_MMA8450,
+	ACCEL_ID_MMA845X,
+	ACCEL_ID_MPU6050,
+
+	COMPASS_ID_AK8963,
+	COMPASS_ID_AK8975,
+	COMPASS_ID_AK8972,
+	COMPASS_ID_AMI30X,
+	COMPASS_ID_AMI306,
+	COMPASS_ID_YAS529,
+	COMPASS_ID_YAS530,
+	COMPASS_ID_HMC5883,
+	COMPASS_ID_LSM303DLH,
+	COMPASS_ID_LSM303DLM,
+	COMPASS_ID_MMC314X,
+	COMPASS_ID_HSCDTD002B,
+	COMPASS_ID_HSCDTD004A,
+
+	PRESSURE_ID_BMA085,
+};
+
+#define INV_PROD_KEY(ver, rev) (ver * 100 + rev)
+/**
+ * struct mpu_platform_data - Platform data for the mpu driver
+ * @int_config:		Bits [7:3] of the int config register.
+ * @level_shifter:	0: VLogic, 1: VDD
+ * @orientation:	Orientation matrix of the gyroscope
+ * @sec_slave_type:     secondary slave device type, can be compass, accel, etc
+ * @sec_slave_id:       id of the secondary slave device
+ * @secondary_i2c_address: secondary device's i2c address
+ * @secondary_orientation: secondary device's orientation matrix
+ *
+ * Contains platform specific information on how to configure the MPU3050 to
+ * work on this platform.  The orientation matricies are 3x3 rotation matricies
+ * that are applied to the data to rotate from the mounting orientation to the
+ * platform orientation.  The values must be one of 0, 1, or -1 and each row and
+ * column should have exactly 1 non-zero value.
+ */
+struct mpu_platform_data {
+	__u8 int_config;
+	__u8 level_shifter;
+	__s8 orientation[9];
+	enum secondary_slave_type sec_slave_type;
+	enum ext_slave_id sec_slave_id;
+	__u16 secondary_i2c_addr;
+	__s8 secondary_orientation[9];
+	__u8 key[16];
+};
+
+#endif	/* __MPU_H_ */
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2012-07-07  8:51 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-06-28 18:30 [PATCH 1/4] IIO: Invensense MPU6050/MPU9150 driver submit Ge Gao
2012-07-06  9:07 ` Jonathan Cameron
2012-07-06 17:40   ` Ge Gao
2012-07-07  8:51     ` Jonathan Cameron

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).