import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / magnetometer / mc6420 / mc6420.c
CommitLineData
6fa3eb70
S
1/* drivers/i2c/chips/mc6420.c - MC6420 compass driver
2 *
3 * Copyright (C) 2012 mCube Inc.
4 * Author:
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17/*******************************************************************************
18 *** INCLUDE FILES
19 *******************************************************************************/
20
21#include <linux/interrupt.h>
22#include <linux/i2c.h>
23#include <linux/slab.h>
24#include <linux/irq.h>
25#include <linux/miscdevice.h>
26#include <asm/uaccess.h>
27#include <asm/atomic.h>
28#include <linux/delay.h>
29#include <linux/input.h>
30#include <linux/workqueue.h>
31#include <linux/kobject.h>
32#include <linux/platform_device.h>
33#include <linux/earlysuspend.h>
34#include <linux/time.h>
35#include <linux/hrtimer.h>
36
37
38
39#include <mach/mt_typedefs.h>
40#include <mach/mt_gpio.h>
41#include <mach/mt_pm_ldo.h>
42
43
44#define POWER_NONE_MACRO MT65XX_POWER_NONE
45
46#include <cust_mag.h>
47#include <linux/hwmsen_helper.h>
48#include <linux/hwmsensor.h>
49#include <linux/hwmsen_dev.h>
50#include <linux/sensors_io.h>
51#include "mc6420.h"
52
53
54/*******************************************************************************
55 *** CONSTANT / DEFINITION
56 *******************************************************************************/
57/**************************
58 *** CONFIGURATION
59 **************************/
60#define MCMAG_DRV_SYSCFG_LINUX_KERNEL_2_6_X (1)
61#define MCMAG_DRV_SYSCFG_LINUX_KERNEL_3_0_X (2)
62
63#define MCMAG_DRV_SYSCFG_KERNEL_VERSION (MCMAG_DRV_SYSCFG_LINUX_KERNEL_3_0_X)
64
65/**************************
66 *** DEBUG
67 **************************/
68#if 0
69 #define MSE_TAG "[MSENSOR] "
70 #define MSE_FUN(f) printk(KERN_INFO MSE_TAG "[%s]", __FUNCTION__)
71 #define MSE_ERR(fmt, args...) printk(KERN_ERR MSE_TAG "[%s] %d: "fmt, __FUNCTION__, __LINE__, ##args)
72 #define MSE_LOG(fmt, args...) printk(KERN_INFO MSE_TAG fmt, ##args)
73 #define MSE_VER(fmt, args...) ((void)0)
74#else
75 #define MSE_TAG
76 #define MSE_FUN(f)
77 #define MSE_ERR(fmt, args...) do {} while (0)
78 #define MSE_LOG(fmt, args...) do {} while (0)
79 #define MSE_VER(fmt, args...) do {} while (0)
80#endif
81
82//#define _MCMAG_DRV_AMI_COMPATIBLE_MODE_
83 #define MCMAG_DRV_AMI304MODE_DATA_CONVERSION_FACTOR 3 // recommended value: 2, or 3
84 #define MCMAG_CONVERT_M 25
85 #define MCMAG_ORIENTATION_ACCURACY_RATE 10
86
87/**************************
88 *** MTK
89 **************************/
90
91/**************************
92 *** mCube
93 **************************/
94#define MCMAG_DRV_DISABLE 0
95#define MCMAG_DRV_ENABLE 1
96
97#define MCMAG_DRV_AXIS_X 0
98#define MCMAG_DRV_AXIS_Y 1
99#define MCMAG_DRV_AXIS_Z 2
100#define MCMAG_DRV_AXES_NUM 3
101
102#define MCMAG_DRV_DATA_LEN 6
103#define MCMAG_DRV_MAX_MSG_LEN 10
104
105#define MCMAG_DRV_DEVICE_NAME "MCMAG"
106#define MCMAG_DRV_DRIVER_VERSION "1.0.1"
107
108#define MCMAG_DRV_DAEMON_NAME "mc6420d"
109
110#define MCMAG_DRV_DEFAULT_SAMPLE_DELAY (10)
111
112#define MCMAG_DRV_SELFTEST_STATUS_INACTIVE (0x00000000)
113#define MCMAG_DRV_SELFTEST_STATUS_RUNNING_POSITIVE (0x00000001)
114#define MCMAG_DRV_SELFTEST_STATUS_RUNNING_NEGATIVE (0x00000002)
115#define MCMAG_DRV_SELFTEST_STATUS_RUNNING_END (0x00000003)
116
117/*******************************************************************************
118 *** DATA TYPE & STRUCTURE DEFINITION
119 *******************************************************************************/
120struct _mcmag_i2c_data
121{
122 struct i2c_client *ptClient;
123 struct mag_hw *ptHW;
124 struct hwmsen_convert tCvt;
125
126 atomic_t tLayout;
127 atomic_t tTrace;
128
129 #if defined(CONFIG_HAS_EARLYSUSPEND)
130 struct early_suspend tDrv_EarlySuspend;
131 #endif
132};
133
134struct _mcmagmid_data
135{
136 // spin-lock to protect data and control block
137 rwlock_t tDataLock;
138 rwlock_t tControlLock;
139
140 // control block
141 s_McmagMagControl tControl;
142
143 // data block (Orientaion Sensor)
144 int nOrientation_Heading;
145 int nOrientation_Roll;
146 int nOrientation_Pitch;
147
148 // data block (Accelemeter Sensor)
149 int nAccel_X;
150 int nAccel_Y;
151 int nAccel_Z;
152
153 // data block (Magnetometer Sensor)
154 int nMag_X;
155 int nMag_Y;
156 int nMag_Z;
157 int nMag_Status;
158
159 // control data between middleware and driver
160 int naMidControlData[10];
161};
162
163/*******************************************************************************
164 *** STATIC FUNCTION DECLARATION
165 *******************************************************************************/
166static int mcmag_i2c_probe (struct i2c_client *ptClient, const struct i2c_device_id *id);
167static int mcmag_i2c_remove(struct i2c_client *ptClient);
168
169#if (MCMAG_DRV_SYSCFG_KERNEL_VERSION == MCMAG_DRV_SYSCFG_LINUX_KERNEL_2_6_X)
170 static int mcmag_i2c_detect(struct i2c_client *ptClient, int kind, struct i2c_board_info *info);
171#endif
172
173/*******************************************************************************
174 *** STATIC VARIABLE & CONTROL BLOCK DECLARATION
175 *******************************************************************************/
176static DECLARE_WAIT_QUEUE_HEAD(wqMcmag_Open);
177static DECLARE_WAIT_QUEUE_HEAD(wqMcmag_DataReady);
178
179static u8 s_baMsgBuffer[MCMAG_DRV_MAX_MSG_LEN];
180static u32 s_dwMamagRangeMultiplier = 40;
181static u32 s_dwIsSelfTestRunning = 0;
182
183static atomic_t s_tMcmag_DeviceOpenCount = ATOMIC_INIT(0);
184static atomic_t s_tMcmag_FlagOpen = ATOMIC_INIT(0);
185static atomic_t s_tMcmag_FlagMagSensor = ATOMIC_INIT(0);
186static atomic_t s_tMcmag_FlagOrientationSensor = ATOMIC_INIT(0);
187
188static struct _mcmagmid_data s_tMcmag_MiddlewareData;
189static struct platform_driver s_tMcmag_SensorDriver;
190
191static struct i2c_client *s_ptMcmag_i2c_client = NULL;
192static const struct i2c_device_id s_tMcmag_i2c_id[] = { {MCMAG_DRV_DEVICE_NAME, 0}, {} };
193
194#if (MCMAG_DRV_SYSCFG_KERNEL_VERSION == MCMAG_DRV_SYSCFG_LINUX_KERNEL_2_6_X)
195 static unsigned short s_tMcmag_force[] = { 0x00, MCMAG_I2C_ADDR, I2C_CLIENT_END, I2C_CLIENT_END };
196 static const unsigned short *const s_ptMcmag_forces[] = { s_tMcmag_force, NULL };
197 static struct i2c_client_address_data s_tMcmag_addr_data = { .forces = s_ptMcmag_forces, };
198#elif (MCMAG_DRV_SYSCFG_KERNEL_VERSION == MCMAG_DRV_SYSCFG_LINUX_KERNEL_3_0_X)
199 static struct i2c_board_info __initdata s_tMcmag_i2c_board_info = { I2C_BOARD_INFO(MCMAG_DRV_DEVICE_NAME, (MCMAG_I2C_ADDR >> 1)) };
200#else
201 #error "MCMAG_DRV_SYSCFG_KERNEL_VERSION should be correctly configured..."
202#endif
203
204//====================================================================================================
205static struct i2c_driver s_tMcmag_i2c_driver = {
206 .driver = {
207 #if (MCMAG_DRV_SYSCFG_KERNEL_VERSION == MCMAG_DRV_SYSCFG_LINUX_KERNEL_2_6_X)
208 .owner = THIS_MODULE,
209 #endif
210
211 .name = MCMAG_DRV_DEVICE_NAME,
212 },
213
214 .probe = mcmag_i2c_probe,
215 .remove = mcmag_i2c_remove,
216
217 #if (MCMAG_DRV_SYSCFG_KERNEL_VERSION == MCMAG_DRV_SYSCFG_LINUX_KERNEL_2_6_X)
218 .detect = mcmag_i2c_detect,
219 #endif
220
221 #if !defined(CONFIG_HAS_EARLYSUSPEND)
222 .suspend = mcmag_suspend,
223 .resume = mcmag_resume,
224 #endif
225
226 .id_table = s_tMcmag_i2c_id,
227
228 #if (MCMAG_DRV_SYSCFG_KERNEL_VERSION == MCMAG_DRV_SYSCFG_LINUX_KERNEL_2_6_X)
229 .address_data = &s_tMcmag_addr_data,
230 #endif
231 };
232
233//====================================================================================================
234const s_McmagConfig c_tMcmagDefaults = { E_MCMAG_STATE_STANDBY,
235 E_MCMAG_MEAS_NORMAL,
236 { E_MCMAG_RATE_100Hz, MCMAG_DEFAULT_SETUP7_HF, MCMAG_DEFAULT_SAMPLE_RATE_DIVIDER },
237 E_MCMAG_FIELD_RANGE_2,
238 { E_MCMAG_IPP_OPEN_DRAIN, E_MCMAG_IAH_ACTIVE_LOW, MCMAG_DEFAULT_ENABLE3 },
239 MCMAG_DEFAULT_ENABLE1,
240 };
241
242/*******************************************************************************
243 *** FUNCTIONs
244 *******************************************************************************/
245/*****************************************
246 *** mCube_SensorWrite
247 *****************************************/
248mCubeResult_t mCube_SensorWrite(void *pDevID, u8 *pbDataBuf, int nDataLength)
249{
250 if ((NULL == pbDataBuf) || (nDataLength < 2))
251 return (MCUBE_FAILURE);
252
253 if (0 > hwmsen_write_block(s_ptMcmag_i2c_client, pbDataBuf[0], &pbDataBuf[1], (nDataLength - 1)))
254 {
255 MSE_ERR("[%s] ERR: i2c write block fail\n", __FUNCTION__);
256 return (MCUBE_FAILURE);
257 }
258
259 return (MCUBE_SUCCESS);
260}
261
262/*****************************************
263 *** mCube_SensorRead
264 *****************************************/
265mCubeResult_t mCube_SensorRead(void *pDevID, u8 bCmd, int nRcvBufLength, u8 *pbRcvBuf)
266{
267 if ((NULL == pbRcvBuf) || (nRcvBufLength < 1))
268 return (MCUBE_FAILURE);
269
270 if (0 > hwmsen_read_block(s_ptMcmag_i2c_client, bCmd, pbRcvBuf, nRcvBufLength))
271 {
272 MSE_ERR("[%s] ERR: i2c read fail\n", __FUNCTION__);
273 return (MCUBE_FAILURE);
274 }
275
276 return (MCUBE_SUCCESS);
277}
278
279/*****************************************
280 *** _mCube_ClearMessageBuffer
281 *****************************************/
282void _mCube_ClearMessageBuffer(void)
283{
284 memset(s_baMsgBuffer, 0, MCMAG_DRV_MAX_MSG_LEN);
285}
286
287/*****************************************
288 *** MCMAG_ConfigRegSetup1_MeasRate
289 *****************************************/
290mCubeResult_t MCMAG_ConfigRegSetup1_MeasRate(s_McmagMagControl *ptMagControl)
291{
292 u8 *_pbMsgBuf = s_baMsgBuffer;
293
294 MSE_FUN();
295
296 _mCube_ClearMessageBuffer();
297
298 *_pbMsgBuf = MCMAG_REG_SETUP1_RATE_MEAS;
299
300 _pbMsgBuf++;
301
302 switch (ptMagControl->tMagConfig.eMeasCfg)
303 {
304 case E_MCMAG_MEAS_NORMAL : *_pbMsgBuf |= MCMAG_SETUP1_MEAS_NORMAL; break;
305 case E_MCMAG_MEAS_SELFTEST_POSITIVE: *_pbMsgBuf |= MCMAG_SETUP1_MEAS_SELFTEST_POSITIVE; break;
306 case E_MCMAG_MEAS_SELFTEST_NEGATIVE: *_pbMsgBuf |= MCMAG_SETUP1_MEAS_SELFTEST_NEGATIVE; break;
307 default : return (MCUBE_FAILURE); break;
308 }
309
310 switch (ptMagControl->tMagConfig.tSampleRateCfg.eRateCfg)
311 {
312 case E_MCMAG_RATE_10Hz : *_pbMsgBuf |= MCMAG_SAMPLE_RATE_10Hz; break;
313 case E_MCMAG_RATE_25Hz : *_pbMsgBuf |= MCMAG_SAMPLE_RATE_30Hz; break;
314 case E_MCMAG_RATE_100Hz: *_pbMsgBuf |= MCMAG_SAMPLE_RATE_100Hz; break;
315 case E_MCMAG_RATE_200Hz: *_pbMsgBuf |= MCMAG_SAMPLE_RATE_200Hz; break;
316 default : return (MCUBE_FAILURE); break;
317 }
318
319 _pbMsgBuf++;
320
321 return (mCube_SensorWrite(ptMagControl->pDeviceID, s_baMsgBuffer, (_pbMsgBuf - s_baMsgBuffer)));
322}
323
324/*****************************************
325 *** MCMAG_ConfigRegSetup2_State
326 *****************************************/
327mCubeResult_t MCMAG_ConfigRegSetup2_State(s_McmagMagControl *ptMagControl)
328{
329 u8 *_pbMsgBuf = s_baMsgBuffer;
330
331 MSE_FUN();
332
333 _mCube_ClearMessageBuffer();
334
335 *_pbMsgBuf = MCMAG_REG_SETUP2_STATE;
336
337 _pbMsgBuf++;
338
339 switch (ptMagControl->tMagConfig.eActiveState)
340 {
341 case E_MCMAG_STATE_WAKE : *_pbMsgBuf |= MCMAG_SETUP2_STATE_CONTINUOUS; break;
342 case E_MCMAG_STATE_SINGLE : *_pbMsgBuf |= MCMAG_SETUP2_STATE_SINGLE; break;
343 case E_MCMAG_STATE_STANDBY: *_pbMsgBuf |= MCMAG_SETUP2_STATE_STANDBY; break;
344 default : return (MCUBE_FAILURE); break;
345 }
346
347 _pbMsgBuf++;
348
349 return (mCube_SensorWrite(ptMagControl->pDeviceID, s_baMsgBuffer, (_pbMsgBuf - s_baMsgBuffer)));
350}
351
352/*****************************************
353 *** MCMAG_ConfigRegSetup6_Range
354 *****************************************/
355mCubeResult_t MCMAG_ConfigRegSetup6_Range(s_McmagMagControl *ptMagControl)
356{
357 u8 *_pbMsgBuf = s_baMsgBuffer;
358
359 MSE_FUN();
360
361 _mCube_ClearMessageBuffer();
362
363 *_pbMsgBuf = MCMAG_REG_SETUP6_EXOFF2;
364
365 _pbMsgBuf++;
366
367 switch (ptMagControl->tMagConfig.eRangeCfg)
368 {
369 case E_MCMAG_FIELD_RANGE_1: *_pbMsgBuf |= MCMAG_SETUP6_FIELD_RANGE_1; break;
370 case E_MCMAG_FIELD_RANGE_2: *_pbMsgBuf |= MCMAG_SETUP6_FIELD_RANGE_2; break;
371 case E_MCMAG_FIELD_RANGE_3: *_pbMsgBuf |= MCMAG_SETUP6_FIELD_RANGE_3; break;
372 case E_MCMAG_FIELD_RANGE_4: *_pbMsgBuf |= MCMAG_SETUP6_FIELD_RANGE_4; break;
373 case E_MCMAG_FIELD_RANGE_5: *_pbMsgBuf |= MCMAG_SETUP6_FIELD_RANGE_5; break;
374 default : return (MCUBE_FAILURE); break;
375 }
376
377 _pbMsgBuf++;
378
379 return (mCube_SensorWrite(ptMagControl->pDeviceID, s_baMsgBuffer, (_pbMsgBuf - s_baMsgBuffer)));
380}
381
382/*****************************************
383 *** MCMAG_ConfigRegSetup7ClockRate
384 *****************************************/
385mCubeResult_t MCMAG_ConfigRegSetup7ClockRate(s_McmagMagControl *ptMagControl)
386{
387 u8 *_pbMsgBuf = s_baMsgBuffer;
388
389 MSE_FUN();
390
391 _mCube_ClearMessageBuffer();
392
393 *_pbMsgBuf = MCMAG_REG_SETUP7_EXGAIN1;
394
395 _pbMsgBuf++;
396
397 if (ptMagControl->tMagConfig.tSampleRateCfg.bIsHingFreqON)
398 *_pbMsgBuf |= MCMAG_SETUP7_HF_DIGTAL_CLOCK_8MHz;
399
400 _pbMsgBuf++;
401
402 return (mCube_SensorWrite(ptMagControl->pDeviceID, s_baMsgBuffer, (_pbMsgBuf - s_baMsgBuffer)));
403}
404
405/*****************************************
406 *** MCMAG_ConfigRegEnable1
407 *****************************************/
408mCubeResult_t MCMAG_ConfigRegEnable1(s_McmagMagControl *ptMagControl)
409{
410 u8 *_pbMsgBuf = s_baMsgBuffer;
411
412 MSE_FUN();
413
414 _mCube_ClearMessageBuffer();
415
416 *_pbMsgBuf = MCMAG_REG_ENABLE1;
417
418 _pbMsgBuf++;
419
420 *_pbMsgBuf |= ptMagControl->tMagConfig.bEnable1Cfg;
421
422 _pbMsgBuf++;
423
424 return (mCube_SensorWrite(ptMagControl->pDeviceID, s_baMsgBuffer, (_pbMsgBuf - s_baMsgBuffer)));
425}
426
427/*****************************************
428 *** MCMAG_ConfigRegEnable2
429 *****************************************/
430mCubeResult_t MCMAG_ConfigRegEnable2(s_McmagMagControl *ptMagControl)
431{
432 u8 *_pbMsgBuf = s_baMsgBuffer;
433
434 MSE_FUN();
435
436 _mCube_ClearMessageBuffer();
437
438 *_pbMsgBuf = MCMAG_REG_ENABLE2;
439
440 _pbMsgBuf++;
441
442 switch (ptMagControl->tMagConfig.tIntCfg.eIntPinCfg)
443 {
444 case E_MCMAG_IPP_OPEN_DRAIN: *_pbMsgBuf |= MCMAG_ENABLE2_IPP_OPEN_DRAIN; break;
445 case E_MCMAG_IPP_PUSH_PULL : *_pbMsgBuf |= MCMAG_ENABLE2_IPP_PUSH_PULL; break;
446 default : *_pbMsgBuf |= MCMAG_ENABLE2_IPP_OPEN_DRAIN; break;
447 }
448
449 switch (ptMagControl->tMagConfig.tIntCfg.eIntPinLevel)
450 {
451 case E_MCMAG_IAH_ACTIVE_LOW : *_pbMsgBuf |= MCMAG_ENABLE2_IAH_ACTIVE_LOW; break;
452 case E_MCMAG_IAH_ACTIVE_HIGH: *_pbMsgBuf |= MCMAG_ENABLE2_IAH_ACTIVE_HIGH; break;
453 default : *_pbMsgBuf |= MCMAG_ENABLE2_IAH_ACTIVE_HIGH; break;
454 }
455
456 _pbMsgBuf++;
457
458 return (mCube_SensorWrite(ptMagControl->pDeviceID, s_baMsgBuffer, (_pbMsgBuf - s_baMsgBuffer)));
459}
460
461/*****************************************
462 *** MCMAG_ConfigRegEnable3
463 *****************************************/
464mCubeResult_t MCMAG_ConfigRegEnable3(s_McmagMagControl *ptMagControl)
465{
466 u8 *_pbMsgBuf = s_baMsgBuffer;
467
468 MSE_FUN();
469
470 _mCube_ClearMessageBuffer();
471
472 *_pbMsgBuf = MCMAG_REG_ENABLE3_INTREN;
473
474 _pbMsgBuf++;
475
476 *_pbMsgBuf |= ((u8) ptMagControl->tMagConfig.tIntCfg.wIntEnableFlag);
477
478 _pbMsgBuf++;
479
480 return (mCube_SensorWrite(ptMagControl->pDeviceID, s_baMsgBuffer, (_pbMsgBuf - s_baMsgBuffer)));
481}
482
483/*****************************************
484 *** MCMAG_ConfigRegPowerOnReset
485 *****************************************/
486mCubeResult_t MCMAG_ConfigRegPowerOnReset(s_McmagMagControl *ptMagControl)
487{
488 u8 *_pbMsgBuf = s_baMsgBuffer;
489
490 MSE_FUN();
491
492 _mCube_ClearMessageBuffer();
493
494 *_pbMsgBuf = MCMAG_REG_POWER_ON_RESET;
495
496 _pbMsgBuf++;
497
498 *_pbMsgBuf = MCMAG_DRV_ENABLE;
499
500 _pbMsgBuf++;
501
502 return (mCube_SensorWrite(ptMagControl->pDeviceID, s_baMsgBuffer, (_pbMsgBuf - s_baMsgBuffer)));
503}
504
505/*****************************************
506 *** MCMAG_ReadChipDefaults
507 *****************************************/
508mCubeResult_t MCMAG_ReadChipDefaults(u8 bChipID, s_McmagConfig *ptMagCfg)
509{
510 MSE_FUN();
511
512 switch (bChipID)
513 {
514 case MCUBE_UNPROGRAMMED_ID:
515 case MCUBE_MARS_CHIPID0:
516 case MCUBE_MARS_CHIPID1:
517 case MCUBE_MARS_CHIPID2:
518 *ptMagCfg = c_tMcmagDefaults;
519 break;
520
521 default:
522 return (MCUBE_ACCEL_UNKNOWN_CHIPID);
523 break;
524 }
525
526 return (MCUBE_SUCCESS);
527}
528
529/*****************************************
530 *** MCMAG_SetFieldRange
531 *****************************************/
532void MCMAG_SetFieldRange(void)
533{
534 u8 _bRange;
535
536 MSE_FUN();
537
538 mCube_SensorRead(s_tMcmag_MiddlewareData.tControl.pDeviceID, MCMAG_REG_SETUP6_EXOFF2, sizeof(_bRange), &_bRange);
539
540 switch (_bRange & MCMAG_SETUP6_FIELD_RANGE_MASK)
541 {
542 case MCMAG_SETUP6_FIELD_RANGE_1: s_dwMamagRangeMultiplier = 80; break;
543 case MCMAG_SETUP6_FIELD_RANGE_2: s_dwMamagRangeMultiplier = 40; break;
544 case MCMAG_SETUP6_FIELD_RANGE_3: s_dwMamagRangeMultiplier = 30; break;
545 case MCMAG_SETUP6_FIELD_RANGE_4: s_dwMamagRangeMultiplier = 25; break;
546 case MCMAG_SETUP6_FIELD_RANGE_5: s_dwMamagRangeMultiplier = 20; break;
547 default : s_dwMamagRangeMultiplier = 40; break;
548 }
549}
550
551/*****************************************
552 *** MCMAG_SetMode
553 *****************************************/
554static int MCMAG_SetMode(int nNewMode)
555{
556 MSE_LOG("eActiveState: %d, nNewMode: %d", s_tMcmag_MiddlewareData.tControl.tMagConfig.eActiveState, nNewMode);
557
558 //if (nNewMode == s_tMcmag_MiddlewareData.tControl.tMagConfig.eActiveState)
559 // return (-1);
560
561 s_tMcmag_MiddlewareData.tControl.tMagConfig.eActiveState = nNewMode;
562
563 return (MCMAG_ConfigRegSetup2_State(&s_tMcmag_MiddlewareData.tControl));
564}
565
566/*****************************************
567 *** MCMAG_InitMagSensor
568 *****************************************/
569mCubeResult_t MCMAG_InitMagSensor(s_McmagMagControl *ptMagControl)
570{
571 e_McmagSetup2State _eActiveStateBackup;
572
573 MSE_FUN();
574
575 if (NULL == ptMagControl)
576 return (MCUBE_FAILURE);
577
578 if (E_MCMAG_INIT_STATUS_INITIALIZED == ptMagControl->eInitStatus)
579 return (MCUBE_SUCCESS);
580
581 if (!ptMagControl->bIsChipIdValid)
582 {
583 if (MCUBE_SUCCESS != mCube_SensorRead(ptMagControl->pDeviceID ,
584 ((u8) MCMAG_REG_CHIPID) ,
585 sizeof(ptMagControl->bChipID),
586 &(ptMagControl->bChipID) ))
587 {
588 return (MCUBE_MAG_INVALID_CHIP_ID);
589 }
590
591 ptMagControl->bIsChipIdValid = true;
592 }
593
594 _eActiveStateBackup = ptMagControl->tMagConfig.eActiveState;
595
596 MCMAG_SetMode(E_MCMAG_STATE_STANDBY);
597
598 MCMAG_ConfigRegSetup1_MeasRate(ptMagControl);
599 MCMAG_ConfigRegSetup6_Range(ptMagControl);
600 MCMAG_ConfigRegEnable1(ptMagControl);
601 MCMAG_ConfigRegSetup7ClockRate(ptMagControl);
602 MCMAG_ConfigRegEnable2(ptMagControl);
603 MCMAG_ConfigRegEnable3(ptMagControl);
604
605 ptMagControl->ePowerState = E_MCMAG_STATE_STANDBY;
606 ptMagControl->eInitStatus = E_MCMAG_INIT_STATUS_INITIALIZED;
607
608 MCMAG_SetMode(_eActiveStateBackup);
609
610 return (MCUBE_SUCCESS);
611}
612
613/*****************************************
614 *** MCMAG_Start
615 *****************************************/
616mCubeResult_t MCMAG_Start(s_McmagMagControl *ptMagControl)
617{
618 MSE_FUN();
619
620 if (NULL == ptMagControl)
621 return (MCUBE_FAILURE);
622
623 if (E_MCMAG_INIT_STATUS_INITIALIZED != ptMagControl->eInitStatus)
624 return (MCUBE_FAILURE);
625
626 if (E_MCMAG_STATE_STANDBY == ptMagControl->ePowerState)
627 {
628 ptMagControl->tMagConfig.eActiveState = E_MCMAG_STATE_WAKE;
629
630 if (MCUBE_SUCCESS == MCMAG_ConfigRegSetup2_State(ptMagControl))
631 ptMagControl->ePowerState = E_MCMAG_STATE_WAKE;
632 }
633
634 return (MCUBE_SUCCESS);
635}
636
637/*****************************************
638 *** MCMAG_Stop
639 *****************************************/
640mCubeResult_t MCMAG_Stop(s_McmagMagControl *ptMagControl)
641{
642 MSE_FUN();
643
644 if (NULL == ptMagControl)
645 return (MCUBE_FAILURE);
646
647 if (E_MCMAG_INIT_STATUS_INITIALIZED != ptMagControl->eInitStatus)
648 return (MCUBE_MAG_UNINITIALIZED);
649
650 ptMagControl->tMagConfig.eActiveState = E_MCMAG_STATE_STANDBY;
651 ptMagControl->ePowerState = E_MCMAG_STATE_STANDBY;
652
653 MCMAG_ConfigRegSetup2_State(ptMagControl);
654
655 return (MCUBE_SUCCESS);
656}
657
658/*****************************************
659 *** MCMAG_ReadMagSensorData
660 *****************************************/
661static int MCMAG_ReadMagSensorData(char *pszBuf, int nBufSize)
662{
663 u8 _bDataReadyStatus = 0;
664 u8 _baDataBuffer[MCMAG_DRV_DATA_LEN] = { 0 };
665 s16 _waRawData[MCMAG_DRV_AXES_NUM] = { 0 };
666 s32 _naConvertedData[MCMAG_DRV_AXES_NUM] = { 0 };
667 int _naFinalData[MCMAG_DRV_AXES_NUM] = { 0 };
668
669 struct timeval _tTimeStamp;
670 struct _mcmag_i2c_data *_pt_i2c_data = i2c_get_clientdata(s_ptMcmag_i2c_client);
671
672 MSE_FUN();
673
674 MCMAG_Start(&s_tMcmag_MiddlewareData.tControl);
675
676 if (MCUBE_SUCCESS != mCube_SensorRead(s_tMcmag_MiddlewareData.tControl.pDeviceID, MCMAG_REG_STATUS1_STATUS, sizeof(_bDataReadyStatus), &_bDataReadyStatus))
677 return (-1);
678
679 if (!(_bDataReadyStatus & MCMAG_STATUS1_ACQ_DATA_READY))
680 return (-1);
681
682 mCube_SensorRead(s_tMcmag_MiddlewareData.tControl.pDeviceID, MCMAG_REG_CH1_OUT_LSB, sizeof(_baDataBuffer), _baDataBuffer);
683
684 _waRawData[MCMAG_DRV_AXIS_X] = (_baDataBuffer[0] | (_baDataBuffer[1] << 8));
685 _waRawData[MCMAG_DRV_AXIS_Y] = (_baDataBuffer[2] | (_baDataBuffer[3] << 8));
686 _waRawData[MCMAG_DRV_AXIS_Z] = (_baDataBuffer[4] | (_baDataBuffer[5] << 8));
687
688 #ifdef _MCMAG_DRV_AMI_COMPATIBLE_MODE_
689 _naConvertedData[MCMAG_DRV_AXIS_X] = (((_waRawData[MCMAG_DRV_AXIS_X] / MCMAG_DRV_AMI304MODE_DATA_CONVERSION_FACTOR) * 2048) / 32768);
690 _naConvertedData[MCMAG_DRV_AXIS_Y] = (((_waRawData[MCMAG_DRV_AXIS_Y] / MCMAG_DRV_AMI304MODE_DATA_CONVERSION_FACTOR) * 2048) / 32768);
691 _naConvertedData[MCMAG_DRV_AXIS_Z] = (((_waRawData[MCMAG_DRV_AXIS_Z] / MCMAG_DRV_AMI304MODE_DATA_CONVERSION_FACTOR) * 2048) / 32768);
692 #else
693 _naConvertedData[MCMAG_DRV_AXIS_X] = (int)(_waRawData[MCMAG_DRV_AXIS_X] * (1000 / s_dwMamagRangeMultiplier));
694 _naConvertedData[MCMAG_DRV_AXIS_Y] = (int)(_waRawData[MCMAG_DRV_AXIS_Y] * (1000 / s_dwMamagRangeMultiplier));
695 _naConvertedData[MCMAG_DRV_AXIS_Z] = (int)(_waRawData[MCMAG_DRV_AXIS_Z] * (1000 / s_dwMamagRangeMultiplier));
696
697 do_gettimeofday(&_tTimeStamp);
698 #endif
699
700 _naFinalData[_pt_i2c_data->tCvt.map[MCMAG_DRV_AXIS_X]] = (_pt_i2c_data->tCvt.sign[MCMAG_DRV_AXIS_X] * _naConvertedData[MCMAG_DRV_AXIS_X]);
701 _naFinalData[_pt_i2c_data->tCvt.map[MCMAG_DRV_AXIS_Y]] = (_pt_i2c_data->tCvt.sign[MCMAG_DRV_AXIS_Y] * _naConvertedData[MCMAG_DRV_AXIS_Y]);
702 _naFinalData[_pt_i2c_data->tCvt.map[MCMAG_DRV_AXIS_Z]] = (_pt_i2c_data->tCvt.sign[MCMAG_DRV_AXIS_Z] * _naConvertedData[MCMAG_DRV_AXIS_Z]);
703
704 sprintf(pszBuf, "%04x %04x %04x %ld %ld", _naFinalData[MCMAG_DRV_AXIS_X], _naFinalData[MCMAG_DRV_AXIS_Y], _naFinalData[MCMAG_DRV_AXIS_Z], _tTimeStamp.tv_sec, _tTimeStamp.tv_usec);
705
706 return (0);
707}
708
709/*****************************************
710 *** MCMAG_GetOpenStatus
711 *****************************************/
712static int MCMAG_GetOpenStatus(void)
713{
714 wait_event_interruptible(wqMcmag_Open, (atomic_read(&s_tMcmag_FlagOpen) != 0));
715
716 return (atomic_read(&s_tMcmag_FlagOpen));
717}
718
719/*****************************************
720 *** MCMAG_ConfigGPIO
721 *****************************************/
722#if 0
723static int MCMAG_ConfigGPIO(void)
724{
725 mt_set_gpio_mode (GPIO_MSE_EINT_PIN, GPIO_MSE_EINT_PIN_M_GPIO);
726 mt_set_gpio_dir (GPIO_MSE_EINT_PIN, GPIO_DIR_IN );
727 mt_set_gpio_pull_enable(GPIO_MSE_EINT_PIN, GPIO_PULL_ENABLE );
728 mt_set_gpio_pull_select(GPIO_MSE_EINT_PIN, GPIO_PULL_DOWN );
729
730 return 0;
731}
732#endif
733/*****************************************
734 *** MCMAG_InitChipset
735 *****************************************/
736static int MCMAG_InitChipset(int nMode)
737{
738 MSE_FUN();
739
740 //MCMAG_ConfigGPIO();
741
742 s_ptMcmag_i2c_client->addr = ((s_ptMcmag_i2c_client->addr & I2C_MASK_FLAG) | (I2C_ENEXT_FLAG));
743
744 MCMAG_ReadChipDefaults(s_tMcmag_MiddlewareData.tControl.bChipID, &s_tMcmag_MiddlewareData.tControl.tMagConfig);
745
746 if (MCMAG_DRV_SELFTEST_STATUS_RUNNING_POSITIVE == s_dwIsSelfTestRunning)
747 s_tMcmag_MiddlewareData.tControl.tMagConfig.eMeasCfg = E_MCMAG_MEAS_SELFTEST_POSITIVE;
748 else if (MCMAG_DRV_SELFTEST_STATUS_RUNNING_NEGATIVE == s_dwIsSelfTestRunning)
749 s_tMcmag_MiddlewareData.tControl.tMagConfig.eMeasCfg = E_MCMAG_MEAS_SELFTEST_NEGATIVE;
750
751 s_tMcmag_MiddlewareData.tControl.eInitStatus = E_MCMAG_INIT_STATUS_UNINITIALIZED;
752
753 MCMAG_InitMagSensor(&s_tMcmag_MiddlewareData.tControl);
754
755 return (MCUBE_SUCCESS);
756}
757
758/*****************************************
759 *** MCMAG_ReadChipInfo
760 *****************************************/
761static int MCMAG_ReadChipInfo(char *pszBuf, int nBufSize)
762{
763 if ((NULL == pszBuf) || (nBufSize <= 16))
764 return (-1);
765
766 sprintf(pszBuf, "MC6420 Chip");
767
768 return (0);
769}
770
771/*****************************************
772 *** MCMAG_ReadPostureData
773 *****************************************/
774static int MCMAG_ReadPostureData(char *pszBuf, int nBufSize)
775{
776 MSE_FUN();
777
778 if ((NULL == pszBuf) || (nBufSize < 32))
779 return (-1);
780
781 read_lock(&s_tMcmag_MiddlewareData.tDataLock);
782
783 sprintf(pszBuf ,
784 "%d %d %d %d" ,
785 s_tMcmag_MiddlewareData.nOrientation_Heading,
786 s_tMcmag_MiddlewareData.nOrientation_Pitch ,
787 s_tMcmag_MiddlewareData.nOrientation_Roll ,
788 s_tMcmag_MiddlewareData.nMag_Status );
789
790 read_unlock(&s_tMcmag_MiddlewareData.tDataLock);
791
792 return (0);
793}
794
795/*****************************************
796 *** MCMAG_ReadCaliData
797 *****************************************/
798static int MCMAG_ReadCaliData(char *pszBuf, int nBufSize)
799{
800 MSE_FUN();
801
802 if ((NULL == pszBuf) || (nBufSize < 64))
803 return (-1);
804
805 read_lock(&s_tMcmag_MiddlewareData.tDataLock);
806
807 sprintf(pszBuf ,
808 "%d %d %d %d %d %d %d" ,
809 s_tMcmag_MiddlewareData.nMag_X ,
810 s_tMcmag_MiddlewareData.nMag_Y ,
811 s_tMcmag_MiddlewareData.nMag_Z ,
812 s_tMcmag_MiddlewareData.nAccel_X ,
813 s_tMcmag_MiddlewareData.nAccel_Y ,
814 s_tMcmag_MiddlewareData.nAccel_Z ,
815 s_tMcmag_MiddlewareData.nMag_Status );
816
817 read_unlock(&s_tMcmag_MiddlewareData.tDataLock);
818
819 return (0);
820}
821
822/*****************************************
823 *** MCMAG_ReadMiddleControl
824 *****************************************/
825static int MCMAG_ReadMiddleControl(char *pszBuf, int nBufSize)
826{
827 if ((NULL == pszBuf) || (nBufSize < 64))
828 return (-1);
829
830 read_lock(&s_tMcmag_MiddlewareData.tControlLock);
831
832 sprintf(pszBuf, "%d %d %d %d %d %d %d %d %d %d",
833 s_tMcmag_MiddlewareData.naMidControlData[0], s_tMcmag_MiddlewareData.naMidControlData[1],
834 s_tMcmag_MiddlewareData.naMidControlData[2], s_tMcmag_MiddlewareData.naMidControlData[3],
835 s_tMcmag_MiddlewareData.naMidControlData[4], s_tMcmag_MiddlewareData.naMidControlData[5],
836 s_tMcmag_MiddlewareData.naMidControlData[6], s_tMcmag_MiddlewareData.naMidControlData[7],
837 s_tMcmag_MiddlewareData.naMidControlData[8], s_tMcmag_MiddlewareData.naMidControlData[9] );
838
839 read_unlock(&s_tMcmag_MiddlewareData.tControlLock);
840
841 return (0);
842}
843
844/*****************************************
845 *** MCMAG_DoSelfTest: MACRO
846 *****************************************/
847#define _MCMAG_SELFTEST_INVALID_POSITIVE(data) (( 1000 > data) || (data > 3500))
848#define _MCMAG_SELFTEST_INVALID_NEGATIVE(data) ((-1000 < data) || (data < -3500))
849
850/*****************************************
851 *** MCMAG_DoSelfTest
852 *****************************************/
853static void MCMAG_DoSelfTest(char *pszBuf, int nBufSize)
854{
855 s16 _wRaw_PX = 0;
856 s16 _wRaw_PY = 0;
857 s16 _wRaw_PZ = 0;
858 s16 _wRaw_NX = 0;
859 s16 _wRaw_NY = 0;
860 s16 _wRaw_NZ = 0;
861
862 u32 _dwTestStatus;
863
864 MSE_FUN();
865
866 if (s_dwIsSelfTestRunning)
867 return;
868
869 memset(pszBuf, 0, nBufSize);
870
871 pszBuf[0] = 'P';
872 pszBuf[1] = 'A';
873 pszBuf[2] = 'S';
874 pszBuf[3] = 'S';
875
876 for (_dwTestStatus = MCMAG_DRV_SELFTEST_STATUS_RUNNING_POSITIVE; _dwTestStatus < MCMAG_DRV_SELFTEST_STATUS_RUNNING_END; _dwTestStatus++)
877 {
878 u8 _bStatus = 0xFF;
879 u8 _baRawDataBuf[MCMAG_DRV_DATA_LEN] = { 0, 0, 0, 0, 0, 0 };
880
881 MCMAG_SetMode(E_MCMAG_STATE_STANDBY);
882 MCMAG_ConfigRegPowerOnReset(&s_tMcmag_MiddlewareData.tControl);
883
884 s_dwIsSelfTestRunning = _dwTestStatus;
885 MCMAG_InitChipset(E_MCMAG_STATE_STANDBY);
886
887 MCMAG_SetMode(E_MCMAG_STATE_SINGLE);
888 msleep(3);
889 mCube_SensorRead(s_tMcmag_MiddlewareData.tControl.pDeviceID, MCMAG_REG_SETUP2_STATE, sizeof(_bStatus), &_bStatus);
890
891 if (_bStatus & 0x03)
892 goto _SELFTEST_ON_ERROR;
893
894 mCube_SensorRead(s_tMcmag_MiddlewareData.tControl.pDeviceID, MCMAG_REG_CH1_OUT_LSB, sizeof(_baRawDataBuf), _baRawDataBuf);
895
896 if (MCMAG_DRV_SELFTEST_STATUS_RUNNING_POSITIVE == s_dwIsSelfTestRunning)
897 {
898 _wRaw_PX = (_baRawDataBuf[0] | (_baRawDataBuf[1] << 8));
899 _wRaw_PY = (_baRawDataBuf[2] | (_baRawDataBuf[3] << 8));
900 _wRaw_PZ = (_baRawDataBuf[4] | (_baRawDataBuf[5] << 8));
901
902 if ( _MCMAG_SELFTEST_INVALID_POSITIVE(_wRaw_PX)
903 || _MCMAG_SELFTEST_INVALID_POSITIVE(_wRaw_PY)
904 || _MCMAG_SELFTEST_INVALID_POSITIVE(_wRaw_PZ))
905 {
906 goto _SELFTEST_ON_ERROR;
907 }
908 }
909 else //if (MCMAG_DRV_SELFTEST_STATUS_RUNNING_NEGATIVE == s_dwIsSelfTestRunning)
910 {
911 _wRaw_NX = (_baRawDataBuf[0] | (_baRawDataBuf[1] << 8));
912 _wRaw_NY = (_baRawDataBuf[2] | (_baRawDataBuf[3] << 8));
913 _wRaw_NZ = (_baRawDataBuf[4] | (_baRawDataBuf[5] << 8));
914
915 if ( _MCMAG_SELFTEST_INVALID_NEGATIVE(_wRaw_NX)
916 || _MCMAG_SELFTEST_INVALID_NEGATIVE(_wRaw_NY)
917 || _MCMAG_SELFTEST_INVALID_NEGATIVE(_wRaw_NZ))
918 {
919 goto _SELFTEST_ON_ERROR;
920 }
921 }
922 }
923
924 goto _SELFTEST_DONE;
925
926_SELFTEST_ON_ERROR:
927 pszBuf[0] = 'F';
928 pszBuf[1] = 'A';
929 pszBuf[2] = 'I';
930 pszBuf[3] = 'L';
931
932_SELFTEST_DONE:
933 sprintf(&pszBuf[4] ,
934 "\nP: %d %d %d\nN: %d %d %d\n",
935 _wRaw_PX, _wRaw_PY, _wRaw_PZ,
936 _wRaw_NX, _wRaw_NY, _wRaw_NZ );
937
938 MSE_LOG(">>> %s", pszBuf);
939
940 s_dwIsSelfTestRunning = MCMAG_DRV_SELFTEST_STATUS_INACTIVE;
941 MCMAG_InitChipset(E_MCMAG_STATE_STANDBY);
942}
943
944/*****************************************
945 *** show_daemon_name
946 *****************************************/
947static ssize_t show_daemon_name(struct device_driver *ptDeviceDriver, char *pszBuf)
948{
949 return (sprintf(pszBuf, MCMAG_DRV_DAEMON_NAME));
950}
951
952/*****************************************
953 *** show_chipinfo_value
954 *****************************************/
955static ssize_t show_chipinfo_value(struct device_driver *ptDeviceDriver, char *pszBuf)
956{
957 char _szChipInfoBuf[MCMAG_BUFFER_SIZE] = { 0 };
958
959 MCMAG_ReadChipInfo(_szChipInfoBuf, MCMAG_BUFFER_SIZE);
960
961 return (sprintf(pszBuf, "%s\n", _szChipInfoBuf));
962}
963
964/*****************************************
965 *** show_sensordata_value
966 *****************************************/
967static ssize_t show_sensordata_value(struct device_driver *ptDeviceDriver, char *pszBuf)
968{
969 char _szSensorDataBuf[MCMAG_BUFFER_SIZE] = { 0 };
970
971 memset(_szSensorDataBuf, 0, MCMAG_BUFFER_SIZE);
972 MCMAG_ReadMagSensorData(_szSensorDataBuf, MCMAG_BUFFER_SIZE);
973
974 return (sprintf(pszBuf, "%s\n", _szSensorDataBuf));
975}
976
977/*****************************************
978 *** show_posturedata_value
979 *****************************************/
980static ssize_t show_posturedata_value(struct device_driver *ptDeviceDriver, char *pszBuf)
981{
982 char _szPostureDataBuf[MCMAG_BUFFER_SIZE] = { 0 };
983
984 memset(_szPostureDataBuf, 0, MCMAG_BUFFER_SIZE);
985 MCMAG_ReadPostureData(_szPostureDataBuf, MCMAG_BUFFER_SIZE);
986
987 return (sprintf(pszBuf, "%s\n", _szPostureDataBuf));
988}
989
990/*****************************************
991 *** show_calidata_value
992 *****************************************/
993static ssize_t show_calidata_value(struct device_driver *ptDeviceDriver, char *pszBuf)
994{
995 char _szCaliDataBuf[MCMAG_BUFFER_SIZE] = { 0 };
996
997 memset(_szCaliDataBuf, 0, MCMAG_BUFFER_SIZE);
998 MCMAG_ReadCaliData(_szCaliDataBuf, MCMAG_BUFFER_SIZE);
999
1000 return (sprintf(pszBuf, "%s\n", _szCaliDataBuf));
1001}
1002
1003/*****************************************
1004 *** show_midcontrol_value
1005 *****************************************/
1006static ssize_t show_midcontrol_value(struct device_driver *ptDeviceDriver, char *pszBuf)
1007{
1008 char _szControlDataBuf[MCMAG_BUFFER_SIZE] = { 0 };
1009
1010 memset(_szControlDataBuf, 0, MCMAG_BUFFER_SIZE);
1011
1012 MCMAG_ReadMiddleControl(_szControlDataBuf, MCMAG_BUFFER_SIZE);
1013
1014 return (sprintf(pszBuf, "%s\n", _szControlDataBuf));
1015}
1016
1017/*****************************************
1018 *** store_midcontrol_value
1019 *****************************************/
1020static ssize_t store_midcontrol_value(struct device_driver *ptDeviceDriver, const char *pszBuf, size_t tCount)
1021{
1022 int _naNewControlData[10];
1023
1024 if (10 == sscanf(pszBuf,
1025 "%d %d %d %d %d %d %d %d %d %d",
1026 &_naNewControlData[0], &_naNewControlData[1],
1027 &_naNewControlData[2], &_naNewControlData[3],
1028 &_naNewControlData[4], &_naNewControlData[5],
1029 &_naNewControlData[6], &_naNewControlData[7],
1030 &_naNewControlData[8], &_naNewControlData[9] ))
1031 {
1032 write_lock(&s_tMcmag_MiddlewareData.tControlLock);
1033
1034 memcpy(s_tMcmag_MiddlewareData.naMidControlData, _naNewControlData, (sizeof(int) * 10));
1035
1036 write_unlock(&s_tMcmag_MiddlewareData.tControlLock);
1037 }
1038 else
1039 {
1040 MSE_ERR("ERR: invalid format of arguments\n");
1041
1042 return (0);
1043 }
1044
1045 return ((sizeof(int) * 10));
1046}
1047
1048/*****************************************
1049 *** show_middebug_value
1050 *****************************************/
1051static ssize_t show_middebug_value(struct device_driver *ptDeviceDriver, char *pszBuf)
1052{
1053 return (0);
1054}
1055
1056/*****************************************
1057 *** store_middebug_value
1058 *****************************************/
1059static ssize_t store_middebug_value(struct device_driver *ptDeviceDriver, const char *pszBuf, size_t tCount)
1060{
1061 return (0);
1062}
1063
1064/*****************************************
1065 *** show_mode_value
1066 *****************************************/
1067static ssize_t show_mode_value(struct device_driver *ptDeviceDriver, char *pszBuf)
1068{
1069 int _nMode = 0;
1070
1071 return (sprintf(pszBuf, "%d\n", _nMode));
1072}
1073
1074/*****************************************
1075 *** store_mode_value
1076 *****************************************/
1077static ssize_t store_mode_value(struct device_driver *ptDeviceDriver, const char *pszBuf, size_t tCount)
1078{
1079 return (0);
1080}
1081
1082/*****************************************
1083 *** show_layout_value
1084 *****************************************/
1085static ssize_t show_layout_value(struct device_driver *ptDeviceDriver, char *pszBuf)
1086{
1087 struct i2c_client *_ptClient = s_ptMcmag_i2c_client;
1088 struct _mcmag_i2c_data *_pt_i2c_data = i2c_get_clientdata(_ptClient);
1089
1090 return (sprintf(pszBuf ,
1091 "(%d, %d)\n[%+2d %+2d %+2d]\n[%+2d %+2d %+2d]\n" ,
1092 _pt_i2c_data->ptHW->direction, atomic_read(&_pt_i2c_data->tLayout) ,
1093 _pt_i2c_data->tCvt.sign[0], _pt_i2c_data->tCvt.sign[1], _pt_i2c_data->tCvt.sign[2],
1094 _pt_i2c_data->tCvt.map[0] , _pt_i2c_data->tCvt.map[1] , _pt_i2c_data->tCvt.map[2] ));
1095}
1096
1097/*****************************************
1098 *** store_layout_value
1099 *****************************************/
1100static ssize_t store_layout_value(struct device_driver *ptDeviceDriver, const char *pszBuf, size_t tCount)
1101{
1102 int _nLayout;
1103
1104 struct _mcmag_i2c_data *_pt_i2c_data = i2c_get_clientdata(s_ptMcmag_i2c_client);
1105
1106 if (1 != sscanf(pszBuf, "%d", &_nLayout))
1107 return (-1);
1108
1109 atomic_set(&_pt_i2c_data->tLayout, _nLayout);
1110
1111 if (!hwmsen_get_convert(_nLayout, &_pt_i2c_data->tCvt))
1112 MSE_ERR("HWMSEN_GET_CONVERT function error!\r\n");
1113 else if (!hwmsen_get_convert(_pt_i2c_data->ptHW->direction, &_pt_i2c_data->tCvt))
1114 MSE_ERR("invalid tLayout: %d, restore to %d\n", _nLayout, _pt_i2c_data->ptHW->direction);
1115 else
1116 {
1117 MSE_ERR("invalid tLayout: (%d, %d)\n", _nLayout, _pt_i2c_data->ptHW->direction);
1118
1119 hwmsen_get_convert(0, &_pt_i2c_data->tCvt);
1120 }
1121
1122 return (tCount);
1123}
1124
1125/*****************************************
1126 *** show_status_value
1127 *****************************************/
1128static ssize_t show_status_value(struct device_driver *ptDeviceDriver, char *pszBuf)
1129{
1130 return (0);
1131}
1132
1133/*****************************************
1134 *** show_trace_value
1135 *****************************************/
1136static ssize_t show_trace_value(struct device_driver *ptDeviceDriver, char *pszBuf)
1137{
1138 struct _mcmag_i2c_data *_pt_i2c_data = i2c_get_clientdata(s_ptMcmag_i2c_client);
1139
1140 if (NULL == _pt_i2c_data)
1141 return (-1);
1142
1143 return (snprintf(pszBuf, PAGE_SIZE, "0x%04X\n", atomic_read(&_pt_i2c_data->tTrace)));
1144}
1145
1146/*****************************************
1147 *** store_trace_value
1148 *****************************************/
1149static ssize_t store_trace_value(struct device_driver *ptDeviceDriver, const char *pszBuf, size_t tCount)
1150{
1151 int _nTrace;
1152
1153 struct _mcmag_i2c_data *_pt_i2c_data = i2c_get_clientdata(s_ptMcmag_i2c_client);
1154
1155 if (NULL == _pt_i2c_data)
1156 return (-1);
1157
1158 if (1 != sscanf(pszBuf, "0x%x", &_nTrace))
1159 return (-1);
1160
1161 atomic_set(&_pt_i2c_data->tTrace, _nTrace);
1162
1163 return (tCount);
1164}
1165
1166/*****************************************
1167 *** show_self_test
1168 *****************************************/
1169static ssize_t show_self_test(struct device_driver *ptDeviceDriver, char *pszBuf)
1170{
1171 char _szSelfTestDataBuf[MCMAG_BUFFER_SIZE] = { 0 };
1172
1173 MCMAG_DoSelfTest(_szSelfTestDataBuf, MCMAG_BUFFER_SIZE);
1174
1175 return (sprintf(pszBuf, "%s\n", _szSelfTestDataBuf));
1176}
1177
1178/*****************************************
1179 *** store_shipment_test
1180 *****************************************/
1181static ssize_t store_shipment_test(struct device_driver * ptDeviceDriver, const char * pszBuf, size_t tCount)
1182{
1183 // add code, if this is supported in future
1184
1185 return (tCount);
1186}
1187
1188/*****************************************
1189 *** show_shipment_test
1190 *****************************************/
1191static ssize_t show_shipment_test(struct device_driver *ptDeviceDriver, char *pszBuf)
1192{
1193 char _szSelfTestDataBuf[MCMAG_BUFFER_SIZE] = { 0 };
1194
1195 MCMAG_DoSelfTest(_szSelfTestDataBuf, MCMAG_BUFFER_SIZE);
1196
1197 if ( ('P' == _szSelfTestDataBuf[0])
1198 && ('A' == _szSelfTestDataBuf[1])
1199 && ('S' == _szSelfTestDataBuf[2])
1200 && ('S' == _szSelfTestDataBuf[3]))
1201 {
1202 return (sprintf(pszBuf, "y\n"));
1203 }
1204
1205 return (sprintf(pszBuf, "n\n"));
1206}
1207
1208/*****************************************
1209 *** DRIVER ATTRIBUTE LIST TABLE
1210 *****************************************/
1211static DRIVER_ATTR(daemon , S_IRUGO , show_daemon_name , NULL );
1212static DRIVER_ATTR(chipinfo , S_IRUGO , show_chipinfo_value , NULL );
1213static DRIVER_ATTR(sensordata , S_IRUGO , show_sensordata_value , NULL );
1214static DRIVER_ATTR(posturedata , S_IRUGO , show_posturedata_value, NULL );
1215static DRIVER_ATTR(calidata , S_IRUGO , show_calidata_value , NULL );
1216static DRIVER_ATTR(midcontrol , S_IRUGO | S_IWUSR, show_midcontrol_value , store_midcontrol_value );
1217static DRIVER_ATTR(middebug , S_IRUGO | S_IWUSR, show_middebug_value , store_middebug_value );
1218static DRIVER_ATTR(mode , S_IRUGO | S_IWUSR, show_mode_value , store_mode_value );
1219static DRIVER_ATTR(layout , S_IRUGO | S_IWUSR, show_layout_value , store_layout_value );
1220static DRIVER_ATTR(status , S_IRUGO , show_status_value , NULL );
1221static DRIVER_ATTR(trace , S_IRUGO | S_IWUSR, show_trace_value , store_trace_value );
1222static DRIVER_ATTR(selftest , S_IRUGO , show_self_test , NULL );
1223static DRIVER_ATTR(shipmenttest, S_IRUGO | S_IWUSR, show_shipment_test , store_shipment_test );
1224
1225static struct driver_attribute *ptMcmagDriverAttributeList[] = { &driver_attr_daemon ,
1226 &driver_attr_chipinfo ,
1227 &driver_attr_sensordata ,
1228 &driver_attr_posturedata ,
1229 &driver_attr_calidata ,
1230 &driver_attr_midcontrol ,
1231 &driver_attr_middebug ,
1232 &driver_attr_mode ,
1233 &driver_attr_layout ,
1234 &driver_attr_status ,
1235 &driver_attr_trace ,
1236 &driver_attr_selftest ,
1237 &driver_attr_shipmenttest
1238 };
1239
1240/*****************************************
1241 *** mcmag_create_attr
1242 *****************************************/
1243static int mcmag_create_attr(struct device_driver *ptDeviceDriver)
1244{
1245 int _nIdex;
1246 int _nNumOfAttributes = (int)(sizeof(ptMcmagDriverAttributeList) / sizeof(ptMcmagDriverAttributeList[0]));
1247
1248 MSE_FUN();
1249
1250 if (NULL == ptDeviceDriver)
1251 return (-EINVAL);
1252
1253 for (_nIdex = 0; _nIdex < _nNumOfAttributes; _nIdex++)
1254 {
1255 if(driver_create_file(ptDeviceDriver, ptMcmagDriverAttributeList[_nIdex]))
1256 break;
1257 }
1258
1259 return (0);
1260}
1261
1262/*****************************************
1263 *** mcmag_delete_attr
1264 *****************************************/
1265static int mcmag_delete_attr(struct device_driver *ptDeviceDriver)
1266{
1267 int _nIdex;
1268 int _nNumOfAttributes = (int)(sizeof(ptMcmagDriverAttributeList) / sizeof(ptMcmagDriverAttributeList[0]));
1269
1270 MSE_FUN();
1271
1272 if (NULL == ptDeviceDriver)
1273 return (-EINVAL);
1274
1275 for (_nIdex = 0; _nIdex < _nNumOfAttributes; _nIdex++)
1276 driver_remove_file(ptDeviceDriver, ptMcmagDriverAttributeList[_nIdex]);
1277
1278 return (0);
1279}
1280
1281/*****************************************
1282 *** mcmag_open
1283 *****************************************/
1284static int mcmag_open(struct inode *ptINode, struct file *ptFile)
1285{
1286 MSE_FUN();
1287
1288 atomic_inc(&s_tMcmag_DeviceOpenCount);
1289
1290 return (nonseekable_open(ptINode, ptFile));
1291}
1292
1293/*****************************************
1294 *** mcmag_release
1295 *****************************************/
1296static int mcmag_release(struct inode *ptINode, struct file *ptFile)
1297{
1298 MSE_FUN();
1299
1300 atomic_dec(&s_tMcmag_DeviceOpenCount);
1301
1302 return (0);
1303}
1304
1305/*****************************************
1306 *** _operate_sensor_enable
1307 *****************************************/
1308void _operate_sensor_enable(u32 dwType, int nSwitch)
1309{
1310 MSE_FUN();
1311
1312 read_lock(&s_tMcmag_MiddlewareData.tControlLock);
1313
1314 if (MCMAG_DRV_ENABLE == nSwitch)
1315 {
1316 if (SENSOR_ORIENTATION == dwType)
1317 {
1318 atomic_set(&s_tMcmag_FlagOrientationSensor, 1);
1319
1320 #ifdef _MCMAG_DRV_AMI_COMPATIBLE_MODE_
1321 s_tMcmag_MiddlewareData.naMidControlData[7] |= SENSOR_ORIENTATION;
1322 #endif
1323 }
1324 else // if (SENSOR_MAGNETIC == _sensor_type)
1325 {
1326 atomic_set(&s_tMcmag_FlagMagSensor, 1);
1327
1328 #ifdef _MCMAG_DRV_AMI_COMPATIBLE_MODE_
1329 s_tMcmag_MiddlewareData.naMidControlData[7] |= SENSOR_MAGNETIC;
1330 #endif
1331 }
1332
1333 atomic_set(&s_tMcmag_FlagOpen, 1);
1334 }
1335 else
1336 {
1337 if (SENSOR_ORIENTATION == dwType)
1338 {
1339 atomic_set(&s_tMcmag_FlagOrientationSensor, 0);
1340
1341 #ifdef _MCMAG_DRV_AMI_COMPATIBLE_MODE_
1342 s_tMcmag_MiddlewareData.naMidControlData[7] &= ~SENSOR_ORIENTATION;
1343 #endif
1344
1345 if (0 == atomic_read(&s_tMcmag_FlagMagSensor))
1346 atomic_set(&s_tMcmag_FlagOpen, 0);
1347 }
1348 else // if (SENSOR_MAGNETIC == _sensor_type)
1349 {
1350 atomic_set(&s_tMcmag_FlagMagSensor, 0);
1351
1352 #ifdef _MCMAG_DRV_AMI_COMPATIBLE_MODE_
1353 s_tMcmag_MiddlewareData.naMidControlData[7] &= ~SENSOR_MAGNETIC;
1354 #endif
1355
1356 if (0 == atomic_read(&s_tMcmag_FlagOrientationSensor))
1357 atomic_set(&s_tMcmag_FlagOpen, 0);
1358 }
1359 }
1360
1361 wake_up(&wqMcmag_Open);
1362
1363 read_unlock(&s_tMcmag_MiddlewareData.tControlLock);
1364
1365 if (MCMAG_DRV_ENABLE == nSwitch)
1366 MCMAG_Start(&s_tMcmag_MiddlewareData.tControl);
1367 else
1368 MCMAG_Stop(&s_tMcmag_MiddlewareData.tControl);
1369}
1370
1371/*****************************************
1372 *** MACRO :: _IOCTL_CHK_ARG
1373 *****************************************/
1374#define _IOCTL_CHK_ARG() \
1375 _pUserData = ((void __user *) lArg); \
1376 \
1377 if (NULL == _pUserData) \
1378 return (-EFAULT);
1379
1380/*****************************************
1381 *** MACRO :: _IOCTL_COPY_FROM_USER
1382 *****************************************/
1383#define _IOCTL_COPY_FROM_USER(buff) \
1384 if (copy_from_user(&buff, _pUserData, sizeof(buff))) \
1385 return (-EFAULT);
1386
1387/*****************************************
1388 *** mcmag_unlocked_ioctl
1389 *****************************************/
1390
1391static long mcmag_unlocked_ioctl(struct file *ptFile, unsigned int nCmd, unsigned long lArg)
1392{
1393 void __user *_pUserData;
1394
1395 MSE_LOG("[%s] cmd: 0x%X\n", __func__, nCmd);
1396
1397 switch (nCmd)
1398 {
1399 //================================================================
1400 case MSENSOR_IOCTL_INIT:
1401
1402 MCMAG_InitChipset(E_MCMAG_STATE_INVALID);
1403
1404 break;
1405
1406 //================================================================
1407 case ECOMPASS_IOC_GET_OFLAG:
1408 case ECOMPASS_IOC_GET_MFLAG:
1409 {
1410 short _wSensorStatus;
1411 void __user *_pArg = ((void __user *) lArg);
1412
1413 if (ECOMPASS_IOC_GET_OFLAG == nCmd)
1414 _wSensorStatus = atomic_read(&s_tMcmag_FlagOrientationSensor);
1415 else //if (ECOMPASS_IOC_GET_MFLAG == nCmd)
1416 _wSensorStatus = atomic_read(&s_tMcmag_FlagMagSensor);
1417
1418 if(copy_to_user(_pArg, &_wSensorStatus, sizeof(_wSensorStatus)))
1419 return (-EFAULT);
1420 }
1421 break;
1422
1423 //================================================================
1424 case ECOMPASS_IOC_GET_OPEN_STATUS:
1425 {
1426 int _nSensorsOpenStatus;
1427 void __user *_pArg = ((void __user *) lArg);
1428
1429 _nSensorsOpenStatus = MCMAG_GetOpenStatus();
1430
1431 if(copy_to_user(_pArg, &_nSensorsOpenStatus, sizeof(_nSensorsOpenStatus)))
1432 return (-EFAULT);
1433 }
1434 break;
1435
1436 //================================================================
1437 case MSENSOR_IOCTL_SET_POSTURE:
1438 {
1439 int _naPostureData[4] = { 0 };
1440
1441 _IOCTL_CHK_ARG();
1442 _IOCTL_COPY_FROM_USER(_naPostureData);
1443
1444 write_lock(&s_tMcmag_MiddlewareData.tDataLock);
1445 s_tMcmag_MiddlewareData.nOrientation_Heading = _naPostureData[0];
1446 s_tMcmag_MiddlewareData.nOrientation_Pitch = _naPostureData[1];
1447 s_tMcmag_MiddlewareData.nOrientation_Roll = _naPostureData[2];
1448 s_tMcmag_MiddlewareData.nMag_Status = _naPostureData[3];
1449 write_unlock(&s_tMcmag_MiddlewareData.tDataLock);
1450 }
1451 break;
1452
1453 //================================================================
1454 case MSENSOR_IOCTL_SET_CALIDATA:
1455 {
1456 int _naCaliData[7] = { 0 };
1457
1458 _IOCTL_CHK_ARG();
1459 _IOCTL_COPY_FROM_USER(_naCaliData);
1460
1461 write_lock(&s_tMcmag_MiddlewareData.tDataLock);
1462 s_tMcmag_MiddlewareData.nMag_X = _naCaliData[0];
1463 s_tMcmag_MiddlewareData.nMag_Y = _naCaliData[1];
1464 s_tMcmag_MiddlewareData.nMag_Z = _naCaliData[2];
1465 s_tMcmag_MiddlewareData.nAccel_X = _naCaliData[3];
1466 s_tMcmag_MiddlewareData.nAccel_Y = _naCaliData[4];
1467 s_tMcmag_MiddlewareData.nAccel_Z = _naCaliData[5];
1468 s_tMcmag_MiddlewareData.nMag_Status = _naCaliData[6];
1469 write_unlock(&s_tMcmag_MiddlewareData.tDataLock);
1470 }
1471 break;
1472
1473 //================================================================
1474 case MSENSOR_IOCTL_SENSOR_ENABLE:
1475 {
1476 int _nEnable;
1477
1478 _IOCTL_CHK_ARG();
1479 _IOCTL_COPY_FROM_USER(_nEnable)
1480 _operate_sensor_enable(SENSOR_ORIENTATION, _nEnable);
1481 }
1482 break;
1483
1484 //================================================================
1485 case MSENSOR_IOCTL_READ_SENSORDATA:
1486 case MSENSOR_IOCTL_READ_POSTUREDATA:
1487 case MSENSOR_IOCTL_READ_CALIDATA:
1488 case MSENSOR_IOCTL_READ_CHIPINFO:
1489 case MSENSOR_IOCTL_READ_FACTORY_SENSORDATA:
1490 {
1491 char _szStrBuf[MCMAG_BUFFER_SIZE] = { 0 };
1492
1493 _IOCTL_CHK_ARG();
1494
1495 if (MSENSOR_IOCTL_READ_SENSORDATA == nCmd)
1496 MCMAG_ReadMagSensorData(_szStrBuf, MCMAG_BUFFER_SIZE);
1497 else if ((MSENSOR_IOCTL_READ_POSTUREDATA == nCmd) || (MSENSOR_IOCTL_READ_FACTORY_SENSORDATA == nCmd))
1498 MCMAG_ReadPostureData(_szStrBuf, MCMAG_BUFFER_SIZE);
1499 else if (MSENSOR_IOCTL_READ_CALIDATA == nCmd)
1500 MCMAG_ReadCaliData(_szStrBuf, MCMAG_BUFFER_SIZE);
1501 else //if (MSENSOR_IOCTL_READ_CHIPINFO == nCmd)
1502 MCMAG_ReadChipInfo(_szStrBuf, MCMAG_BUFFER_SIZE);
1503
1504 if (copy_to_user(_pUserData, _szStrBuf, (strlen(_szStrBuf) + 1)))
1505 return (-EFAULT);
1506 }
1507 break;
1508
1509 //================================================================
1510 case MSENSOR_IOCTL_READ_CONTROL:
1511 {
1512 int _naControlData[10] = { 0 };
1513
1514 _IOCTL_CHK_ARG();
1515
1516 read_lock(&s_tMcmag_MiddlewareData.tControlLock);
1517
1518 memcpy(_naControlData, &s_tMcmag_MiddlewareData.naMidControlData[0], sizeof(_naControlData));
1519
1520 read_unlock(&s_tMcmag_MiddlewareData.tControlLock);
1521
1522 if (copy_to_user(_pUserData, _naControlData, sizeof(_naControlData)))
1523 return (-EFAULT);
1524 }
1525 break;
1526
1527 //================================================================
1528 case MSENSOR_IOCTL_SET_CONTROL:
1529
1530 break;
1531
1532 //================================================================
1533 case MSENSOR_IOCTL_SET_MODE:
1534 {
1535 int _nMode;
1536
1537 _IOCTL_CHK_ARG();
1538 _IOCTL_COPY_FROM_USER(_nMode)
1539
1540 MCMAG_SetMode(_nMode);
1541 }
1542 break;
1543
1544 //=== DISABLE THIS, DUE TO CODE MANAGEMENT =======================
1545 #if 0
1546 case MSENSOR_IOCTL_MCUBE_SET_SELF_TEST:
1547 {
1548 char _szStrBuf[MCMAG_BUFFER_SIZE] = { 0 };
1549
1550 _IOCTL_CHK_ARG();
1551
1552 MCMAG_DoSelfTest(_szStrBuf, MCMAG_BUFFER_SIZE);
1553
1554 if (copy_to_user(_pUserData, _szStrBuf, (strlen(_szStrBuf) + 1)))
1555 return (-EFAULT);
1556 }
1557
1558 break;
1559 #endif
1560
1561 //================================================================
1562 default:
1563
1564 MSE_ERR("ERR: 0x%4x CMD not supported!", nCmd);
1565 return (-ENOIOCTLCMD);
1566
1567 break;
1568 }
1569
1570 return (0);
1571}
1572
1573/*****************************************
1574 *** STATIC STRUCTURE:: fops
1575 *****************************************/
1576static struct file_operations mcmag_fops = {
1577 .owner = THIS_MODULE,
1578 .open = mcmag_open,
1579 .release = mcmag_release,
1580 .unlocked_ioctl = mcmag_unlocked_ioctl,
1581 };
1582
1583/*****************************************
1584 *** STATIC STRUCTURE:: misc-device
1585 *****************************************/
1586static struct miscdevice mcmag_device = {
1587 .minor = MISC_DYNAMIC_MINOR,
1588 .name = "msensor",
1589 .fops = &mcmag_fops,
1590 };
1591
1592/*****************************************
1593 *** MACRO :: _OPERATE_CHK_BUFF_AND_SIZE
1594 *****************************************/
1595#define _OPERATE_CHK_BUFF_AND_SIZE(buff, buffsize, TypeSize) \
1596 if ((NULL == buff) || (buffsize < sizeof(TypeSize))) \
1597 return (-EINVAL); \
1598
1599/*****************************************
1600 *** INLINE:: _operate_accuracy_status_transformer
1601 *****************************************/
1602__inline void _operate_accuracy_status_transformer(int nStatus, hwm_sensor_data *ptSensorData)
1603{
1604 switch (nStatus)
1605 {
1606 case 1 : ptSensorData->status = SENSOR_STATUS_ACCURACY_HIGH; break;
1607 case 2 : ptSensorData->status = SENSOR_STATUS_ACCURACY_HIGH; break;
1608 case 3 : ptSensorData->status = SENSOR_STATUS_ACCURACY_MEDIUM; break;
1609 case 4 : ptSensorData->status = SENSOR_STATUS_ACCURACY_LOW; break;
1610 default: ptSensorData->status = SENSOR_STATUS_UNRELIABLE; break;
1611 }
1612}
1613
1614/*****************************************
1615 *** mcmag_operate
1616 *****************************************/
1617int mcmag_operate(void *pSelf ,
1618 uint32_t dwCommand ,
1619 void *pInBuf ,
1620 int nInBufSize ,
1621 void *pOutBuf ,
1622 int nOutBufSize,
1623 int *pnActualOut )
1624{
1625 MSE_LOG("[%s] cmd: 0x%X\n", __func__, dwCommand);
1626
1627 switch (dwCommand)
1628 {
1629 //================================================================
1630 case SENSOR_DELAY:
1631 {
1632 int _nSampleDelay;
1633
1634 _OPERATE_CHK_BUFF_AND_SIZE(pInBuf, nInBufSize, int);
1635
1636 _nSampleDelay = *((int *) pInBuf);
1637
1638 if (_nSampleDelay < MCMAG_DRV_DEFAULT_SAMPLE_DELAY)
1639 _nSampleDelay = MCMAG_DRV_DEFAULT_SAMPLE_DELAY;
1640
1641 s_tMcmag_MiddlewareData.naMidControlData[0] = _nSampleDelay;
1642
1643 MSE_LOG("_nSampleDelay: %d", _nSampleDelay);
1644 }
1645 break;
1646
1647 //================================================================
1648 case SENSOR_ENABLE:
1649
1650 _OPERATE_CHK_BUFF_AND_SIZE(pInBuf, nInBufSize, int);
1651 _operate_sensor_enable(SENSOR_MAGNETIC, *(int *)pInBuf);
1652
1653 break;
1654
1655 //================================================================
1656 case SENSOR_GET_DATA:
1657 {
1658 int _nStatus = 0;
1659 hwm_sensor_data *_ptMagSensorData = NULL;
1660
1661 _OPERATE_CHK_BUFF_AND_SIZE(pOutBuf, nOutBufSize, hwm_sensor_data);
1662
1663 _ptMagSensorData = ((hwm_sensor_data *) pOutBuf);
1664
1665 read_lock(&s_tMcmag_MiddlewareData.tDataLock);
1666 _ptMagSensorData->values[0] = s_tMcmag_MiddlewareData.nMag_X;
1667 _ptMagSensorData->values[1] = s_tMcmag_MiddlewareData.nMag_Y;
1668 _ptMagSensorData->values[2] = s_tMcmag_MiddlewareData.nMag_Z;
1669 _nStatus = s_tMcmag_MiddlewareData.nMag_Status;
1670 read_unlock(&s_tMcmag_MiddlewareData.tDataLock);
1671
1672 #ifdef _MCMAG_DRV_AMI_COMPATIBLE_MODE_
1673 _ptMagSensorData->values[0] = (_ptMagSensorData->values[0] * MCMAG_CONVERT_M);
1674 _ptMagSensorData->values[1] = (_ptMagSensorData->values[1] * MCMAG_CONVERT_M);
1675 _ptMagSensorData->values[2] = (_ptMagSensorData->values[2] * MCMAG_CONVERT_M);
1676 _ptMagSensorData->value_divide = 1000;
1677
1678 _operate_accuracy_status_transformer(_nStatus, _ptMagSensorData);
1679 #else
1680 _ptMagSensorData->value_divide = 1;
1681 _ptMagSensorData->status = _nStatus;
1682 #endif // END of _MCMAG_DRV_AMI_COMPATIBLE_MODE_
1683 }
1684
1685 break; // END of SENSOR_GET_DATA
1686
1687 //================================================================
1688 default:
1689
1690 MSE_ERR("ERR: 0x%4x CMD not supported!", dwCommand);
1691 return (-1); \
1692
1693 break;
1694 }
1695
1696 return (0);
1697}
1698
1699/*****************************************
1700 *** mcmag_orientation_operate
1701 *****************************************/
1702int mcmag_orientation_operate(void *pSelf ,
1703 uint32_t dwCommand ,
1704 void *pInBuf ,
1705 int nInBufSize ,
1706 void *pOutBuf ,
1707 int nOutBufSize,
1708 int *pnActualOut )
1709{
1710 MSE_LOG("[%s] cmd: 0x%X\n", __func__, dwCommand);
1711
1712 switch (dwCommand)
1713 {
1714 //================================================================
1715 case SENSOR_DELAY:
1716 {
1717 int _nSampleDelay;
1718
1719 _OPERATE_CHK_BUFF_AND_SIZE(pInBuf, nInBufSize, int);
1720
1721 _nSampleDelay = *((int *) pInBuf);
1722
1723 if (_nSampleDelay < MCMAG_DRV_DEFAULT_SAMPLE_DELAY)
1724 _nSampleDelay = MCMAG_DRV_DEFAULT_SAMPLE_DELAY;
1725
1726 s_tMcmag_MiddlewareData.naMidControlData[0] = _nSampleDelay;
1727
1728 MSE_LOG("_nSampleDelay: %d", _nSampleDelay);
1729 }
1730 break;
1731
1732 break;
1733
1734 //================================================================
1735 case SENSOR_ENABLE:
1736
1737 _OPERATE_CHK_BUFF_AND_SIZE(pInBuf, nInBufSize, int);
1738 _operate_sensor_enable(SENSOR_ORIENTATION, *(int *)pInBuf);
1739
1740 break;
1741
1742 //================================================================
1743 case SENSOR_GET_DATA:
1744 {
1745 int _nStatus = 0;
1746 hwm_sensor_data *_ptOrientationSensorData = NULL;
1747
1748 _OPERATE_CHK_BUFF_AND_SIZE(pOutBuf, nOutBufSize, hwm_sensor_data);
1749
1750 _ptOrientationSensorData = ((hwm_sensor_data *) pOutBuf);
1751
1752 read_lock(&s_tMcmag_MiddlewareData.tDataLock);
1753 _ptOrientationSensorData->values[0] = s_tMcmag_MiddlewareData.nOrientation_Heading;
1754 _ptOrientationSensorData->values[1] = s_tMcmag_MiddlewareData.nOrientation_Pitch;
1755 _ptOrientationSensorData->values[2] = s_tMcmag_MiddlewareData.nOrientation_Roll;
1756 _nStatus = s_tMcmag_MiddlewareData.nMag_Status;
1757 read_unlock(&s_tMcmag_MiddlewareData.tDataLock);
1758
1759 #ifdef _MCMAG_DRV_AMI_COMPATIBLE_MODE_
1760 _ptOrientationSensorData->value_divide = MCMAG_ORIENTATION_ACCURACY_RATE;
1761 _operate_accuracy_status_transformer(_nStatus, _ptOrientationSensorData);
1762 #else
1763 _ptOrientationSensorData->value_divide = 1;
1764 _ptOrientationSensorData->status = _nStatus;
1765 #endif
1766 }
1767
1768 break; // END of SENSOR_GET_DATA
1769
1770 //================================================================
1771 default:
1772
1773 MSE_ERR("ERR: 0x%4x CMD not supported!", dwCommand);
1774 return (-1); \
1775
1776 break;
1777 }
1778
1779 return (0);
1780}
1781
1782/*****************************************
1783 *** MCMAG_power (MTK Reference Code)
1784 *****************************************/
1785static void MCMAG_power(struct mag_hw *ptHW, unsigned int on)
1786{
1787 static unsigned int power_on = 0;
1788
1789 if(ptHW->power_id != MT65XX_POWER_NONE) // have externel LDO
1790 {
1791 MSE_LOG("power %s\n", on ? "on" : "off");
1792
1793 if(power_on == on) // power status not change
1794 {
1795 MSE_LOG("ignore power control: %d\n", on);
1796 }
1797 else if(on) // power on
1798 {
1799 if(!hwPowerOn(ptHW->power_id, ptHW->power_vol, MCMAG_DRV_DEVICE_NAME))
1800 {
1801 MSE_ERR("power on fails!!\n");
1802 }
1803 }
1804 else // power off
1805 {
1806 if (!hwPowerDown(ptHW->power_id, MCMAG_DRV_DEVICE_NAME))
1807 {
1808 MSE_ERR("power off fail!!\n");
1809 }
1810 }
1811 }
1812
1813 power_on = on;
1814}
1815
1816/*****************************************
1817 *** POWER SAVING (MTK Reference Code)
1818 *****************************************/
1819/*----------------------------------------------------------------------------*/
1820#ifndef CONFIG_HAS_EARLYSUSPEND
1821/*----------------------------------------------------------------------------*/
1822static int mcmag_suspend(struct i2c_client *ptClient, pm_message_t msg)
1823{
1824 struct _mcmag_i2c_data *_pt_i2c_data = i2c_get_clientdata(ptClient)
1825
1826 MSE_FUN();
1827
1828 if (PM_EVENT_SUSPEND == msg.event)
1829 {
1830 MCMAG_Stop(&s_tMcmag_MiddlewareData.tControl);
1831 MCMAG_power(_pt_i2c_data->ptHW, 0);
1832 }
1833
1834 return (0);
1835}
1836/*----------------------------------------------------------------------------*/
1837static int mcmag_resume(struct i2c_client *ptClient)
1838{
1839 struct _mcmag_i2c_data *_pt_i2c_data = i2c_get_clientdata(ptClient)
1840
1841 MSE_FUN();
1842
1843 MCMAG_power(_pt_i2c_data->ptHW, 1);
1844 MCMAG_InitChipset(E_MCMAG_STATE_INVALID);
1845
1846 return (0);
1847}
1848/*----------------------------------------------------------------------------*/
1849#else /*CONFIG_HAS_EARLY_SUSPEND is defined*/
1850/*----------------------------------------------------------------------------*/
1851static void mcmag_early_suspend(struct early_suspend *h)
1852{
1853 struct _mcmag_i2c_data *_pt_i2c_data = container_of(h, struct _mcmag_i2c_data, tDrv_EarlySuspend);
1854
1855 MSE_FUN();
1856
1857 if (_pt_i2c_data == NULL)
1858 {
1859 MSE_ERR("null pointer!!\n");
1860 return;
1861 }
1862
1863 MCMAG_Stop(&s_tMcmag_MiddlewareData.tControl);
1864 MCMAG_power(_pt_i2c_data->ptHW, 0);
1865}
1866/*----------------------------------------------------------------------------*/
1867static void mcmag_late_resume(struct early_suspend *h)
1868{
1869 struct _mcmag_i2c_data *_pt_i2c_data = container_of(h, struct _mcmag_i2c_data, tDrv_EarlySuspend);
1870
1871 MSE_FUN();
1872
1873 if (_pt_i2c_data == NULL)
1874 {
1875 MSE_ERR("null pointer!!\n");
1876 return;
1877 }
1878
1879 MCMAG_power(_pt_i2c_data->ptHW, 1);
1880 MCMAG_InitChipset(E_MCMAG_STATE_INVALID);
1881}
1882/*----------------------------------------------------------------------------*/
1883#endif /*CONFIG_HAS_EARLYSUSPEND*/
1884/*----------------------------------------------------------------------------*/
1885
1886/*****************************************
1887 *** mcmag_i2c_detect
1888 *****************************************/
1889#if (MCMAG_DRV_SYSCFG_KERNEL_VERSION == MCMAG_DRV_SYSCFG_LINUX_KERNEL_2_6_X)
1890 static int mcmag_i2c_detect(struct i2c_client *ptClient, int kind, struct i2c_board_info *info)
1891 {
1892 strcpy(info->type, MCMAG_DRV_DEVICE_NAME);
1893
1894 return (0);
1895 }
1896#endif
1897
1898/*****************************************
1899 *** mcmag_init_hardware
1900 *****************************************/
1901#if (MCMAG_DRV_SYSCFG_KERNEL_VERSION == MCMAG_DRV_SYSCFG_LINUX_KERNEL_2_6_X)
1902 static void mcmag_init_hardware(void)
1903 {
1904 #if defined (K8_DH_P110)
1905 mt_set_gpio_mode(GPIO_GSE_1_EINT_PIN, GPIO_MODE_01);
1906 mt_set_gpio_dir (GPIO_GSE_1_EINT_PIN, GPIO_DIR_OUT);
1907 mt_set_gpio_out (GPIO_GSE_1_EINT_PIN, GPIO_OUT_ONE);
1908 #endif
1909 }
1910#endif
1911
1912/*****************************************
1913 *** mcmag_i2c_probe
1914 *****************************************/
1915static int mcmag_i2c_probe(struct i2c_client *ptClient, const struct i2c_device_id *id)
1916{
1917 int err = 0;
1918
1919 struct i2c_client *new_client;
1920 struct _mcmag_i2c_data *data;
1921 struct hwmsen_object sobj_m, sobj_o;
1922
1923 MSE_FUN();
1924
1925 #if (MCMAG_DRV_SYSCFG_KERNEL_VERSION == MCMAG_DRV_SYSCFG_LINUX_KERNEL_2_6_X)
1926 mcmag_init_hardware();
1927 #endif
1928
1929 if (!(data = kmalloc(sizeof(struct _mcmag_i2c_data), GFP_KERNEL)))
1930 {
1931 err = -ENOMEM;
1932 goto exit;
1933 }
1934
1935 memset(data, 0, sizeof(struct _mcmag_i2c_data));
1936
1937 data->ptHW = get_cust_mag_hw();
1938
1939 if ((err = hwmsen_get_convert(data->ptHW->direction, &data->tCvt)))
1940 {
1941 MSE_ERR("invalid direction: %d\n", data->ptHW->direction);
1942 goto exit;
1943 }
1944
1945 atomic_set(&data->tLayout, data->ptHW->direction);
1946 atomic_set(&data->tTrace, 0);
1947 init_waitqueue_head(&wqMcmag_DataReady);
1948 init_waitqueue_head(&wqMcmag_Open);
1949
1950 data->ptClient = ptClient;
1951 new_client = data->ptClient;
1952 i2c_set_clientdata(new_client, data);
1953
1954 s_ptMcmag_i2c_client = new_client;
1955
1956 if ((err = MCMAG_InitChipset(E_MCMAG_STATE_INVALID)))
1957 goto exit_init_failed;
1958
1959 if ((err = mcmag_create_attr(&s_tMcmag_SensorDriver.driver)))
1960 {
1961 MSE_ERR("create attribute err = %d\n", err);
1962 goto exit_sysfs_create_group_failed;
1963 }
1964
1965 if ((err = misc_register(&mcmag_device)))
1966 {
1967 MSE_ERR("mcmag_device register failed\n");
1968 goto exit_misc_device_register_failed;
1969 }
1970
1971 sobj_m.self = data;
1972 sobj_m.polling = 1;
1973 sobj_m.sensor_operate = mcmag_operate;
1974
1975 if ((err = hwmsen_attach(ID_MAGNETIC, &sobj_m)))
1976 {
1977 MSE_ERR("attach fail = %d\n", err);
1978 goto exit_kfree;
1979 }
1980
1981 sobj_o.self = data;
1982 sobj_o.polling = 1;
1983 sobj_o.sensor_operate = mcmag_orientation_operate;
1984
1985 if ((err = hwmsen_attach(ID_ORIENTATION, &sobj_o)))
1986 {
1987 MSE_ERR("attach fail = %d\n", err);
1988 goto exit_kfree;
1989 }
1990
1991 #if CONFIG_HAS_EARLYSUSPEND
1992 data->tDrv_EarlySuspend.level = (EARLY_SUSPEND_LEVEL_DISABLE_FB - 1),
1993 data->tDrv_EarlySuspend.suspend = mcmag_early_suspend,
1994 data->tDrv_EarlySuspend.resume = mcmag_late_resume,
1995 register_early_suspend(&data->tDrv_EarlySuspend);
1996 #endif
1997
1998 MSE_LOG("%s: OK\n", __func__);
1999 return (0);
2000
2001exit_sysfs_create_group_failed:
2002exit_init_failed:
2003 //i2c_detach_client(new_client);
2004exit_misc_device_register_failed:
2005exit_kfree:
2006 kfree(data);
2007exit:
2008 MSE_ERR("[%s] err = %d\n", __func__, err);
2009
2010 return (err);
2011}
2012
2013/*****************************************
2014 *** mcmag_i2c_remove
2015 *****************************************/
2016static int mcmag_i2c_remove(struct i2c_client *ptClient)
2017{
2018 MSE_FUN();
2019
2020 if (mcmag_delete_attr(&s_tMcmag_SensorDriver.driver))
2021 MSE_ERR("ERR: mcmag_delete_attr fail\n");
2022
2023 s_ptMcmag_i2c_client = NULL;
2024
2025 i2c_unregister_device(ptClient);
2026 kfree(i2c_get_clientdata(ptClient));
2027 misc_deregister(&mcmag_device);
2028
2029 return (0);
2030}
2031
2032/*****************************************
2033 *** mcmag_probe
2034 *****************************************/
2035static int mcmag_probe(struct platform_device *pPlatformDevice)
2036{
2037 struct mag_hw *_ptHW = get_cust_mag_hw();
2038
2039 MSE_FUN();
2040
2041 MCMAG_power(_ptHW, 1);
2042
2043 rwlock_init(&s_tMcmag_MiddlewareData.tControlLock);
2044 rwlock_init(&s_tMcmag_MiddlewareData.tDataLock);
2045
2046 s_tMcmag_MiddlewareData.naMidControlData[0] = 20; // sample delay
2047 s_tMcmag_MiddlewareData.naMidControlData[1] = 0; // run / stop daemon (HAL, middleware)
2048 s_tMcmag_MiddlewareData.naMidControlData[2] = 0; // reserved
2049 s_tMcmag_MiddlewareData.naMidControlData[3] = 0; // reserved
2050 s_tMcmag_MiddlewareData.naMidControlData[4] = 0; // reserved
2051 s_tMcmag_MiddlewareData.naMidControlData[5] = 0; // reserved
2052 s_tMcmag_MiddlewareData.naMidControlData[6] = 0; // reserved
2053 s_tMcmag_MiddlewareData.naMidControlData[7] = 0; // reserved
2054 s_tMcmag_MiddlewareData.naMidControlData[8] = 0; // reserved
2055 s_tMcmag_MiddlewareData.naMidControlData[9] = 0; // reserved
2056
2057 #if (MCMAG_DRV_SYSCFG_KERNEL_VERSION == MCMAG_DRV_SYSCFG_LINUX_KERNEL_2_6_X)
2058 s_tMcmag_force[0] = _ptHW->i2c_num;
2059 #endif
2060
2061 if (i2c_add_driver(&s_tMcmag_i2c_driver))
2062 {
2063 MSE_ERR("ERR: add driver error\n");
2064 return (-1);
2065 }
2066
2067 return (0);
2068}
2069
2070/*****************************************
2071 *** mcmag_remove
2072 *****************************************/
2073static int mcmag_remove(struct platform_device *pPlatformDevice)
2074{
2075 struct mag_hw *_ptHW = get_cust_mag_hw();
2076
2077 MSE_FUN();
2078
2079 MCMAG_power(_ptHW, 0);
2080 atomic_set(&s_tMcmag_DeviceOpenCount, 0);
2081 i2c_del_driver(&s_tMcmag_i2c_driver);
2082
2083 return (0);
2084}
2085
2086/*****************************************
2087 *** PLATFORM DRIVER:: s_tMcmag_SensorDriver
2088 *****************************************/
2089 #if 0
2090static struct platform_driver s_tMcmag_SensorDriver = {
2091 .probe = mcmag_probe,
2092 .remove = mcmag_remove,
2093 .driver = {
2094 .name = "msensor",
2095 //.owner = THIS_MODULE,
2096 }
2097 };
2098
2099#endif
2100
2101#ifdef CONFIG_OF
2102static const struct of_device_id mcmag_of_match[] = {
2103 { .compatible = "mediatek,msensor", },
2104 {},
2105};
2106#endif
2107
2108static struct platform_driver s_tMcmag_SensorDriver =
2109{
2110 .probe = mcmag_probe,
2111 .remove = mcmag_remove,
2112 .driver =
2113 {
2114 .name = "msensor",
2115 #ifdef CONFIG_OF
2116 .of_match_table = mcmag_of_match,
2117 #endif
2118 }
2119};
2120
2121/*****************************************
2122 *** mcmag_init
2123 *****************************************/
2124static int __init mcmag_init(void)
2125{
2126 #if (MCMAG_DRV_SYSCFG_KERNEL_VERSION == MCMAG_DRV_SYSCFG_LINUX_KERNEL_3_0_X)
2127 struct mag_hw *_ptHW = get_cust_mag_hw();
2128 #endif
2129
2130 MSE_FUN();
2131
2132 #if (MCMAG_DRV_SYSCFG_KERNEL_VERSION == MCMAG_DRV_SYSCFG_LINUX_KERNEL_3_0_X)
2133 i2c_register_board_info(_ptHW->i2c_num, &s_tMcmag_i2c_board_info, 1);
2134 #endif
2135
2136 if (platform_driver_register(&s_tMcmag_SensorDriver))
2137 {
2138 MSE_ERR("ERR: failed to register driver");
2139 return (-ENODEV);
2140 }
2141
2142 return (0);
2143}
2144
2145/*****************************************
2146 *** mcmag_exit
2147 *****************************************/
2148static void __exit mcmag_exit(void)
2149{
2150 MSE_FUN();
2151
2152 platform_driver_unregister(&s_tMcmag_SensorDriver);
2153}
2154
2155/*----------------------------------------------------------------------------*/
2156module_init(mcmag_init);
2157module_exit(mcmag_exit);
2158/*----------------------------------------------------------------------------*/
2159MODULE_AUTHOR("Louis Li");
2160MODULE_DESCRIPTION("MC6420 M-Sensor Driver");
2161MODULE_LICENSE("GPL");
2162MODULE_VERSION(MCMAG_DRV_DRIVER_VERSION);