Commit | Line | Data |
---|---|---|
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 | *******************************************************************************/ | |
120 | struct _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 | ||
134 | struct _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 | *******************************************************************************/ | |
166 | static int mcmag_i2c_probe (struct i2c_client *ptClient, const struct i2c_device_id *id); | |
167 | static 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 | *******************************************************************************/ | |
176 | static DECLARE_WAIT_QUEUE_HEAD(wqMcmag_Open); | |
177 | static DECLARE_WAIT_QUEUE_HEAD(wqMcmag_DataReady); | |
178 | ||
179 | static u8 s_baMsgBuffer[MCMAG_DRV_MAX_MSG_LEN]; | |
180 | static u32 s_dwMamagRangeMultiplier = 40; | |
181 | static u32 s_dwIsSelfTestRunning = 0; | |
182 | ||
183 | static atomic_t s_tMcmag_DeviceOpenCount = ATOMIC_INIT(0); | |
184 | static atomic_t s_tMcmag_FlagOpen = ATOMIC_INIT(0); | |
185 | static atomic_t s_tMcmag_FlagMagSensor = ATOMIC_INIT(0); | |
186 | static atomic_t s_tMcmag_FlagOrientationSensor = ATOMIC_INIT(0); | |
187 | ||
188 | static struct _mcmagmid_data s_tMcmag_MiddlewareData; | |
189 | static struct platform_driver s_tMcmag_SensorDriver; | |
190 | ||
191 | static struct i2c_client *s_ptMcmag_i2c_client = NULL; | |
192 | static 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 | //==================================================================================================== | |
205 | static 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 | //==================================================================================================== | |
234 | const 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 | *****************************************/ | |
248 | mCubeResult_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 | *****************************************/ | |
265 | mCubeResult_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 | *****************************************/ | |
282 | void _mCube_ClearMessageBuffer(void) | |
283 | { | |
284 | memset(s_baMsgBuffer, 0, MCMAG_DRV_MAX_MSG_LEN); | |
285 | } | |
286 | ||
287 | /***************************************** | |
288 | *** MCMAG_ConfigRegSetup1_MeasRate | |
289 | *****************************************/ | |
290 | mCubeResult_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 | *****************************************/ | |
327 | mCubeResult_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 | *****************************************/ | |
355 | mCubeResult_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 | *****************************************/ | |
385 | mCubeResult_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 | *****************************************/ | |
408 | mCubeResult_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 | *****************************************/ | |
430 | mCubeResult_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 | *****************************************/ | |
464 | mCubeResult_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 | *****************************************/ | |
486 | mCubeResult_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 | *****************************************/ | |
508 | mCubeResult_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 | *****************************************/ | |
532 | void 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 | *****************************************/ | |
554 | static 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 | *****************************************/ | |
569 | mCubeResult_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 | *****************************************/ | |
616 | mCubeResult_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 | *****************************************/ | |
640 | mCubeResult_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 | *****************************************/ | |
661 | static 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 | *****************************************/ | |
712 | static 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 | |
723 | static 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 | *****************************************/ | |
736 | static 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 | *****************************************/ | |
761 | static 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 | *****************************************/ | |
774 | static 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 | *****************************************/ | |
798 | static 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 | *****************************************/ | |
825 | static 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 | *****************************************/ | |
853 | static 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 | *****************************************/ | |
947 | static 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 | *****************************************/ | |
955 | static 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 | *****************************************/ | |
967 | static 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 | *****************************************/ | |
980 | static 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 | *****************************************/ | |
993 | static 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 | *****************************************/ | |
1006 | static 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 | *****************************************/ | |
1020 | static 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 | *****************************************/ | |
1051 | static ssize_t show_middebug_value(struct device_driver *ptDeviceDriver, char *pszBuf) | |
1052 | { | |
1053 | return (0); | |
1054 | } | |
1055 | ||
1056 | /***************************************** | |
1057 | *** store_middebug_value | |
1058 | *****************************************/ | |
1059 | static 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 | *****************************************/ | |
1067 | static 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 | *****************************************/ | |
1077 | static 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 | *****************************************/ | |
1085 | static 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 | *****************************************/ | |
1100 | static 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 | *****************************************/ | |
1128 | static ssize_t show_status_value(struct device_driver *ptDeviceDriver, char *pszBuf) | |
1129 | { | |
1130 | return (0); | |
1131 | } | |
1132 | ||
1133 | /***************************************** | |
1134 | *** show_trace_value | |
1135 | *****************************************/ | |
1136 | static 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 | *****************************************/ | |
1149 | static 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 | *****************************************/ | |
1169 | static 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 | *****************************************/ | |
1181 | static 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 | *****************************************/ | |
1191 | static 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 | *****************************************/ | |
1211 | static DRIVER_ATTR(daemon , S_IRUGO , show_daemon_name , NULL ); | |
1212 | static DRIVER_ATTR(chipinfo , S_IRUGO , show_chipinfo_value , NULL ); | |
1213 | static DRIVER_ATTR(sensordata , S_IRUGO , show_sensordata_value , NULL ); | |
1214 | static DRIVER_ATTR(posturedata , S_IRUGO , show_posturedata_value, NULL ); | |
1215 | static DRIVER_ATTR(calidata , S_IRUGO , show_calidata_value , NULL ); | |
1216 | static DRIVER_ATTR(midcontrol , S_IRUGO | S_IWUSR, show_midcontrol_value , store_midcontrol_value ); | |
1217 | static DRIVER_ATTR(middebug , S_IRUGO | S_IWUSR, show_middebug_value , store_middebug_value ); | |
1218 | static DRIVER_ATTR(mode , S_IRUGO | S_IWUSR, show_mode_value , store_mode_value ); | |
1219 | static DRIVER_ATTR(layout , S_IRUGO | S_IWUSR, show_layout_value , store_layout_value ); | |
1220 | static DRIVER_ATTR(status , S_IRUGO , show_status_value , NULL ); | |
1221 | static DRIVER_ATTR(trace , S_IRUGO | S_IWUSR, show_trace_value , store_trace_value ); | |
1222 | static DRIVER_ATTR(selftest , S_IRUGO , show_self_test , NULL ); | |
1223 | static DRIVER_ATTR(shipmenttest, S_IRUGO | S_IWUSR, show_shipment_test , store_shipment_test ); | |
1224 | ||
1225 | static 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 | *****************************************/ | |
1243 | static 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 | *****************************************/ | |
1265 | static 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 | *****************************************/ | |
1284 | static 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 | *****************************************/ | |
1296 | static 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 | *****************************************/ | |
1308 | void _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 | ||
1391 | static 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 | *****************************************/ | |
1576 | static 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 | *****************************************/ | |
1586 | static 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 | *****************************************/ | |
1617 | int 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 | *****************************************/ | |
1702 | int 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 | *****************************************/ | |
1785 | static 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 | /*----------------------------------------------------------------------------*/ | |
1822 | static 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 | /*----------------------------------------------------------------------------*/ | |
1837 | static 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 | /*----------------------------------------------------------------------------*/ | |
1851 | static 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 | /*----------------------------------------------------------------------------*/ | |
1867 | static 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 | *****************************************/ | |
1915 | static 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 | ||
2001 | exit_sysfs_create_group_failed: | |
2002 | exit_init_failed: | |
2003 | //i2c_detach_client(new_client); | |
2004 | exit_misc_device_register_failed: | |
2005 | exit_kfree: | |
2006 | kfree(data); | |
2007 | exit: | |
2008 | MSE_ERR("[%s] err = %d\n", __func__, err); | |
2009 | ||
2010 | return (err); | |
2011 | } | |
2012 | ||
2013 | /***************************************** | |
2014 | *** mcmag_i2c_remove | |
2015 | *****************************************/ | |
2016 | static 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 | *****************************************/ | |
2035 | static 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 | *****************************************/ | |
2073 | static 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 | |
2090 | static 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 | |
2102 | static const struct of_device_id mcmag_of_match[] = { | |
2103 | { .compatible = "mediatek,msensor", }, | |
2104 | {}, | |
2105 | }; | |
2106 | #endif | |
2107 | ||
2108 | static 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 | *****************************************/ | |
2124 | static 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 | *****************************************/ | |
2148 | static void __exit mcmag_exit(void) | |
2149 | { | |
2150 | MSE_FUN(); | |
2151 | ||
2152 | platform_driver_unregister(&s_tMcmag_SensorDriver); | |
2153 | } | |
2154 | ||
2155 | /*----------------------------------------------------------------------------*/ | |
2156 | module_init(mcmag_init); | |
2157 | module_exit(mcmag_exit); | |
2158 | /*----------------------------------------------------------------------------*/ | |
2159 | MODULE_AUTHOR("Louis Li"); | |
2160 | MODULE_DESCRIPTION("MC6420 M-Sensor Driver"); | |
2161 | MODULE_LICENSE("GPL"); | |
2162 | MODULE_VERSION(MCMAG_DRV_DRIVER_VERSION); |