Index: linux-2.6.35/drivers/misc/mpu3050/mlos.h
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.35/drivers/misc/mpu3050/mlos.h    2010-12-22
14:09:28.000000000 +0800
@@ -0,0 +1,73 @@
+/*
+ $License:
+    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
+
+    This program is free software; you can redistribute it and/or
modify
+    it under the terms of the GNU General Public License as published
by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    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.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see
<http://www.gnu.org/licenses/>.
+  $
+ */
+
+#ifndef _MLOS_H
+#define _MLOS_H
+
+#ifndef __KERNEL__
+#include <stdio.h>
+#endif
+
+#include "mltypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+       /* ------------ */
+       /* - Defines. - */
+       /* ------------ */
+
+       /* - MLOSCreateFile defines. - */
+
+#define MLOS_GENERIC_READ         ((unsigned int)0x80000000)
+#define MLOS_GENERIC_WRITE        ((unsigned int)0x40000000)
+#define MLOS_FILE_SHARE_READ      ((unsigned int)0x00000001)
+#define MLOS_FILE_SHARE_WRITE     ((unsigned int)0x00000002)
+#define MLOS_OPEN_EXISTING        ((unsigned int)0x00000003)
+
+       /* ---------- */
+       /* - Enums. - */
+       /* ---------- */
+
+       /* --------------- */
+       /* - Structures. - */
+       /* --------------- */
+
+       /* --------------------- */
+       /* - Function p-types. - */
+       /* --------------------- */
+
+       void *MLOSMalloc(unsigned int numBytes);
+       tMLError MLOSFree(void *ptr);
+       tMLError MLOSCreateMutex(HANDLE *mutex);
+       tMLError MLOSLockMutex(HANDLE mutex);
+       tMLError MLOSUnlockMutex(HANDLE mutex);
+       FILE *MLOSFOpen(char *filename);
+       void MLOSFClose(FILE *fp);
+
+       tMLError MLOSDestroyMutex(HANDLE handle);
+
+       void MLOSSleep(int mSecs);
+       unsigned long MLOSGetTickCount(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif                         /* _MLOS_H */
Index: linux-2.6.35/drivers/misc/mpu3050/mpu-i2c.h
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.35/drivers/misc/mpu3050/mpu-i2c.h 2010-12-22
14:09:28.000000000 +0800
@@ -0,0 +1,58 @@
+/*
+ $License:
+    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
+
+    This program is free software; you can redistribute it and/or
modify
+    it under the terms of the GNU General Public License as published
by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    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.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see
<http://www.gnu.org/licenses/>.
+  $
+ */
+/**
+ * @defgroup
+ * @brief
+ *
+ * @{
+ * @file     mpu-i2c.c
+ * @brief
+ *
+ *
+ */
+
+#ifndef __MPU_I2C_H__
+#define __MPU_I2C_H__
+
+#include <linux/i2c.h>
+
+int sensor_i2c_write(struct i2c_adapter *i2c_adap,
+                    unsigned char address,
+                    unsigned int len, unsigned char const *data);
+
+int sensor_i2c_write_register(struct i2c_adapter *i2c_adap,
+                             unsigned char address,
+                             unsigned char reg, unsigned char value);
+
+int sensor_i2c_read(struct i2c_adapter *i2c_adap,
+                   unsigned char address,
+                   unsigned char reg,
+                   unsigned int len, unsigned char *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 mpu_memory_write(struct i2c_adapter *i2c_adap,
+                    unsigned char mpu_addr,
+                    unsigned short mem_addr,
+                    unsigned int len, unsigned char const *data);
+
+#endif /* __MPU_I2C_H__ */
Index: linux-2.6.35/drivers/misc/mpu3050/mpuirq.h
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.35/drivers/misc/mpu3050/mpuirq.h  2010-12-22
14:09:28.000000000 +0800
@@ -0,0 +1,50 @@
+/*
+ $License:
+    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
+
+    This program is free software; you can redistribute it and/or
modify
+    it under the terms of the GNU General Public License as published
by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    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.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see
<http://www.gnu.org/licenses/>.
+  $
+ */
+
+#ifndef __MPUIRQ__
+#define __MPUIRQ__
+
+#ifdef __KERNEL__
+#include <linux/i2c-dev.h>
+#endif
+
+#define MPUIRQ_ENABLE_DEBUG          (1)
+#define MPUIRQ_GET_INTERRUPT_CNT     (2)
+#define MPUIRQ_GET_IRQ_TIME          (3)
+#define MPUIRQ_GET_LED_VALUE         (4)
+#define MPUIRQ_SET_TIMEOUT           (5)
+#define MPUIRQ_SET_ACCEL_INFO        (6)
+#define MPUIRQ_SET_FREQUENCY_DIVIDER (7)
+
+struct mpuirq_data {
+       int interruptcount;
+       unsigned long long irqtime;
+       int data_type;
+       int data_size;
+       void *data;
+};
+
+#ifdef __KERNEL__
+
+void mpuirq_exit(void);
+int mpuirq_init(struct i2c_client *mpu_client);
+
+#endif
+
+#endif
Index: linux-2.6.35/drivers/misc/mpu3050/compass/hmc5883.c
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.35/drivers/misc/mpu3050/compass/hmc5883.c 2010-12-22
14:09:28.000000000 +0800
@@ -0,0 +1,232 @@
+/*
+ $License:
+    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
+
+    This program is free software; you can redistribute it and/or
modify
+    it under the terms of the GNU General Public License as published
by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    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.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see
<http://www.gnu.org/licenses/>.
+  $
+ */
+
+/**
+ *  @brief      Provides the interface to setup and handle a compass
+ *              connected to the primary I2C interface of the
gyroscope.
+ *
+ *  @{
+ *      @file   hmc5883.c
+ *      @brief  Magnetometer setup and handling methods for honeywell
hmc5883
+ *              compass.
+ */
+
+/* ------------------ */
+/* - Include Files. - */
+/* ------------------ */
+
+#ifdef __KERNEL__
+#include <linux/module.h>
+#endif
+
+#include "mpu.h"
+#include "mlsl.h"
+#include "mlos.h"
+
+#include <log.h>
+#undef MPL_LOG_TAG
+#define MPL_LOG_TAG "MPL-compass"
+
+/*-----HONEYWELL HMC5883 Registers ------*/
+enum HMC_REG {
+       HMC_REG_CONF_A = 0x0,
+       HMC_REG_CONF_B = 0x1,
+       HMC_REG_MODE = 0x2,
+       HMC_REG_X_M = 0x3,
+       HMC_REG_X_L = 0x4,
+       HMC_REG_Z_M = 0x5,
+       HMC_REG_Z_L = 0x6,
+       HMC_REG_Y_M = 0x7,
+       HMC_REG_Y_L = 0x8,
+       HMC_REG_STATUS = 0x9,
+       HMC_REG_ID_A = 0xA,
+       HMC_REG_ID_B = 0xB,
+       HMC_REG_ID_C = 0xC
+};
+
+enum HMC_CONF_A {
+       HMC_CONF_A_DRATE_MASK = 0x1C,
+       HMC_CONF_A_DRATE_0_75 = 0x00,
+       HMC_CONF_A_DRATE_1_5 = 0x04,
+       HMC_CONF_A_DRATE_3 = 0x08,
+       HMC_CONF_A_DRATE_7_5 = 0x0C,
+       HMC_CONF_A_DRATE_15 = 0x10,
+       HMC_CONF_A_DRATE_30 = 0x14,
+       HMC_CONF_A_DRATE_75 = 0x18,
+       HMC_CONF_A_MEAS_MASK = 0x3,
+       HMC_CONF_A_MEAS_NORM = 0x0,
+       HMC_CONF_A_MEAS_POS = 0x1,
+       HMC_CONF_A_MEAS_NEG = 0x2
+};
+
+enum HMC_CONF_B{
+       HMC_CONF_B_GAIN_MASK = 0xE0,
+       HMC_CONF_B_GAIN_0_9 = 0x00,
+       HMC_CONF_B_GAIN_1_2 = 0x20,
+       HMC_CONF_B_GAIN_1_9 = 0x40,
+       HMC_CONF_B_GAIN_2_5 = 0x60,
+       HMC_CONF_B_GAIN_4_0 = 0x80,
+       HMC_CONF_B_GAIN_4_6 = 0xA0,
+       HMC_CONF_B_GAIN_5_5 = 0xC0,
+       HMC_CONF_B_GAIN_7_9 = 0xE0
+};
+
+enum HMC_MODE {
+       HMC_MODE_MASK = 0x3,
+       HMC_MODE_CONT = 0x0,
+       HMC_MODE_SINGLE = 0x1,
+       HMC_MODE_IDLE = 0x2,
+       HMC_MODE_SLEEP = 0x3
+};
+
+/* --------------------- */
+/* -    Variables.     - */
+/* --------------------- */
+
+/*****************************************
+    Accelerometer Initialization Functions
+*****************************************/
+
+int hmc5883_suspend(void *mlsl_handle,
+                   struct ext_slave_descr *slave,
+                   struct ext_slave_platform_data *pdata)
+{
+       int result = ML_SUCCESS;
+
+       result =
+           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                 HMC_REG_MODE, HMC_MODE_SLEEP);
+       ERROR_CHECK(result);
+       MLOSSleep(3);
+
+       return result;
+}
+
+int hmc5883_resume(void *mlsl_handle,
+                  struct ext_slave_descr *slave,
+                  struct ext_slave_platform_data *pdata)
+{
+       int result = ML_SUCCESS;
+
+       /* Use single measurement mode. Start at sleep state. */
+       result =
+           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                 HMC_REG_MODE, HMC_MODE_SLEEP);
+       ERROR_CHECK(result);
+       /* Config normal measurement */
+       result =
+           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                 HMC_REG_CONF_A, 0);
+       ERROR_CHECK(result);
+       /* Adjust gain to 307 LSB/Gauss */
+       result =
+           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                 HMC_REG_CONF_B, HMC_CONF_B_GAIN_5_5);
+       ERROR_CHECK(result);
+
+       return result;
+}
+
+int hmc5883_read(void *mlsl_handle,
+                struct ext_slave_descr *slave,
+                struct ext_slave_platform_data *pdata,
+                unsigned char *data)
+{
+       unsigned char stat;
+       tMLError result = ML_SUCCESS;
+       unsigned char tmp;
+       short zAxisfixed;
+
+       /* Read status reg. to check if data is ready */
+       result =
+           MLSLSerialRead(mlsl_handle, pdata->address, HMC_REG_STATUS,
1,
+                          &stat);
+       ERROR_CHECK(result);
+       if (stat & 0x01) {
+               result =
+                   MLSLSerialRead(mlsl_handle, pdata->address,
+                                  HMC_REG_X_M, 6, (unsigned char *)
data);
+               ERROR_CHECK(result);
+
+               /* switch YZ axis to proper position */
+               tmp = data[2];
+               data[2] = data[4];
+               data[4] = tmp;
+               tmp = data[3];
+               data[3] = data[5];
+               data[5] = tmp;
+
+               /*drop data if overflows */
+               if ((data[0] == 0xf0) || (data[2] == 0xf0)
+                   || (data[4] == 0xf0)) {
+                       return ML_ERROR_COMPASS_DATA_OVERFLOW;
+               }
+               /* convert to fixed point and apply sensitivity
correction for
+                  Z-axis */
+               zAxisfixed =
+                   (short) ((unsigned short) data[5] +
+                            (unsigned short) data[4] * 256);
+               /* scale up by 1.122 */
+               zAxisfixed = (short) (zAxisfixed * 9) >> 3;
+               data[4] = zAxisfixed >> 8;
+               data[5] = zAxisfixed & 0xFF;
+
+               /* trigger next measurement read */
+               result =
+                   MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                         HMC_REG_MODE,
HMC_MODE_SINGLE);
+               ERROR_CHECK(result);
+
+               return ML_SUCCESS;
+       } else {
+               /* trigger next measurement read */
+               result =
+                   MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                         HMC_REG_MODE,
HMC_MODE_SINGLE);
+               ERROR_CHECK(result);
+
+               return ML_ERROR_COMPASS_DATA_NOT_READY;
+       }
+}
+
+struct ext_slave_descr hmc5883_descr = {
+       /*.suspend          = */ hmc5883_suspend,
+       /*.resume           = */ hmc5883_resume,
+       /*.read             = */ hmc5883_read,
+       /*.name             = */ "hmc5883",
+       /*.type             = */ EXT_SLAVE_TYPE_COMPASS,
+       /*.id               = */ COMPASS_ID_HMC5883,
+       /*.reg              = */ 0x06,
+       /*.len              = */ 6,
+       /*.endian           = */ EXT_SLAVE_BIG_ENDIAN,
+       /*.range            = */ {10673, 6156},
+};
+
+struct ext_slave_descr *hmc5883_get_slave_descr(void)
+{
+       return &hmc5883_descr;
+}
+
+#ifdef __KERNEL__
+EXPORT_SYMBOL(hmc5883_get_slave_descr);
+#endif
+
+/**
+ *  @}
+**/
Index: linux-2.6.35/drivers/misc/mpu3050/compass/ak8975.c
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.35/drivers/misc/mpu3050/compass/ak8975.c  2010-12-22
14:09:28.000000000 +0800
@@ -0,0 +1,151 @@
+/*
+ $License:
+    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
+
+    This program is free software; you can redistribute it and/or
modify
+    it under the terms of the GNU General Public License as published
by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    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.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see
<http://www.gnu.org/licenses/>.
+  $
+ */
+
+/**
+ *  @defgroup   COMPASSDL (Motion Library - Accelerometer Driver Layer)
+ *  @brief      Provides the interface to setup and handle an
accelerometers
+ *              connected to the secondary I2C interface of the
gyroscope.
+ *
+ *  @{
+ *      @file   AK8975.c
+ *      @brief  Magnetometer setup and handling methods for AKM 8975
compass.
+**/
+
+/* ------------------ */
+/* - Include Files. - */
+/* ------------------ */
+
+#ifdef __KERNEL__
+#include <linux/module.h>
+#endif
+
+#include "mpu.h"
+#include "mlsl.h"
+#include "mlos.h"
+
+#include <log.h>
+#undef MPL_LOG_TAG
+#define MPL_LOG_TAG "MPL-compass"
+
+
+#define AK8975_REG_ST1  (0x02)
+#define AK8975_REG_HXL  (0x03)
+#define AK8975_REG_ST2  (0x09)
+
+#define AK8975_REG_CNTL (0x0A)
+
+#define AK8975_CNTL_MODE_POWER_DOWN         (0x00)
+#define AK8975_CNTL_MODE_SINGLE_MEASUREMENT (0x01)
+
+int ak8975_suspend(void *mlsl_handle,
+                  struct ext_slave_descr *slave,
+                  struct ext_slave_platform_data *pdata)
+{
+       int result = ML_SUCCESS;
+       result =
+           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                 AK8975_REG_CNTL,
+                                 AK8975_CNTL_MODE_POWER_DOWN);
+       MLOSSleep(1);           /* wait at least 100us */
+       ERROR_CHECK(result);
+       return result;
+}
+
+int ak8975_resume(void *mlsl_handle,
+                 struct ext_slave_descr *slave,
+                 struct ext_slave_platform_data *pdata)
+{
+       int result = ML_SUCCESS;
+       result =
+           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                 AK8975_REG_CNTL,
+                                 AK8975_CNTL_MODE_SINGLE_MEASUREMENT);
+       ERROR_CHECK(result);
+       return result;
+}
+
+int ak8975_read(void *mlsl_handle,
+               struct ext_slave_descr *slave,
+               struct ext_slave_platform_data *pdata, unsigned char
*data)
+{
+       unsigned char stat;
+       unsigned char stat2;
+       int result = ML_SUCCESS;
+
+       result =
+           MLSLSerialRead(mlsl_handle, pdata->address, AK8975_REG_ST1,
1,
+                          &stat);
+       ERROR_CHECK(result);
+       if (stat & 0x01) {
+               result =
+                   MLSLSerialRead(mlsl_handle, pdata->address,
+                                  AK8975_REG_HXL, 6,
+                                  (unsigned char *) data);
+               ERROR_CHECK(result);
+               result =
+                   MLSLSerialRead(mlsl_handle, pdata->address,
+                                  AK8975_REG_ST2, 1, &stat2);
+               ERROR_CHECK(result);
+               if (stat2 & 0x04)       /*data error */
+                       return ML_ERROR_COMPASS_DATA_NOT_READY;
+               if (stat2 & 0x08)
+                       return ML_ERROR_COMPASS_DATA_OVERFLOW;
+
+               result =
+                   MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                         AK8975_REG_CNTL,
+
AK8975_CNTL_MODE_SINGLE_MEASUREMENT);
+               ERROR_CHECK(result);
+               return ML_SUCCESS;
+       } else if (stat & 0x02) {
+               result =
+                   MLSLSerialRead(mlsl_handle, pdata->address,
+                                  AK8975_REG_ST2, 1, &stat2);
+               ERROR_CHECK(result);
+               return ML_ERROR_COMPASS_DATA_OVERFLOW;
+       } else {
+               return ML_ERROR_COMPASS_DATA_NOT_READY;
+       }
+}
+
+struct ext_slave_descr ak8975_descr = {
+       /*.suspend          = */ ak8975_suspend,
+       /*.resume           = */ ak8975_resume,
+       /*.read             = */ ak8975_read,
+       /*.name             = */ "ak8975",
+       /*.type             = */ EXT_SLAVE_TYPE_COMPASS,
+       /*.id               = */ COMPASS_ID_AKM,
+       /*.reg              = */ 0x03,
+       /*.len              = */ 6,
+       /*.endian           = */ EXT_SLAVE_LITTLE_ENDIAN,
+       /*.range            = */ {9830, 4000}
+};
+
+struct ext_slave_descr *ak8975_get_slave_descr(void)
+{
+       return &ak8975_descr;
+}
+
+#ifdef __KERNEL__
+EXPORT_SYMBOL(ak8975_get_slave_descr);
+#endif
+
+/**
+ *  @}
+**/
Index: linux-2.6.35/drivers/misc/mpu3050/compass/yas529-kernel.c
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.35/drivers/misc/mpu3050/compass/yas529-kernel.c
2010-12-22 14:09:28.000000000 +0800
@@ -0,0 +1,476 @@
+/*
+ $License:
+    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
+
+    This program is free software; you can redistribute it and/or
modify
+    it under the terms of the GNU General Public License as published
by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    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.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see
<http://www.gnu.org/licenses/>.
+  $
+ */
+/**
+ *  @defgroup   ACCELDL (Motion Library - Accelerometer Driver Layer)
+ *  @brief      Provides the interface to setup and handle an
accelerometers
+ *              connected to the secondary I2C interface of the
gyroscope.
+ *
+ *  @{
+ *      @file   yas529.c
+ *      @brief  Magnetometer setup and handling methods for Yamaha
yas529
+ *              compass.
+ */
+
+/* ------------------ */
+/* - Include Files. - */
+/* ------------------ */
+
+#ifdef __KERNEL__
+#include <linux/module.h>
+#include <linux/i2c.h>
+#endif
+
+#include "mpu.h"
+#include "mlos.h"
+
+#include <log.h>
+#undef MPL_LOG_TAG
+#define MPL_LOG_TAG "MPL-acc"
+
+/*----- YAMAHA YAS529 Registers ------*/
+enum YAS_REG {
+       YAS_REG_CMDR            = 0x00, /* 000 < 5 */
+       YAS_REG_XOFFSETR        = 0x20, /* 001 < 5 */
+       YAS_REG_Y1OFFSETR       = 0x40, /* 010 < 5 */
+       YAS_REG_Y2OFFSETR       = 0x60, /* 011 < 5 */
+       YAS_REG_ICOILR          = 0x80, /* 100 < 5 */
+       YAS_REG_CAL             = 0xA0, /* 101 < 5 */
+       YAS_REG_CONFR           = 0xC0, /* 110 < 5 */
+       YAS_REG_DOUTR           = 0xE0  /* 111 < 5 */
+};
+
+/* --------------------- */
+/* -    Variables.     - */
+/* --------------------- */
+
+static long a1;
+static long a2;
+static long a3;
+static long a4;
+static long a5;
+static long a6;
+static long a7;
+static long a8;
+static long a9;
+
+/*****************************************
+    Yamaha I2C access functions
+*****************************************/
+
+static int yas529_sensor_i2c_write(struct i2c_adapter *i2c_adap,
+                                  unsigned char address,
+                                  unsigned int len, unsigned char
*data)
+{
+       struct i2c_msg msgs[1];
+       int res;
+
+       if (NULL == data || NULL == i2c_adap)
+               return -EINVAL;
+
+       msgs[0].addr = address;
+       msgs[0].flags = 0;      /* write */
+       msgs[0].buf = (unsigned char *) data;
+       msgs[0].len = len;
+
+       res = i2c_transfer(i2c_adap, msgs, 1);
+       if (res < 1)
+               return res;
+       else
+               return 0;
+}
+
+static int yas529_sensor_i2c_read(struct i2c_adapter *i2c_adap,
+                                 unsigned char address,
+                                 unsigned char reg,
+                                 unsigned int len, unsigned char *data)
+{
+       struct i2c_msg msgs[2];
+       int res;
+
+       if (NULL == data || NULL == i2c_adap)
+               return -EINVAL;
+
+       msgs[0].addr = address;
+       msgs[0].flags = I2C_M_RD;
+       msgs[0].buf = data;
+       msgs[0].len = len;
+
+       res = i2c_transfer(i2c_adap, msgs, 1);
+       if (res < 1)
+               return res;
+       else
+               return 0;
+}
+
+/*****************************************
+    Accelerometer Initialization Functions
+*****************************************/
+
+int yas529_suspend(void *mlsl_handle,
+                  struct ext_slave_descr *slave,
+                  struct ext_slave_platform_data *pdata)
+{
+       int result = ML_SUCCESS;
+
+       return result;
+}
+
+int yas529_resume(void *mlsl_handle,
+                 struct ext_slave_descr *slave,
+                 struct ext_slave_platform_data *pdata)
+{
+       int result = ML_SUCCESS;
+
+       unsigned char dummyData[1] = { 0 };
+       unsigned char dummyRegister = 0;
+       unsigned char rawData[6];
+       unsigned char calData[9];
+
+       short xoffset, y1offset, y2offset;
+       short d2, d3, d4, d5, d6, d7, d8, d9;
+
+       /* YAS529 Application Manual MS-3C - Section 4.4.5 */
+       /* =============================================== */
+       /* Step 1 - register initialization */
+       /* zero initialization coil register - "100 00 000" */
+       dummyData[0] = YAS_REG_ICOILR | 0x00;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
+                                   dummyData);
+       ERROR_CHECK(result);
+       /* zero config register - "110 00 000" */
+       dummyData[0] = YAS_REG_CONFR | 0x00;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
+                                   dummyData);
+       ERROR_CHECK(result);
+
+       /* Step 2 - initialization coil operation */
+       dummyData[0] = YAS_REG_ICOILR | 0x11;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
+                                   dummyData);
+       ERROR_CHECK(result);
+       dummyData[0] = YAS_REG_ICOILR | 0x01;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
+                                   dummyData);
+       ERROR_CHECK(result);
+       dummyData[0] = YAS_REG_ICOILR | 0x12;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
+                                   dummyData);
+       ERROR_CHECK(result);
+       dummyData[0] = YAS_REG_ICOILR | 0x02;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
+                                   dummyData);
+       ERROR_CHECK(result);
+       dummyData[0] = YAS_REG_ICOILR | 0x13;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
+                                   dummyData);
+       ERROR_CHECK(result);
+       dummyData[0] = YAS_REG_ICOILR | 0x03;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
+                                   dummyData);
+       ERROR_CHECK(result);
+       dummyData[0] = YAS_REG_ICOILR | 0x14;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
+                                   dummyData);
+       ERROR_CHECK(result);
+       dummyData[0] = YAS_REG_ICOILR | 0x04;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
+                                   dummyData);
+       ERROR_CHECK(result);
+       dummyData[0] = YAS_REG_ICOILR | 0x15;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
+                                   dummyData);
+       ERROR_CHECK(result);
+       dummyData[0] = YAS_REG_ICOILR | 0x05;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
+                                   dummyData);
+       ERROR_CHECK(result);
+       dummyData[0] = YAS_REG_ICOILR | 0x16;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
+                                   dummyData);
+       ERROR_CHECK(result);
+       dummyData[0] = YAS_REG_ICOILR | 0x06;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
+                                   dummyData);
+       ERROR_CHECK(result);
+       dummyData[0] = YAS_REG_ICOILR | 0x17;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
+                                   dummyData);
+       ERROR_CHECK(result);
+       dummyData[0] = YAS_REG_ICOILR | 0x07;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
+                                   dummyData);
+       ERROR_CHECK(result);
+       dummyData[0] = YAS_REG_ICOILR | 0x10;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
+                                   dummyData);
+       ERROR_CHECK(result);
+       dummyData[0] = YAS_REG_ICOILR | 0x00;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
+                                   dummyData);
+       ERROR_CHECK(result);
+
+       /* Step 3 - rough offset measurement */
+       /* Config register - Measurements results - "110 00 000" */
+       dummyData[0] = YAS_REG_CONFR | 0x00;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
+                                   dummyData);
+       ERROR_CHECK(result);
+       /* Measurements command register - Rough offset measurement -
+          "000 00001" */
+       dummyData[0] = YAS_REG_CMDR | 0x01;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
+                                   dummyData);
+       ERROR_CHECK(result);
+       MLOSSleep(2);           /* wait at least 1.5ms */
+
+       /* Measurement data read */
+       result =
+           yas529_sensor_i2c_read(mlsl_handle, pdata->address,
+                                  dummyRegister, 6, rawData);
+       ERROR_CHECK(result);
+       xoffset =
+           (short) ((unsigned short) rawData[5] +
+                    ((unsigned short) rawData[4] & 0x7) * 256) - 5;
+       if (xoffset < 0)
+               xoffset = 0;
+       y1offset =
+           (short) ((unsigned short) rawData[3] +
+                    ((unsigned short) rawData[2] & 0x7) * 256) - 5;
+       if (y1offset < 0)
+               y1offset = 0;
+       y2offset =
+           (short) ((unsigned short) rawData[1] +
+                    ((unsigned short) rawData[0] & 0x7) * 256) - 5;
+       if (y2offset < 0)
+               y2offset = 0;
+
+       /* Step 4 - rough offset setting */
+       /* Set rough offset register values */
+       dummyData[0] = YAS_REG_XOFFSETR | xoffset;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
+                                   dummyData);
+       ERROR_CHECK(result);
+       dummyData[0] = YAS_REG_Y1OFFSETR | y1offset;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
+                                   dummyData);
+       ERROR_CHECK(result);
+       dummyData[0] = YAS_REG_Y2OFFSETR | y2offset;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
+                                   dummyData);
+       ERROR_CHECK(result);
+
+       /* CAL matrix read (first read is invalid) */
+       /* Config register - CAL register read - "110 01 000" */
+       dummyData[0] = YAS_REG_CONFR | 0x08;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
+                                   dummyData);
+       ERROR_CHECK(result);
+       /* CAL data read */
+       result =
+           yas529_sensor_i2c_read(mlsl_handle, pdata->address,
+                                  dummyRegister, 9, calData);
+       ERROR_CHECK(result);
+       /* Config register - CAL register read - "110 01 000" */
+       dummyData[0] = YAS_REG_CONFR | 0x08;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
+                                   dummyData);
+       ERROR_CHECK(result);
+       /* CAL data read */
+       result =
+           yas529_sensor_i2c_read(mlsl_handle, pdata->address,
+                                  dummyRegister, 9, calData);
+       ERROR_CHECK(result);
+
+       /* Calculate coefficients of the sensitivity corrcetion matrix
*/
+#if 1                          /* production sensor */
+       a1 = 100;
+       d2 = (calData[0] & 0xFC) >> 2;  /* [71..66] 6bit */
+       a2 = (short) (d2 - 32);
+       /* [65..62] 4bit */
+       d3 = ((calData[0] & 0x03) << 2) | ((calData[1] & 0xC0) >> 6);
+       a3 = (short) (d3 - 8);
+       d4 = (calData[1] & 0x3F);       /* [61..56] 6bit */
+       a4 = (short) (d4 - 32);
+       d5 = (calData[2] & 0xFC) >> 2;  /* [55..50] 6bit */
+       a5 = (short) (d5 - 32) + 70;
+       /* [49..44] 6bit */
+       d6 = ((calData[2] & 0x03) << 4) | ((calData[3] & 0xF0) >> 4);
+       a6 = (short) (d6 - 32);
+       /* [43..38] 6bit */
+       d7 = ((calData[3] & 0x0F) << 2) | ((calData[4] & 0xC0) >> 6);
+       a7 = (short) (d7 - 32);
+       d8 = (calData[4] & 0x3F);       /* [37..32] 6bit */
+       a8 = (short) (d8 - 32);
+       d9 = (calData[5] & 0xFE) >> 1;  /* [31..25] 7bit */
+       a9 = (short) (d9 - 64) + 130;
+#else                          /* evaluation sensor */
+       a1 = 1.0f;
+       /* [71..66] 6bit */
+       d2 = (calData[0] & 0xFC) >> 2;
+       a2 = (short) d2;
+       /* [65..60] 6bit */
+       d3 = ((calData[0] & 0x03) << 4) | ((calData[1] & 0xF0) >> 4);
+       a3 = (short) d3;
+       /* [59..54] 6bit */
+       d4 = ((calData[1] & 0x0F) << 2) | ((calData[2] & 0xC0) >> 6);
+       a4 = (short) d4;
+       /* [53..48] 6bit */
+       d5 = (calData[2] & 0x3F);
+       a5 = (short) (d5 + 70);
+       /* [47..42] 6bit */
+       d6 = ((calData[3] & 0xFC) >> 2);
+       a6 = (short) d6;
+       /* [41..36] 6bit */
+       d7 = ((calData[3] & 0x03) << 4) | ((calData[4] & 0xF0) >> 4);
+       a7 = (short) d7;
+       /* [35..30] 6bit */
+       d8 = ((calData[4] & 0x0F) << 2) | ((calData[5] & 0xC0) >> 6);
+       a8 = (short) d8;
+       /* [29..24] 6bit */
+       d9 = (calData[5] & 0x3F);
+       a9 = (short) (d9 + 150);
+#endif
+
+       return result;
+}
+
+int yas529_read(void *mlsl_handle,
+               struct ext_slave_descr *slave,
+               struct ext_slave_platform_data *pdata, unsigned char
*data)
+{
+       unsigned char stat;
+       unsigned char rawData[6];
+       unsigned char dummyData[1] = { 0 };
+       unsigned char dummyRegister = 0;
+       tMLError result = ML_SUCCESS;
+       short SX, SY1, SY2, SY, SZ;
+       short row1fixed, row2fixed, row3fixed;
+
+       /* Config register - Measurements results - "110 00 000" */
+       dummyData[0] = YAS_REG_CONFR | 0x00;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
+                                   dummyData);
+       ERROR_CHECK(result);
+       /* Measurements command register - Normal magnetic field
measurement -
+          "000 00000" */
+       dummyData[0] = YAS_REG_CMDR | 0x00;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
+                                   dummyData);
+       ERROR_CHECK(result);
+       MLOSSleep(10);
+       /* Measurement data read */
+       result =
+           yas529_sensor_i2c_read(mlsl_handle, pdata->address,
+                                  dummyRegister, 6,
+                                  (unsigned char *) &rawData);
+       ERROR_CHECK(result);
+
+       stat = rawData[0] & 0x80;
+       if (stat == 0x00) {
+               /* Extract raw data */
+               SX = (short) ((unsigned short) rawData[5] +
+                             ((unsigned short) rawData[4] & 0x7) *
256);
+               SY1 =
+                   (short) ((unsigned short) rawData[3] +
+                            ((unsigned short) rawData[2] & 0x7) * 256);
+               SY2 =
+                   (short) ((unsigned short) rawData[1] +
+                            ((unsigned short) rawData[0] & 0x7) * 256);
+               if ((SX <= 1) || (SY1 <= 1) || (SY2 <= 1))
+                       return ML_ERROR_COMPASS_DATA_UNDERFLOW;
+               if ((SX >= 1024) || (SY1 >= 1024) || (SY2 >= 1024))
+                       return ML_ERROR_COMPASS_DATA_OVERFLOW;
+               /* Convert to XYZ axis */
+               SX = -1 * SX;
+               SY = SY2 - SY1;
+               SZ = SY1 + SY2;
+
+               /* Apply sensitivity correction matrix */
+               row1fixed =
+                   (short) ((a1 * SX + a2 * SY + a3 * SZ) >> 7) * 41;
+               row2fixed =
+                   (short) ((a4 * SX + a5 * SY + a6 * SZ) >> 7) * 41;
+               row3fixed =
+                   (short) ((a7 * SX + a8 * SY + a9 * SZ) >> 7) * 41;
+
+               data[0] = row1fixed >> 8;
+               data[1] = row1fixed & 0xFF;
+               data[2] = row2fixed >> 8;
+               data[3] = row2fixed & 0xFF;
+               data[4] = row3fixed >> 8;
+               data[5] = row3fixed & 0xFF;
+
+               return ML_SUCCESS;
+       } else {
+               return ML_ERROR_COMPASS_DATA_NOT_READY;
+       }
+}
+
+struct ext_slave_descr yas529_descr = {
+       /*.suspend          = */ yas529_suspend,
+       /*.resume           = */ yas529_resume,
+       /*.read             = */ yas529_read,
+       /*.name             = */ "yas529",
+       /*.type             = */ EXT_SLAVE_TYPE_COMPASS,
+       /*.id               = */ COMPASS_ID_YAS529,
+       /*.reg              = */ 0x06,
+       /*.len              = */ 6,
+       /*.endian           = */ EXT_SLAVE_BIG_ENDIAN,
+       /*.range            = */ {19660, 8000},
+};
+
+struct ext_slave_descr *yas529_get_slave_descr(void)
+{
+       return &yas529_descr;
+}
+
+#ifdef __KERNEL__
+EXPORT_SYMBOL(yas529_get_slave_descr);
+#endif
+
+/**
+ *  @}
+ */
_______________________________________________
MeeGo-kernel mailing list
[email protected]
http://lists.meego.com/listinfo/meego-kernel

Reply via email to