import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / magnetometer / s62x / s62x.c
1 /* s62x.c - s62x compass driver
2 *
3 * This software is licensed under the terms of the GNU General Public
4 * License version 2, as published by the Free Software Foundation, and
5 * may be copied, distributed, and modified under those terms.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13 #include <linux/version.h>
14 #include <linux/interrupt.h>
15 #include <linux/i2c.h>
16 #include <linux/slab.h>
17 #include <linux/irq.h>
18 #include <linux/miscdevice.h>
19 #include <asm/uaccess.h>
20 #include <asm/atomic.h>
21 #include <linux/delay.h>
22 #include <linux/input.h>
23 #include <linux/workqueue.h>
24 #include <linux/kobject.h>
25 #include <linux/platform_device.h>
26 #include <linux/earlysuspend.h>
27
28 #include <linux/hwmsensor.h>
29 #include <linux/hwmsen_dev.h>
30 #include <linux/sensors_io.h>
31
32 #include <mach/mt_devs.h>
33 #include <mach/mt_typedefs.h>
34 #include <mach/mt_gpio.h>
35 #include <mach/mt_pm_ldo.h>
36
37
38 #include <cust_mag.h>
39 #include <linux/hwmsen_helper.h>
40
41
42 /*-------------------------MT6516&MT6573 define-------------------------------*/
43 #define POWER_NONE_MACRO MT65XX_POWER_NONE
44
45 /*----------------------------------------------------------------------------*/
46
47 /****** Begin of Customization ****/
48 //#define USE_ALTERNATE_ADDRESS //can change i2c address when the first(0x0c<<1) conflig whit other devices
49 //#define FORCE_KERNEL2X_STYLE //auto fit android version(cause the different i2c flow)
50 /****** End of Customization ******/
51
52 #ifndef FORCE_KERNEL2X_STYLE
53 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0))
54 #define MTK_ANDROID_4
55 #endif
56 #endif
57
58
59 #define PLATFORM_DRIVER_NAME "msensor"
60
61
62 /* The following items are for internal testing only.
63 -USE_ALTERNATE_ADDRESS: (--)default (+*)test S
64 +USE_ALTERNATE_ADDRESS: (--)default (+-)test S (-+)test A
65 */
66 //#define _MAGIC_KPT_COMMAND
67 //#define _FORCE_PROBE_ERROR
68
69 /*----------------------------------------------------------------------------*/
70 #ifndef MTK_ANDROID_4
71 #define S62X_I2C_ADDR1 (0x0C<<1)
72 #define S62X_I2C_ADDR2 (0x1E<<1)
73 #else
74 #define S62X_I2C_ADDR1 (0x0C)
75 #define S62X_I2C_ADDR2 (0x1E)
76 #endif
77
78 #ifdef USE_ALTERNATE_ADDRESS
79 #define S62X_I2C_ADDRESS S62X_I2C_ADDR2
80 #else
81 #define S62X_I2C_ADDRESS S62X_I2C_ADDR1
82 #endif
83 #define S62X_DEV_NAME "s62x"
84 #define DRIVER_VERSION "2.0.0"
85
86 /*----------------------------------------------------------------------------*/
87 #define DEBUG 0
88 #define S62X_DEBUG 1
89 #define S62X_DEBUG_MSG 1
90 #define S62X_DEBUG_FUNC 1
91 #define S62X_DEBUG_DATA 1
92 #define S62X_RETRY_COUNT 9
93 #define S62X_DEFAULT_DELAY 100
94
95 #if S62X_DEBUG_MSG
96 #define SSMDBG(format, ...) printk(KERN_INFO "S62X " format "\n", ## __VA_ARGS__)
97 #else
98 #define SSMDBG(format, ...)
99 #endif
100
101 #if S62X_DEBUG_FUNC
102 #define SSMFUNC(func) printk(KERN_INFO "S62X " func " is called\n")
103 #else
104 #define SSMFUNC(func)
105 #endif
106
107 //Don't change this if you don't know why! (refer comment:ticket:35:2)
108 #define PROJECT_ID "S628"
109
110 /*----------------------------------------------------------------------------*/
111 #define SENSOR_DATA_SIZE 6
112 #define SENSOR_DATA_COUNT (SENSOR_DATA_SIZE/sizeof(short))
113 #define CALIBRATION_DATA_SIZE 12
114
115 #define RWBUF_SIZE 32
116 #define S62X_BUFSIZE 32
117
118 #define CONVERT_O 1
119 #define CONVERT_O_DIV 1
120 #define CONVERT_M 5
121 #define CONVERT_M_DIV 28
122
123 /*----------------------------------------------------------------------------*/
124 #define SS_SENSOR_MODE_OFF 0
125 #define SS_SENSOR_MODE_MEASURE 1
126
127 /*----------------------------------------------------------------------------*/
128 #define S62X_IDX_DEVICE_ID 0x00
129 #define DEVICE_ID_VALUE 0x21
130
131 #define S62X_IDX_DEVICE_INFO 0x01
132 #define DEVICE_INFO_VALUE 0x10
133
134 #define S62X_IDX_STA1 0x02
135 #define STA1_DRDY 0x01
136
137 #define S62X_IDX_X_LSB 0x03
138 #define S62X_IDX_STA2 0x09
139
140 #define S62X_IDX_MODE 0x0A
141 #define MODE_TRIGGER 0x01
142
143 #define S62X_IDX_I2CDIS 0x0F
144 #define I2CDIS_CIC 0x00
145 #define I2CDIS_ADC 0x01
146
147 #define S62X_IDX_SET_RESET 0x1A
148 #define SET_RESET_SET 0x01
149 #define SET_RESET_RESET 0x02
150
151 #define S62X_IDX_SET_RESET_CON 0x1C
152 #define S62X_IDX_VBGSEL 0x1D
153 #define S62X_IDX_OSC_TRIM 0x1E
154
155 #define S62X_IDX_ECO1 0x1F
156 #ifdef USE_ALTERNATE_ADDRESS
157 #define ECO1_DEFAULT 0x44
158 #else
159 #define ECO1_DEFAULT 0x40
160 #endif
161
162 #define S62X_IDX_ECO2 0x20
163 #define ECO2_MRAS_NO_RST 0x80
164
165 #define S62X_IDX_CHOP 0x21
166 #define S62X_IDX_BIAS 0x23
167 #define S62X_IDX_LDO_SEL 0x24
168 #define S62X_IDX_DATA_POL 0x25
169 #define S62X_IDX_ADC_RDY_CNT 0x27
170 #define S62X_IDX_W2 0x28
171 #define S62X_IDX_PW_VALUE 0x35
172
173 #define S62X_IDX_PROBE_OE 0x37
174 #define PROBE_OE_WATCHDOG 0x10
175
176 /*----------------------------------------------------------------------------*/
177 static struct i2c_client *this_client = NULL;
178
179 static short last_m_data[SENSOR_DATA_COUNT];
180 static struct mutex last_m_data_mutex;
181
182 static short sensor_data[CALIBRATION_DATA_SIZE];
183 static struct mutex sensor_data_mutex;
184 static DECLARE_WAIT_QUEUE_HEAD(open_wq);
185
186 static short ssmd_delay = S62X_DEFAULT_DELAY;
187 static char ssmd_status[RWBUF_SIZE];
188
189 static atomic_t open_flag = ATOMIC_INIT(0);
190 static atomic_t m_flag = ATOMIC_INIT(0);
191 static atomic_t o_flag = ATOMIC_INIT(0);
192 static atomic_t m_get_data;
193 static atomic_t o_get_data;
194 static atomic_t dev_open_count;
195 static atomic_t init_phase = ATOMIC_INIT(2); // 1 = id check ok, 0 = init ok
196
197 /*----------------------------------------------------------------------------*/
198 static const struct i2c_device_id s62x_i2c_id[] = { { S62X_DEV_NAME, 0}, {} };
199 #ifndef MTK_ANDROID_4
200 static unsigned short s62x_force[] = { 0x00, S62X_I2C_ADDRESS, I2C_CLIENT_END, I2C_CLIENT_END };
201 static const unsigned short *const s62x_forces[] = { s62x_force, NULL };
202 static struct i2c_client_address_data s62x_addr_data = { .forces = s62x_forces };
203 #else
204 static struct i2c_board_info __initdata i2c_s62x = { I2C_BOARD_INFO(S62X_DEV_NAME, S62X_I2C_ADDRESS) };
205 #endif
206
207 /*----------------------------------------------------------------------------*/
208 static int s62x_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id);
209 static int s62x_i2c_remove(struct i2c_client *client);
210 #ifndef MTK_ANDROID_4
211 static int s62x_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info);
212 #else
213 static int s62x_i2c_detect(struct i2c_client *client, struct i2c_board_info *info);
214 #endif
215 static int ssm_probe(struct platform_device *pdev);
216 static int ssm_remove(struct platform_device *pdev);
217
218 /*----------------------------------------------------------------------------*/
219 typedef enum {
220 SS_FUN_DEBUG = 0x01,
221 SS_DATA_DEBUG = 0X02,
222 SS_HWM_DEBUG = 0X04,
223 SS_CTR_DEBUG = 0X08,
224 SS_I2C_DEBUG = 0x10,
225 } SS_TRACE;
226
227 /*----------------------------------------------------------------------------*/
228 struct s62x_i2c_data {
229 struct i2c_client *client;
230 struct mag_hw *hw;
231 atomic_t layout;
232 atomic_t trace;
233 struct hwmsen_convert cvt;
234 #if defined(CONFIG_HAS_EARLYSUSPEND)
235 struct early_suspend early_drv;
236 #endif
237 };
238
239 #define L2CHIP(x) ((x)/10) //layout to chip id
240 #define L2CVTI(x) ((x)%10) //layout to cvt index
241
242 /*----------------------------------------------------------------------------*/
243 static struct i2c_driver s62x_i2c_driver = {
244 .driver = {
245 #ifndef MTK_ANDROID_4
246 .owner = THIS_MODULE,
247 #endif
248 .name = S62X_DEV_NAME,
249 },
250 .probe = s62x_i2c_probe,
251 .remove = s62x_i2c_remove,
252 .detect = s62x_i2c_detect,
253 #if !defined(CONFIG_HAS_EARLYSUSPEND)
254 .suspend = s62x_suspend,
255 .resume = s62x_resume,
256 #endif
257 .id_table = s62x_i2c_id,
258 #ifndef MTK_ANDROID_4
259 .address_data = &s62x_addr_data,
260 #endif
261 };
262
263 /*----------------------------------------------------------------------------*/
264 #if 0
265 static struct platform_driver ssm_sensor_driver = {
266 .probe = ssm_probe,
267 .remove = ssm_remove,
268 .driver = {
269 .name = PLATFORM_DRIVER_NAME,
270 #ifndef MTK_ANDROID_4
271 .owner = THIS_MODULE,
272 #endif
273 }
274 };
275 #endif
276
277 #ifdef CONFIG_OF
278 static const struct of_device_id ssm_of_match[] = {
279 { .compatible = "mediatek,msensor", },
280 {},
281 };
282 #endif
283
284 static struct platform_driver ssm_sensor_driver =
285 {
286 .probe = ssm_probe,
287 .remove = ssm_remove,
288 .driver =
289 {
290 .name = "msensor",
291 #ifdef CONFIG_OF
292 .of_match_table = ssm_of_match,
293 #endif
294 }
295 };
296
297 /*----------------------------------------------------------------------------*/
298 static void s62x_power(struct mag_hw *hw, unsigned int on)
299 {
300 static unsigned int power_on = 0;
301
302 if (hw->power_id != POWER_NONE_MACRO) {
303 SSMDBG("power %s", on ? "on" : "off");
304 if (power_on == on) {
305 SSMDBG("ignore power control: %d", on);
306 } else if (on) {
307 if (!hwPowerOn(hw->power_id, hw->power_vol, S62X_DEV_NAME)) {
308 printk(KERN_ERR "S62X power on fail\n");
309 }
310 } else {
311 if (!hwPowerDown(hw->power_id, S62X_DEV_NAME)) {
312 printk(KERN_ERR "S62X power off fail\n");
313 }
314 }
315 }
316
317 power_on = on;
318 }
319
320 /*----------------------------------------------------------------------------*/
321 static int I2C_RxData(char *rxData, int length)
322 {
323 uint8_t loop_i;
324
325 #if DEBUG
326 int i;
327 struct i2c_client *client = this_client;
328 struct s62x_i2c_data *data = i2c_get_clientdata(client);
329 char addr = rxData[0];
330 #endif
331
332 /* Caller should check parameter validity.*/
333 if ((rxData == NULL) || (length < 1)) {
334 return -EINVAL;
335 }
336
337 for (loop_i = 0; loop_i < S62X_RETRY_COUNT; loop_i++) {
338 this_client->addr = (this_client->addr & I2C_MASK_FLAG) | I2C_WR_FLAG;
339 if (i2c_master_send(this_client, (const char*)rxData, ((length<<0X08) | 0X01))) {
340 break;
341 }
342 mdelay(10);
343 }
344
345 if (loop_i >= S62X_RETRY_COUNT) {
346 printk(KERN_ERR "S62X %s retry over %d\n", __func__, S62X_RETRY_COUNT);
347 return -EIO;
348 }
349
350 #if DEBUG
351 if (atomic_read(&data->trace) & SS_I2C_DEBUG) {
352 printk(KERN_INFO "S62X RxData len=%02x addr=%02x\n data=", length, addr);
353 for (i = 0; i < length; i++) {
354 printk(KERN_INFO " %02x", rxData[i]);
355 }
356 printk(KERN_INFO "\n");
357 }
358 #endif
359 return 0;
360 }
361
362 static int I2C_TxData(char *txData, int length)
363 {
364 uint8_t loop_i;
365
366 #if DEBUG
367 int i;
368 struct i2c_client *client = this_client;
369 struct s62x_i2c_data *data = i2c_get_clientdata(client);
370 #endif
371
372 /* Caller should check parameter validity.*/
373 if ((txData == NULL) || (length < 2)) {
374 return -EINVAL;
375 }
376
377 this_client->addr = this_client->addr & I2C_MASK_FLAG;
378 for (loop_i = 0; loop_i < S62X_RETRY_COUNT; loop_i++) {
379 if (i2c_master_send(this_client, (const char*)txData, length) > 0) {
380 break;
381 }
382 mdelay(10);
383 }
384
385 if (loop_i >= S62X_RETRY_COUNT) {
386 printk(KERN_ERR "S62X %s retry over %d\n", __func__, S62X_RETRY_COUNT);
387 return -EIO;
388 }
389
390 #if DEBUG
391 if (atomic_read(&data->trace) & SS_I2C_DEBUG) {
392 printk(KERN_INFO "S62X TxData len=%02x addr=%02x\n data=", length, txData[0]);
393 for (i = 0; i < (length-1); i++) {
394 printk(KERN_INFO " %02x", txData[i + 1]);
395 }
396 printk(KERN_INFO "\n");
397 }
398 #endif
399 return 0;
400 }
401
402 static int I2C_TxData2(unsigned char c1, unsigned char c2)
403 {
404 unsigned char data[2];
405
406 data[0] = c1;
407 data[1] = c2;
408
409 return I2C_TxData(data, 2);
410 }
411
412 static int ECS_InitDevice(void)
413 {
414 char *err_desc = NULL;
415
416 if (I2C_TxData2(S62X_IDX_BIAS, 0x00) < 0) {
417 err_desc = "BIAS";
418 goto end_of_func;
419 }
420
421 if (I2C_TxData2(S62X_IDX_VBGSEL, 0x70) < 0) {
422 err_desc = "VBGSEL";
423 goto end_of_func;
424 }
425
426 if (I2C_TxData2(S62X_IDX_OSC_TRIM, 0x00) < 0) {
427 err_desc = "OSC_TRIM";
428 goto end_of_func;
429 }
430
431 if (I2C_TxData2(S62X_IDX_ECO1, ECO1_DEFAULT) < 0) {
432 err_desc = "ECO1";
433 goto end_of_func;
434 }
435
436 if (I2C_TxData2(S62X_IDX_ECO2, 0x04) < 0) {
437 err_desc = "ECO2";
438 goto end_of_func;
439 }
440
441 if (I2C_TxData2(S62X_IDX_CHOP, 0x05) < 0) {
442 err_desc = "CHOP";
443 goto end_of_func;
444 }
445
446 if (I2C_TxData2(S62X_IDX_LDO_SEL, 0x13) < 0) {
447 err_desc = "LDO_SEL";
448 goto end_of_func;
449 }
450
451 if (I2C_TxData2(S62X_IDX_PW_VALUE, 0x5f) < 0) {
452 err_desc = "PW_VALUE";
453 goto end_of_func;
454 }
455
456 if (I2C_TxData2(S62X_IDX_SET_RESET_CON, 0x80) < 0) {
457 err_desc = "SET_RESET_CON";
458 goto end_of_func;
459 }
460
461 if (I2C_TxData2(S62X_IDX_DATA_POL, 0x00) < 0) {
462 err_desc = "DATA_POL";
463 goto end_of_func;
464 }
465
466 if (I2C_TxData2(S62X_IDX_ADC_RDY_CNT, 0x03) < 0) {
467 err_desc = "ADC_RDY_CNT";
468 goto end_of_func;
469 }
470
471 if (I2C_TxData2(S62X_IDX_W2, 0x20) < 0) {
472 err_desc = "W2";
473 goto end_of_func;
474 }
475
476 if (I2C_TxData2(S62X_IDX_PROBE_OE, 0x20|PROBE_OE_WATCHDOG) < 0) {
477 err_desc = "PROBE_OE";
478 goto end_of_func;
479 }
480
481 end_of_func:
482
483 if (err_desc) {
484 printk(KERN_ERR "S62X_IDX_%s failed\n", err_desc);
485 return -EFAULT;
486 }
487
488 #if DEBUG
489 {
490 struct i2c_client *client = this_client;
491 struct s62x_i2c_data *data = i2c_get_clientdata(client);
492
493 if ((atomic_read(&data->trace) & 0xF000) == 0x9000) return -EFAULT;
494 else atomic_set(&init_phase, 0);
495 }
496 #endif
497 return 0;
498 }
499
500 static int ECS_SetMode_Off(void)
501 {
502 char *err_desc = NULL;
503
504 if (I2C_TxData2(S62X_IDX_MODE, 0x00) < 0) {
505 err_desc = "MODE";
506 goto end_of_func;
507 }
508
509 if (I2C_TxData2(S62X_IDX_ECO2, 0x04) < 0) {
510 err_desc = "ECO2";
511 goto end_of_func;
512 }
513
514 if (I2C_TxData2(S62X_IDX_I2CDIS, I2CDIS_CIC) < 0) {
515 err_desc = "ECO2";
516 goto end_of_func;
517 }
518
519 end_of_func:
520
521 if (err_desc) {
522 printk(KERN_ERR "S62X_IDX_%s failed\n", err_desc);
523 return -EFAULT;
524 }
525
526 return 0;
527 }
528
529 static int ECS_SetMode_Measure(void)
530 {
531 char *err_desc = NULL;
532
533 if (I2C_TxData2(S62X_IDX_I2CDIS, I2CDIS_ADC) < 0) {
534 err_desc = "I2CDIS";
535 goto end_of_func;
536 }
537
538 if (I2C_TxData2(S62X_IDX_ECO2, 0x04|ECO2_MRAS_NO_RST) < 0) {
539 err_desc = "ECO2";
540 goto end_of_func;
541 }
542
543 if (I2C_TxData2(S62X_IDX_MODE, MODE_TRIGGER) < 0) {
544 err_desc = "MODE";
545 goto end_of_func;
546 }
547
548 end_of_func:
549
550 if (err_desc) {
551 printk(KERN_ERR "S62X_IDX_%s failed\n", err_desc);
552 return -EFAULT;
553 }
554
555 return 0;
556 }
557
558 static int ECS_SetMode(char mode)
559 {
560 int ret;
561
562 switch (mode) {
563
564 case SS_SENSOR_MODE_OFF:
565 ret = ECS_SetMode_Off();
566 break;
567
568 case SS_SENSOR_MODE_MEASURE:
569 ret = ECS_SetMode_Measure();
570 break;
571
572 default:
573 SSMDBG("%s: Unknown mode(%d)", __func__, mode);
574 return -EINVAL;
575 }
576
577 return ret;
578 }
579
580 static int ECS_CheckDevice(void)
581 {
582 char id1, id2;
583 int err;
584
585 id1 = S62X_IDX_DEVICE_ID;
586 err = I2C_RxData(&id1, 1);
587 if (err < 0) {
588 return err;
589 }
590
591 id2 = S62X_IDX_DEVICE_INFO;
592 err = I2C_RxData(&id2, 1);
593 if (err < 0) {
594 return err;
595 }
596
597 #if DEBUG
598 {
599 struct i2c_client *client = this_client;
600 struct s62x_i2c_data *data = i2c_get_clientdata(client);
601
602 if ((atomic_read(&data->trace) & 0xF000) == 0x8000) id1 = 0x00, id2= 0x01;
603 else atomic_set(&init_phase, 1);
604 }
605 #endif
606 if (id1 != DEVICE_ID_VALUE || id2 != DEVICE_INFO_VALUE) {
607 printk(KERN_ERR "S62X incorrect id %02X:%02X\n", id1, id2);
608 return -EFAULT;
609 }
610
611 return 0;
612 }
613
614 static int ECS_SaveData(short *buf)
615 {
616 #if DEBUG
617 struct i2c_client *client = this_client;
618 struct s62x_i2c_data *data = i2c_get_clientdata(client);
619 #endif
620
621 mutex_lock(&sensor_data_mutex);
622 memcpy(sensor_data, buf, sizeof(sensor_data));
623 mutex_unlock(&sensor_data_mutex);
624
625 #if DEBUG
626 if (atomic_read(&data->trace) & SS_HWM_DEBUG) {
627 SSMDBG("Get daemon data: %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d!",
628 sensor_data[0],sensor_data[1],sensor_data[2],sensor_data[3],
629 sensor_data[4],sensor_data[5],sensor_data[6],sensor_data[7],
630 sensor_data[8],sensor_data[9],sensor_data[10],sensor_data[11]);
631 }
632 #endif
633 return 0;
634 }
635
636 #define V(c1,c2) (int)(((((unsigned)(c1))<<8)|((unsigned)(c2)))&0x0fff)
637
638 static int ECS_GetData(short *mag)
639 {
640 int loop_i,ret;
641 struct i2c_client *client = this_client;
642 struct s62x_i2c_data *data = i2c_get_clientdata(client);
643 short v;
644 char buf[6];
645
646 for (loop_i = 0; loop_i < S62X_RETRY_COUNT; loop_i++) {
647 buf[0] = S62X_IDX_STA1;
648 if (I2C_RxData(buf, 1)) {
649 printk(KERN_ERR "S62X_IDX_STA1 %s fail\n", __func__);
650 return -1;
651 }
652
653 if (buf[0] == STA1_DRDY) {
654 break;
655 }
656 msleep(10);
657 }
658
659 if (loop_i >= S62X_RETRY_COUNT) {
660 printk(KERN_ERR "S62X %s retry over\n", __func__);
661 return -1;
662 }
663
664 buf[0] = S62X_IDX_X_LSB;
665 ret = I2C_RxData(buf, sizeof(buf));
666 if (ret < 0) {
667 printk(KERN_ERR "S62X_IDX_X_LSB %s fail\n", __func__);
668 return -1;
669 }
670 v = V(buf[1], buf[0]), mag[data->cvt.map[0]] = (data->cvt.sign[0] > 0) ? v : (4095 - v);
671 v = V(buf[5], buf[4]), mag[data->cvt.map[1]] = (data->cvt.sign[1] > 0) ? v : (4095 - v);
672 v = V(buf[3], buf[2]), mag[data->cvt.map[2]] = (data->cvt.sign[2] > 0) ? v : (4095 - v);
673
674 /* for debug only */
675 mutex_lock(&last_m_data_mutex);
676 memcpy(last_m_data, mag, sizeof(last_m_data));
677 mutex_unlock(&last_m_data_mutex);
678
679 #if DEBUG
680 if (atomic_read(&data->trace) & SS_DATA_DEBUG) {
681 SSMDBG("Get device data: (%d,%d,%d)", mag[0], mag[1], mag[2]);
682 }
683 #endif
684
685 return 0;
686 }
687
688 static int ECS_GetOpenStatus(void)
689 {
690 wait_event_interruptible(open_wq, (atomic_read(&open_flag) != 0));
691 return atomic_read(&open_flag);
692 }
693
694 static int ECS_GetCloseStatus(void)
695 {
696 wait_event_interruptible(open_wq, (atomic_read(&open_flag) <= 0));
697 return atomic_read(&open_flag);
698 }
699
700 /*----------------------------------------------------------------------------*/
701 static int ECS_ReadChipInfo(char *buf, int bufsize)
702 {
703 static const char *supported_chip[] = { "S628", "S628A", "S625A" };
704 int phase = atomic_read(&init_phase);
705 struct i2c_client *client = this_client;
706 struct s62x_i2c_data *data = i2c_get_clientdata(client);
707 unsigned chip = L2CHIP(atomic_read(&data->layout));
708 int ret;
709
710 if (!buf) {
711 return -1;
712 }
713
714 if (!this_client) {
715 *buf = 0;
716 return -2;
717 }
718
719 if (phase != 0) {
720 *buf = 0;
721 return -3;
722 }
723
724 if (chip < sizeof(supported_chip)/sizeof(char*)) {
725 ret = sprintf(buf, supported_chip[chip]);
726 }
727 else {
728 ret = sprintf(buf, "?");
729 }
730
731 return ret;
732 }
733
734 /*----------------------------------------------------------------------------*/
735 static ssize_t show_daemon_value(struct device_driver *ddri, char *buf)
736 {
737 char strbuf[S62X_BUFSIZE];
738 sprintf(strbuf, "s62xd");
739 return sprintf(buf, "%s", strbuf);
740 }
741
742 /*----------------------------------------------------------------------------*/
743 static ssize_t show_chipinfo_value(struct device_driver *ddri, char *buf)
744 {
745 char strbuf[S62X_BUFSIZE];
746 ECS_ReadChipInfo(strbuf, S62X_BUFSIZE);
747 return sprintf(buf, "%s\n", strbuf);
748 }
749
750 /*----------------------------------------------------------------------------*/
751 static ssize_t show_sensordata_value(struct device_driver *ddri, char *buf)
752 {
753 short mdata[SENSOR_DATA_COUNT];
754
755 mutex_lock(&last_m_data_mutex);
756 memcpy(mdata, last_m_data, sizeof(mdata));
757 mutex_unlock(&last_m_data_mutex);
758
759 return sprintf(buf, "%d %d %d\n", mdata[0], mdata[1], mdata[2]);
760 }
761
762 /*----------------------------------------------------------------------------*/
763 static ssize_t show_posturedata_value(struct device_driver *ddri, char *buf)
764 {
765 short tmp[3];
766
767 tmp[0] = sensor_data[0] * CONVERT_O / CONVERT_O_DIV;
768 tmp[1] = sensor_data[1] * CONVERT_O / CONVERT_O_DIV;
769 tmp[2] = sensor_data[2] * CONVERT_O / CONVERT_O_DIV;
770
771 return sprintf(buf, "%d, %d, %d\n", tmp[0], tmp[1], tmp[2]);
772 }
773
774 /*----------------------------------------------------------------------------*/
775 static ssize_t show_layout_value(struct device_driver *ddri, char *buf)
776 {
777 struct i2c_client *client = this_client;
778 struct s62x_i2c_data *data = i2c_get_clientdata(client);
779
780 return sprintf(buf, "(%d, %d)\n[%+2d %+2d %+2d]\n[%+2d %+2d %+2d]\n",
781 data->hw->direction, atomic_read(&data->layout), data->cvt.sign[0], data->cvt.sign[1],
782 data->cvt.sign[2],data->cvt.map[0], data->cvt.map[1], data->cvt.map[2]);
783 }
784 /*----------------------------------------------------------------------------*/
785 static ssize_t store_layout_value(struct device_driver *ddri, const char *buf, size_t count)
786 {
787 struct i2c_client *client = this_client;
788 struct s62x_i2c_data *data = i2c_get_clientdata(client);
789 int layout = 0;
790
791 if (sscanf(buf, "%d", &layout) == 1) {
792 atomic_set(&data->layout, layout);
793 if (!hwmsen_get_convert(L2CVTI(layout), &data->cvt)) {
794 printk(KERN_ERR "HWMSEN_GET_CONVERT function error!\n");
795 } else if (!hwmsen_get_convert(L2CVTI(data->hw->direction), &data->cvt)) {
796 printk(KERN_ERR "invalid layout: %d, restore to %d\n", layout, data->hw->direction);
797 } else {
798 printk(KERN_ERR "invalid layout: (%d, %d)\n", layout, data->hw->direction);
799 hwmsen_get_convert(0, &data->cvt);
800 }
801 } else {
802 printk(KERN_ERR "invalid format = '%s'\n", buf);
803 }
804
805 return count;
806 }
807
808 /*----------------------------------------------------------------------------*/
809 static ssize_t show_status_value(struct device_driver *ddri, char *buf)
810 {
811 struct i2c_client *client = this_client;
812 struct s62x_i2c_data *data = i2c_get_clientdata(client);
813 ssize_t len = 0;
814
815 len += snprintf(buf+len, PAGE_SIZE-len, "VERS: %s (%s)\n", DRIVER_VERSION, ssmd_status);
816
817 if (data->hw) {
818 len += snprintf(buf+len, PAGE_SIZE-len, "CUST: %d %d (%d %d)\n",
819 data->hw->i2c_num, data->hw->direction, data->hw->power_id, data->hw->power_vol);
820 } else {
821 len += snprintf(buf+len, PAGE_SIZE-len, "CUST: NULL\n");
822 }
823
824 switch (atomic_read(&init_phase)) {
825
826 case 2:
827 len += snprintf(buf+len, PAGE_SIZE-len, "IDCK: %d\n", ECS_CheckDevice());
828 break;
829
830 case 1:
831 len += snprintf(buf+len, PAGE_SIZE-len, "INIT: %d\n", ECS_InitDevice());
832 break;
833
834 case 0:
835 len += snprintf(buf+len, PAGE_SIZE-len, "OPEN: %d (%d/%d)\n",
836 atomic_read(&dev_open_count), atomic_read(&m_get_data), atomic_read(&o_get_data));
837 break;
838 }
839
840 return len;
841 }
842
843 /*----------------------------------------------------------------------------*/
844 static ssize_t show_trace_value(struct device_driver *ddri, char *buf)
845 {
846 ssize_t res;
847 struct s62x_i2c_data *obj = i2c_get_clientdata(this_client);
848 if (NULL == obj) {
849 printk(KERN_ERR "S62X data is null!!\n");
850 return 0;
851 }
852
853 res = snprintf(buf, PAGE_SIZE, "0x%04X\n", atomic_read(&obj->trace));
854 return res;
855 }
856
857 /*----------------------------------------------------------------------------*/
858 static ssize_t store_trace_value(struct device_driver *ddri, const char *buf, size_t count)
859 {
860 struct s62x_i2c_data *obj = i2c_get_clientdata(this_client);
861 int trace;
862 if (NULL == obj) {
863 printk(KERN_ERR "S62X data is null!!\n");
864 return 0;
865 }
866
867 if (1 == sscanf(buf, "0x%x", &trace)) {
868 atomic_set(&obj->trace, trace);
869 } else {
870 printk(KERN_ERR "S62X invalid content: '%s', length = %d\n", buf, count);
871 }
872
873 return count;
874 }
875
876 /*----------------------------------------------------------------------------*/
877 static DRIVER_ATTR(daemon, S_IRUGO, show_daemon_value, NULL);
878 static DRIVER_ATTR(chipinfo, S_IRUGO, show_chipinfo_value, NULL);
879 static DRIVER_ATTR(sensordata, S_IRUGO, show_sensordata_value, NULL);
880 static DRIVER_ATTR(posturedata, S_IRUGO, show_posturedata_value, NULL);
881 static DRIVER_ATTR(status, S_IRUGO, show_status_value, NULL);
882 static DRIVER_ATTR(layout, S_IRUGO | S_IWUSR, show_layout_value, store_layout_value);
883 static DRIVER_ATTR(trace, S_IRUGO | S_IWUSR, show_trace_value, store_trace_value);
884
885 /*----------------------------------------------------------------------------*/
886 static struct driver_attribute *s62x_attr_list[] = {
887 &driver_attr_daemon,
888 &driver_attr_chipinfo,
889 &driver_attr_sensordata,
890 &driver_attr_posturedata,
891 &driver_attr_status,
892 &driver_attr_layout,
893 &driver_attr_trace,
894 };
895
896 /*----------------------------------------------------------------------------*/
897 static int s62x_create_attr(struct device_driver *driver)
898 {
899 int idx, err = 0;
900 int num = (int)(sizeof(s62x_attr_list)/sizeof(s62x_attr_list[0]));
901 if (driver == NULL) {
902 return -EINVAL;
903 }
904
905 for (idx = 0; idx < num; idx++) {
906 if ((err = driver_create_file(driver, s62x_attr_list[idx])) !=0 ) {
907 printk(KERN_ERR "S62X driver_create_file (%s) = %d\n", s62x_attr_list[idx]->attr.name, err);
908 break;
909 }
910 }
911 return err;
912 }
913
914 /*----------------------------------------------------------------------------*/
915 static int s62x_delete_attr(struct device_driver *driver)
916 {
917 int idx ,err = 0;
918 int num = (int)(sizeof(s62x_attr_list)/sizeof(s62x_attr_list[0]));
919
920 if (driver == NULL) {
921 return -EINVAL;
922 }
923
924 for (idx = 0; idx < num; idx++) {
925 driver_remove_file(driver, s62x_attr_list[idx]);
926 }
927
928 return err;
929 }
930
931 /*----------------------------------------------------------------------------*/
932 static int s62x_open(struct inode *inode, struct file *file)
933 {
934 int ret = -1;
935 #if DEBUG
936 struct s62x_i2c_data *obj = i2c_get_clientdata(this_client);
937
938 if (atomic_read(&obj->trace) & SS_CTR_DEBUG) {
939 SSMDBG("open device node");
940 }
941 #endif
942
943 atomic_inc(&dev_open_count);
944 ret = nonseekable_open(inode, file);
945
946 return ret;
947 }
948
949 /*----------------------------------------------------------------------------*/
950 static int s62x_release(struct inode *inode, struct file *file)
951 {
952 #if DEBUG
953 struct s62x_i2c_data *obj = i2c_get_clientdata(this_client);
954
955 if (atomic_read(&obj->trace) & SS_CTR_DEBUG) {
956 SSMDBG("release device node");
957 }
958 #endif
959 atomic_dec(&dev_open_count);
960
961 return 0;
962 }
963
964 /*----------------------------------------------------------------------------*/
965 #ifndef MTK_ANDROID_4
966 static int s62x_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
967 #else
968 static long s62x_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
969 #endif
970 {
971 void __user *argp = (void __user *)arg;
972
973 /* NOTE: In this function the size of "char" should be 1-byte. */
974 short mdata[SENSOR_DATA_COUNT];
975 char rwbuf[RWBUF_SIZE];
976 char buff[S62X_BUFSIZE];
977 char mode;
978 short value[12];
979 short delay;
980 int status;
981 int ret = -1;
982
983 switch (cmd) {
984
985 case ECS_IOCTL_WRITE:
986 if (argp == NULL) {
987 SSMDBG("invalid argument.");
988 return -EINVAL;
989 }
990 if (copy_from_user(rwbuf, argp, sizeof(rwbuf))) {
991 SSMDBG("copy_from_user failed.");
992 return -EFAULT;
993 }
994
995 if (rwbuf[0] == 0) {
996 memset(ssmd_status, 0, sizeof(ssmd_status));
997 strncpy(ssmd_status, &rwbuf[1], sizeof(ssmd_status)-1);
998 break;
999 }
1000
1001 if ((rwbuf[0] < 2) || (rwbuf[0] > (RWBUF_SIZE-1))) {
1002 SSMDBG("invalid argument.");
1003 return -EINVAL;
1004 }
1005 ret = I2C_TxData(&rwbuf[1], rwbuf[0]);
1006 if (ret < 0) {
1007 return ret;
1008 }
1009 break;
1010
1011 case ECS_IOCTL_READ:
1012 if (argp == NULL) {
1013 SSMDBG("invalid argument.");
1014 return -EINVAL;
1015 }
1016
1017 if (copy_from_user(rwbuf, argp, sizeof(rwbuf))) {
1018 SSMDBG("copy_from_user failed.");
1019 return -EFAULT;
1020 }
1021
1022 if ((rwbuf[0] < 1) || (rwbuf[0] > (RWBUF_SIZE-1))) {
1023 SSMDBG("invalid argument.");
1024 return -EINVAL;
1025 }
1026 ret = I2C_RxData(&rwbuf[1], rwbuf[0]);
1027 if (ret < 0) {
1028 return ret;
1029 }
1030 if (copy_to_user(argp, rwbuf, rwbuf[0]+1)) {
1031 SSMDBG("copy_to_user failed.");
1032 return -EFAULT;
1033 }
1034 break;
1035
1036 case ECS_IOCTL_SET_MODE:
1037 if (argp == NULL) {
1038 SSMDBG("invalid argument.");
1039 return -EINVAL;
1040 }
1041 if (copy_from_user(&mode, argp, sizeof(mode))) {
1042 SSMDBG("copy_from_user failed.");
1043 return -EFAULT;
1044 }
1045 ret = ECS_SetMode(mode);
1046 if (ret < 0) {
1047 return ret;
1048 }
1049 break;
1050
1051 case ECS_IOCTL_GETDATA:
1052 ret = ECS_GetData(mdata);
1053 if (ret < 0) {
1054 return ret;
1055 }
1056
1057 if (copy_to_user(argp, mdata, sizeof(mdata))) {
1058 SSMDBG("copy_to_user failed.");
1059 return -EFAULT;
1060 }
1061 break;
1062
1063 case ECS_IOCTL_SET_YPR:
1064 if (argp == NULL) {
1065 SSMDBG("invalid argument.");
1066 return -EINVAL;
1067 }
1068 if (copy_from_user(value, argp, sizeof(value))) {
1069 SSMDBG("copy_from_user failed.");
1070 return -EFAULT;
1071 }
1072 ECS_SaveData(value);
1073 break;
1074
1075 case ECS_IOCTL_GET_OPEN_STATUS:
1076 status = ECS_GetOpenStatus();
1077 SSMDBG("ECS_GetOpenStatus returned (%d)", status);
1078 if (copy_to_user(argp, &status, sizeof(status))) {
1079 SSMDBG("copy_to_user failed.");
1080 return -EFAULT;
1081 }
1082 break;
1083
1084 case ECS_IOCTL_GET_CLOSE_STATUS:
1085 status = ECS_GetCloseStatus();
1086 SSMDBG("ECS_GetCloseStatus returned (%d)", status);
1087 if (copy_to_user(argp, &status, sizeof(status))) {
1088 SSMDBG("copy_to_user failed.");
1089 return -EFAULT;
1090 }
1091 break;
1092
1093 case ECS_IOCTL_GET_DELAY:
1094 delay = ssmd_delay;
1095 if (copy_to_user(argp, &delay, sizeof(delay))) {
1096 SSMDBG("copy_to_user failed.");
1097 return -EFAULT;
1098 }
1099 break;
1100
1101 case ECS_IOCTL_GET_PROJECT_NAME:
1102 if (argp == NULL) {
1103 printk(KERN_ERR "S62X IO parameter pointer is NULL!\n");
1104 break;
1105 }
1106
1107 sprintf(buff, PROJECT_ID);
1108 status = ECS_ReadChipInfo(buff + sizeof(PROJECT_ID), S62X_BUFSIZE - sizeof(PROJECT_ID));
1109 status = status < 0 ? sizeof(PROJECT_ID) : sizeof(PROJECT_ID) + status + 1;
1110 if (copy_to_user(argp, buff, status)) {
1111 return -EFAULT;
1112 }
1113 break;
1114
1115 default:
1116 printk(KERN_ERR "S62X %s not supported = 0x%04x\n", __FUNCTION__, cmd);
1117 return -ENOIOCTLCMD;
1118 break;
1119 }
1120
1121 return 0;
1122 }
1123
1124 /*----------------------------------------------------------------------------*/
1125 static struct file_operations s62x_fops = {
1126 #ifndef MTK_ANDROID_4
1127 .owner = THIS_MODULE,
1128 #endif
1129 .open = s62x_open,
1130 .release = s62x_release,
1131 #ifndef MTK_ANDROID_4
1132 .ioctl = s62x_ioctl,
1133 #else
1134 .unlocked_ioctl = s62x_unlocked_ioctl,
1135 #endif
1136 };
1137
1138 /*----------------------------------------------------------------------------*/
1139 static struct miscdevice s62x_device = {
1140 .minor = MISC_DYNAMIC_MINOR,
1141 .name = "msensor",
1142 .fops = &s62x_fops,
1143 };
1144
1145 /*----------------------------------------------------------------------------*/
1146 int s62x_operate(void* self, uint32_t command, void* buff_in, int size_in,
1147 void* buff_out, int size_out, int* actualout)
1148 {
1149 int err = 0;
1150 int value;
1151 hwm_sensor_data* msensor_data;
1152
1153 #if DEBUG
1154 struct i2c_client *client = this_client;
1155 struct s62x_i2c_data *data = i2c_get_clientdata(client);
1156 #endif
1157
1158 #if DEBUG
1159 if (atomic_read(&data->trace) & SS_FUN_DEBUG) {
1160 SSMFUNC("s62x_operate");
1161 }
1162 #endif
1163 switch (command) {
1164
1165 case SENSOR_DELAY:
1166 if ((buff_in == NULL) || (size_in < sizeof(int))) {
1167 printk(KERN_ERR "S62X Set delay parameter error!\n");
1168 err = -EINVAL;
1169 } else {
1170 value = *(int *)buff_in;
1171 if (value <= 20) {
1172 ssmd_delay = 20;
1173 }
1174 ssmd_delay = value;
1175 }
1176 break;
1177
1178 case SENSOR_ENABLE:
1179 if ((buff_in == NULL) || (size_in < sizeof(int))) {
1180 printk(KERN_ERR "S62X Enable sensor parameter error!\n");
1181 err = -EINVAL;
1182 } else {
1183
1184 value = *(int *)buff_in;
1185
1186 if (value == 1) {
1187 atomic_set(&m_flag, 1);
1188 atomic_set(&open_flag, 1);
1189 } else {
1190 atomic_set(&m_get_data, 0);
1191 atomic_set(&m_flag, 0);
1192 if (atomic_read(&o_flag) == 0) {
1193 atomic_set(&open_flag, 0);
1194 }
1195 }
1196 wake_up(&open_wq);
1197 }
1198 break;
1199
1200 case SENSOR_GET_DATA:
1201 atomic_inc(&m_get_data);
1202 if ((buff_out == NULL) || (size_out< sizeof(hwm_sensor_data))) {
1203 printk(KERN_ERR "S62X get sensor data parameter error!\n");
1204 err = -EINVAL;
1205 } else {
1206 msensor_data = (hwm_sensor_data *)buff_out;
1207 mutex_lock(&sensor_data_mutex);
1208
1209 msensor_data->values[0] = sensor_data[9] * CONVERT_M;
1210 msensor_data->values[1] = sensor_data[10] * CONVERT_M;
1211 msensor_data->values[2] = sensor_data[11] * CONVERT_M;
1212 msensor_data->status = sensor_data[4];
1213 msensor_data->value_divide = CONVERT_M_DIV;
1214
1215 mutex_unlock(&sensor_data_mutex);
1216 #if DEBUG
1217 if (atomic_read(&data->trace) & SS_HWM_DEBUG) {
1218 SSMDBG("Hwm get m-sensor data: %d, %d, %d. divide %d, status %d!",
1219 msensor_data->values[0],msensor_data->values[1],msensor_data->values[2],
1220 msensor_data->value_divide,msensor_data->status);
1221 }
1222 #endif
1223 }
1224 break;
1225
1226 default:
1227 printk(KERN_ERR "S62X msensor operate function no this parameter %d!\n", command);
1228 err = -1;
1229 break;
1230 }
1231
1232 return err;
1233 }
1234
1235 /*----------------------------------------------------------------------------*/
1236 int s62x_orientation_operate(void* self, uint32_t command, void* buff_in, int size_in,
1237 void* buff_out, int size_out, int* actualout)
1238 {
1239 int err = 0;
1240 int value;
1241 hwm_sensor_data* osensor_data;
1242 #if DEBUG
1243 struct i2c_client *client = this_client;
1244 struct s62x_i2c_data *data = i2c_get_clientdata(client);
1245 #endif
1246
1247 #if DEBUG
1248 if (atomic_read(&data->trace) & SS_FUN_DEBUG) {
1249 SSMFUNC("s62x_orientation_operate");
1250 }
1251 #endif
1252
1253 switch (command) {
1254
1255 case SENSOR_DELAY:
1256 if ((buff_in == NULL) || (size_in < sizeof(int))) {
1257 printk(KERN_ERR "S62X Set delay parameter error!\n");
1258 err = -EINVAL;
1259 } else {
1260 value = *(int *)buff_in;
1261 if (value <= 20) {
1262 ssmd_delay = 20;
1263 }
1264 ssmd_delay = value;
1265 }
1266 break;
1267
1268 case SENSOR_ENABLE:
1269 if ((buff_in == NULL) || (size_in < sizeof(int))) {
1270 printk(KERN_ERR "S62X Enable sensor parameter error!\n");
1271 err = -EINVAL;
1272 } else {
1273
1274 value = *(int *)buff_in;
1275
1276 if (value == 1) {
1277 atomic_set(&o_flag, 1);
1278 atomic_set(&open_flag, 1);
1279 } else {
1280 atomic_set(&o_get_data, 0);
1281 atomic_set(&o_flag, 0);
1282 if (atomic_read(&m_flag) == 0) {
1283 atomic_set(&open_flag, 0);
1284 }
1285 }
1286 wake_up(&open_wq);
1287 }
1288 break;
1289
1290 case SENSOR_GET_DATA:
1291 atomic_inc(&o_get_data);
1292 if ((buff_out == NULL) || (size_out< sizeof(hwm_sensor_data))) {
1293 printk(KERN_ERR "S62X get sensor data parameter error!\n");
1294 err = -EINVAL;
1295 } else {
1296 osensor_data = (hwm_sensor_data *)buff_out;
1297 mutex_lock(&sensor_data_mutex);
1298
1299 osensor_data->values[0] = sensor_data[0] * CONVERT_O;
1300 osensor_data->values[1] = sensor_data[1] * CONVERT_O;
1301 osensor_data->values[2] = sensor_data[2] * CONVERT_O;
1302 osensor_data->status = sensor_data[4];
1303 osensor_data->value_divide = CONVERT_O_DIV;
1304
1305 mutex_unlock(&sensor_data_mutex);
1306 #if DEBUG
1307 if (atomic_read(&data->trace) & SS_HWM_DEBUG) {
1308 SSMDBG("Hwm get o-sensor data: %d, %d, %d. divide %d, status %d!",
1309 osensor_data->values[0],osensor_data->values[1],osensor_data->values[2],
1310 osensor_data->value_divide,osensor_data->status);
1311 }
1312 #endif
1313 }
1314 break;
1315 default:
1316 printk(KERN_ERR "S62X gsensor operate function no this parameter %d!\n", command);
1317 err = -1;
1318 break;
1319 }
1320
1321 return err;
1322 }
1323
1324 #ifndef CONFIG_HAS_EARLYSUSPEND
1325
1326 /*----------------------------------------------------------------------------*/
1327 static int s62x_suspend(struct i2c_client *client, pm_message_t msg)
1328 {
1329 int err;
1330 struct s62x_i2c_data *obj = i2c_get_clientdata(client)
1331
1332
1333 if (msg.event == PM_EVENT_SUSPEND) {
1334 s62x_power(obj->hw, 0);
1335 }
1336 return 0;
1337 }
1338
1339 /*----------------------------------------------------------------------------*/
1340 static int s62x_resume(struct i2c_client *client)
1341 {
1342 int err;
1343 struct s62x_i2c_data *obj = i2c_get_clientdata(client)
1344
1345
1346 s62x_power(obj->hw, 1);
1347
1348
1349 return 0;
1350 }
1351
1352 #else /*CONFIG_HAS_EARLY_SUSPEND is defined*/
1353
1354 /*----------------------------------------------------------------------------*/
1355 static void s62x_early_suspend(struct early_suspend *h)
1356 {
1357 struct s62x_i2c_data *obj = container_of(h, struct s62x_i2c_data, early_drv);
1358
1359 if (NULL == obj) {
1360 printk(KERN_ERR "S62X null pointer!!\n");
1361 return;
1362 }
1363 }
1364
1365 /*----------------------------------------------------------------------------*/
1366 static void s62x_late_resume(struct early_suspend *h)
1367 {
1368 struct s62x_i2c_data *obj = container_of(h, struct s62x_i2c_data, early_drv);
1369
1370 if (NULL == obj) {
1371 printk(KERN_ERR "S62X null pointer!!\n");
1372 return;
1373 }
1374
1375 s62x_power(obj->hw, 1);
1376 }
1377
1378 #endif /*CONFIG_HAS_EARLYSUSPEND*/
1379
1380 /*----------------------------------------------------------------------------*/
1381 #ifndef MTK_ANDROID_4
1382 static int s62x_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info)
1383 #else
1384 static int s62x_i2c_detect(struct i2c_client *client, struct i2c_board_info *info)
1385 #endif
1386 {
1387 strcpy(info->type, S62X_DEV_NAME);
1388 return 0;
1389 }
1390
1391 /*----------------------------------------------------------------------------*/
1392 #ifdef _MAGIC_KPT_COMMAND
1393 static int magic_kpt_command(const struct i2c_client *client)
1394 {
1395 char cmd1[] = { 0x0A, 0x00 };
1396 char cmd2[] = { 0x0F, 0x1B };
1397 struct i2c_msg msg[] = {
1398 {
1399 .addr = S62X_I2C_ADDR1,
1400 .flags = 0,
1401 .len = sizeof(cmd1),
1402 .buf = cmd1,
1403 },
1404 {
1405 .addr = S62X_I2C_ADDR1,
1406 .flags = 0,
1407 .len = sizeof(cmd2),
1408 .buf = cmd2,
1409 },
1410 };
1411
1412 return i2c_transfer(client->adapter, msg, 2);
1413 }
1414 #endif
1415
1416 /*----------------------------------------------------------------------------*/
1417 #ifdef USE_ALTERNATE_ADDRESS
1418 static int s62x_change_address(const struct i2c_client *client)
1419 {
1420 uint8_t loop_i;
1421 char cmd[] = { S62X_IDX_ECO1, ECO1_DEFAULT };
1422 struct i2c_msg msg[] = {
1423 {
1424 .addr = S62X_I2C_ADDR1,
1425 .flags = 0,
1426 .len = sizeof(cmd),
1427 .buf = cmd,
1428 },
1429 };
1430
1431 for (loop_i = 0; loop_i < 3; loop_i++) {
1432 if (i2c_transfer(client->adapter, msg, 1) > 0) {
1433 return 0;
1434 }
1435 mdelay(10);
1436 }
1437
1438 //printk(KERN_ERR "S62X change address retry over %d\n", loop_i);
1439 return -EIO;
1440 }
1441 #endif
1442
1443 /*----------------------------------------------------------------------------*/
1444 static int s62x_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
1445 {
1446 struct i2c_client *new_client;
1447 struct s62x_i2c_data *data;
1448 int err = 0;
1449 struct hwmsen_object sobj_m, sobj_o;
1450
1451 if (!(data = kmalloc(sizeof(struct s62x_i2c_data), GFP_KERNEL))) {
1452 err = -ENOMEM;
1453 goto exit;
1454 }
1455 memset(data, 0, sizeof(struct s62x_i2c_data));
1456 data->hw = get_cust_mag_hw();
1457
1458 if (hwmsen_get_convert(L2CVTI(data->hw->direction), &data->cvt)) {
1459 printk(KERN_ERR "S62X invalid direction: %d\n", data->hw->direction);
1460 goto exit_init_failed;
1461 }
1462
1463 atomic_set(&data->layout, data->hw->direction);
1464 atomic_set(&data->trace, 0x0000);
1465
1466 mutex_init(&last_m_data_mutex);
1467 mutex_init(&sensor_data_mutex);
1468
1469 init_waitqueue_head(&open_wq);
1470
1471 data->client = client;
1472 new_client = data->client;
1473 i2c_set_clientdata(new_client, data);
1474
1475 this_client = new_client;
1476 this_client->timing = 100;
1477
1478 #ifdef _MAGIC_KPT_COMMAND
1479 magic_kpt_command(client);
1480 #endif
1481
1482 #ifdef USE_ALTERNATE_ADDRESS
1483 err = s62x_change_address(client);
1484 printk(KERN_ERR "S62X address change %s\n", err == 0 ? "OK" : "NG");
1485 #endif
1486
1487 #ifdef _FORCE_PROBE_ERROR
1488 printk(KERN_ERR "S62X force probe error\n");
1489 return -1;
1490 #endif
1491
1492 /* Check connection */
1493 if (ECS_CheckDevice() != 0) {
1494 printk(KERN_ERR "S62X check device connect error\n");
1495 } else {
1496 atomic_set(&init_phase, 1);
1497 if (ECS_InitDevice() != 0) {
1498 printk(KERN_ERR "S62X init device error\n");
1499 } else atomic_set(&init_phase, 0);
1500 }
1501
1502 /* Register sysfs attribute */
1503 if ((err = s62x_create_attr(&ssm_sensor_driver.driver)) != 0) {
1504 printk(KERN_ERR "S62X create attribute err = %d\n", err);
1505 goto exit_sysfs_create_group_failed;
1506 }
1507
1508 #ifdef ENABLE_DUALSTACK_MODE
1509 if (atomic_read(&init_phase) == 2) {
1510 printk(KERN_ERR "S62X dual stack mode exit\n");
1511 goto exit_init_failed;
1512 }
1513 #endif
1514
1515 if ((err = misc_register(&s62x_device)) != 0) {
1516 printk(KERN_ERR "S62X device register failed\n");
1517 goto exit_misc_device_register_failed;
1518 }
1519
1520 sobj_m.self = data;
1521 sobj_m.polling = 1;
1522 sobj_m.sensor_operate = s62x_operate;
1523 if ((err = hwmsen_attach(ID_MAGNETIC, &sobj_m)) != 0) {
1524 printk(KERN_ERR "S62X attach fail = %d\n", err);
1525 goto exit_kfree;
1526 }
1527
1528 sobj_o.self = data;
1529 sobj_o.polling = 1;
1530 sobj_o.sensor_operate = s62x_orientation_operate;
1531 if ((err = hwmsen_attach(ID_ORIENTATION, &sobj_o)) != 0) {
1532 printk(KERN_ERR "S62X attach fail = %d\n", err);
1533 goto exit_kfree;
1534 }
1535
1536 #if CONFIG_HAS_EARLYSUSPEND
1537 data->early_drv.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 1,
1538 data->early_drv.suspend = s62x_early_suspend,
1539 data->early_drv.resume = s62x_late_resume,
1540 register_early_suspend(&data->early_drv);
1541 #endif
1542
1543 SSMDBG("%s: %s", __func__, atomic_read(&init_phase) ? "NG" : "OK");
1544 return 0;
1545
1546 exit_sysfs_create_group_failed:
1547 exit_init_failed:
1548 exit_misc_device_register_failed:
1549 exit_kfree:
1550 kfree(data);
1551
1552 exit:
1553 printk(KERN_ERR "S62X %s: err = %d\n", __func__, err);
1554 return err;
1555 }
1556
1557 /*----------------------------------------------------------------------------*/
1558 static int s62x_i2c_remove(struct i2c_client *client)
1559 {
1560 int err;
1561
1562 if ((err = s62x_delete_attr(&ssm_sensor_driver.driver)) != 0) {
1563 printk(KERN_ERR "S62X delete_attr fail: %d\n", err);
1564 }
1565
1566 this_client = NULL;
1567 i2c_unregister_device(client);
1568 kfree(i2c_get_clientdata(client));
1569 misc_deregister(&s62x_device);
1570 return 0;
1571 }
1572
1573 /*----------------------------------------------------------------------------*/
1574 static int ssm_probe(struct platform_device *pdev)
1575 {
1576 struct mag_hw *hw = get_cust_mag_hw();
1577
1578 s62x_power(hw, 1);
1579
1580 atomic_set(&dev_open_count, 0);
1581 #ifndef MTK_ANDROID_4
1582 s62x_force[0] = hw->i2c_num;
1583 #endif
1584
1585 if (i2c_add_driver(&s62x_i2c_driver)) {
1586 printk(KERN_ERR "S62X add driver error\n");
1587 return -1;
1588 }
1589 return 0;
1590 }
1591
1592 /*----------------------------------------------------------------------------*/
1593 static int ssm_remove(struct platform_device *pdev)
1594 {
1595 struct mag_hw *hw = get_cust_mag_hw();
1596
1597 s62x_power(hw, 0);
1598 atomic_set(&dev_open_count, 0);
1599 i2c_del_driver(&s62x_i2c_driver);
1600 return 0;
1601 }
1602
1603 /*----------------------------------------------------------------------------*/
1604 static int __init s62x_init(void)
1605 {
1606 #ifdef MTK_ANDROID_4
1607 struct mag_hw *hw = get_cust_mag_hw();
1608 printk("%s: i2c_number=%d\n", __func__,hw->i2c_num);
1609 i2c_register_board_info(hw->i2c_num, &i2c_s62x, 1);
1610 #endif
1611 if (platform_driver_register(&ssm_sensor_driver)) {
1612 printk(KERN_ERR "S62X failed to register driver\n");
1613 return -ENODEV;
1614 }
1615 return 0;
1616 }
1617
1618 /*----------------------------------------------------------------------------*/
1619 static void __exit s62x_exit(void)
1620 {
1621 platform_driver_unregister(&ssm_sensor_driver);
1622 }
1623
1624 /*----------------------------------------------------------------------------*/
1625 module_init(s62x_init);
1626 module_exit(s62x_exit);
1627
1628 MODULE_DESCRIPTION("S62X Compass Driver");
1629 MODULE_LICENSE("GPL");
1630 MODULE_VERSION(DRIVER_VERSION);