import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / magnetometer / mag3110 / mag3110.c
1 /* drivers/i2c/chips/mag3110.c - MAG3110 compass driver
2 *
3 * Copyright (C) 2009 AMIT Technology Inc.
4 * Author: Kyle Chen <sw-support@amit-inc.com>
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 #include <linux/interrupt.h>
18 #include <linux/i2c.h>
19 #include <linux/slab.h>
20 #include <linux/irq.h>
21 #include <linux/miscdevice.h>
22 #include <asm/uaccess.h>
23 #include <asm/atomic.h>
24 #include <linux/delay.h>
25 #include <linux/input.h>
26 #include <linux/workqueue.h>
27 #include <linux/kobject.h>
28 #include <linux/platform_device.h>
29 #include <linux/earlysuspend.h>
30
31 #include <linux/hwmsensor.h>
32 #include <linux/hwmsen_dev.h>
33 #include <linux/sensors_io.h>
34
35
36 #include <cust_mag.h>
37 #include <linux/hwmsen_helper.h>
38 #include <linux/ioctl.h>
39
40 #include <mach/mt_typedefs.h>
41 #include <mach/mt_gpio.h>
42 #include <mach/mt_pm_ldo.h>
43
44
45 /*-------------------------MT6516&MT6573 define-------------------------------*/
46
47 #define POWER_NONE_MACRO MT65XX_POWER_NONE
48
49 #define MAG3110_I2C_ADDRESS 0x1c //new Addr=0x0E(Low), old Addr=0x0F(High)
50 /*----------------------------------------------------------------------------*/
51 #define MAG3110_ID 0xC4
52 #define MAG3110_XYZ_DATA_LEN 6
53 #define MAG3110_STATUS_ZYXDR 0x08
54 #define MAG3110_AC_MASK (0x01)
55 #define MAG3110_AC_OFFSET 0
56 #define MAG3110_DR_MODE_MASK (0x7 << 5)
57 #define MAG3110_DR_MODE_OFFSET 5
58
59 /* register enum for mag3110 registers */
60 enum {
61 MAG3110_DR_STATUS = 0x00,
62 MAG3110_OUT_X_MSB,
63 MAG3110_OUT_X_LSB,
64 MAG3110_OUT_Y_MSB,
65 MAG3110_OUT_Y_LSB,
66 MAG3110_OUT_Z_MSB,
67 MAG3110_OUT_Z_LSB,
68 MAG3110_WHO_AM_I,
69
70 MAG3110_OFF_X_MSB,
71 MAG3110_OFF_X_LSB,
72 MAG3110_OFF_Y_MSB,
73 MAG3110_OFF_Y_LSB,
74 MAG3110_OFF_Z_MSB,
75 MAG3110_OFF_Z_LSB,
76
77 MAG3110_DIE_TEMP,
78
79 MAG3110_CTRL_REG1 = 0x10,
80 MAG3110_CTRL_REG2,
81 };
82
83
84 /*----------------------------------------------------------------------------*/
85 #define I2C_DRIVERID_MAG3110 304
86 #define DEBUG 1
87 #define MAG3110_DEV_NAME "mag3110"
88 #define DRIVER_VERSION "1.0.6.11"
89 /*-----------------------------------------------------------------------------*/
90
91 #define MAG3110_BUFSIZE 256
92 #define MAG3110_NORMAL_MODE 0
93 #define MAG3110_FORCE_MODE 1
94 #define MAG3110_IRQ IRQ_EINT9
95
96 // conversion of magnetic data to nT units
97 #define CONVERT_M 25
98 #define ORIENTATION_ACCURACY_RATE 10
99
100 /*----------------------------------------------------------------------------*/
101 #define MAG3110_AXIS_X 0
102 #define MAG3110_AXIS_Y 1
103 #define MAG3110_AXIS_Z 2
104 #define MAG3110_AXES_NUM 3
105 /*----------------------------------------------------------------------------*/
106 #define MSE_TAG "MSENSOR"
107 #define MSE_FUN(f) printk(MSE_TAG" %s\r\n", __FUNCTION__)
108 #define MSE_ERR(fmt, args...) printk(MSE_TAG" %s %d : \r\n"fmt, __FUNCTION__, __LINE__, ##args)
109 #define MSE_LOG(fmt, args...) printk(MSE_TAG fmt, ##args)
110 #define MSE_VER(fmt, args...) ((void)0)
111 /*----------------------------------------------------------------------------*/
112 static DECLARE_WAIT_QUEUE_HEAD(data_ready_wq);
113 static DECLARE_WAIT_QUEUE_HEAD(open_wq);
114
115 static atomic_t open_flag = ATOMIC_INIT(0);
116 static atomic_t m_flag = ATOMIC_INIT(0);
117 static atomic_t o_flag = ATOMIC_INIT(0);
118 /*----------------------------------------------------------------------------*/
119 static struct i2c_client *mag3110_i2c_client = NULL;
120 /*----------------------------------------------------------------------------*/
121 /*----------------------------------------------------------------------------*/
122 static const struct i2c_device_id mag3110_i2c_id[] = {{MAG3110_DEV_NAME,0},{}};
123 static struct i2c_board_info __initdata i2c_mag3110={ I2C_BOARD_INFO("mag3110", (0X1C>>1))};
124 /*the adapter id will be available in customization*/
125 //static unsigned short mag3110_force[] = {0x00, MAG3110_I2C_ADDRESS, I2C_CLIENT_END, I2C_CLIENT_END};
126 //static const unsigned short *const mag3110_forces[] = { mag3110_force, NULL };
127 //static struct i2c_client_address_data mag3110_addr_data = { .forces = mag3110_forces,};
128 /*----------------------------------------------------------------------------*/
129 static int mag3110_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id);
130 static int mag3110_i2c_remove(struct i2c_client *client);
131 //static int mag3110_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info);
132
133 static struct platform_driver ami_sensor_driver;
134
135 /*----------------------------------------------------------------------------*/
136 typedef enum {
137 AMI_TRC_DEBUG = 0x01,
138 } AMI_TRC;
139 /*----------------------------------------------------------------------------*/
140 struct _ami302_data {
141 rwlock_t lock;
142 int mode;
143 int rate;
144 volatile int updated;
145 } mag3110_data;
146 /*----------------------------------------------------------------------------*/
147 struct _mag3110_mid_data {
148 rwlock_t datalock;
149 rwlock_t ctrllock;
150 int controldata[10];
151 unsigned int debug;
152 int yaw;
153 int roll;
154 int pitch;
155 int nmx;
156 int nmy;
157 int nmz;
158 int nax;
159 int nay;
160 int naz;
161 int mag_status;
162 } mag3110_mid_data;
163 /*----------------------------------------------------------------------------*/
164 struct mag3110_i2c_data {
165 struct i2c_client *client;
166 struct mag_hw *hw;
167 struct hwmsen_convert cvt;
168 atomic_t layout;
169 atomic_t trace;
170 #if defined(CONFIG_HAS_EARLYSUSPEND)
171 struct early_suspend early_drv;
172 #endif
173 };
174 /*----------------------------------------------------------------------------*/
175 static struct i2c_driver mag3110_i2c_driver = {
176 .driver = {
177 // .owner = THIS_MODULE,
178 .name = MAG3110_DEV_NAME,
179 },
180 .probe = mag3110_i2c_probe,
181 .remove = mag3110_i2c_remove,
182 // .detect = mag3110_i2c_detect,
183 #if !defined(CONFIG_HAS_EARLYSUSPEND)
184 .suspend = mag3110_suspend,
185 .resume = mag3110_resume,
186 #endif
187 .id_table = mag3110_i2c_id,
188 // .address_data = &mag3110_addr_data,
189 };
190 /*----------------------------------------------------------------------------*/
191 static atomic_t dev_open_count;
192 /*----------------------------------------------------------------------------*/
193 static int hwmsen_read_byte_sr(struct i2c_client *client, u8 addr, u8 *data)
194 {
195 u8 buf;
196 int ret = 0;
197
198 client->addr = client->addr& I2C_MASK_FLAG | I2C_WR_FLAG |I2C_RS_FLAG;
199 buf = addr;
200 ret = i2c_master_send(client, (const char*)&buf, 1<<8 | 1);
201 //ret = i2c_master_send(client, (const char*)&buf, 1);
202 if (ret < 0) {
203 MSE_ERR("send command error!!\n");
204 return -EFAULT;
205 }
206
207 *data = buf;
208 client->addr = client->addr& I2C_MASK_FLAG;
209 return 0;
210 }
211 static int hwmsen_read_block_sr(struct i2c_client *client, u8 addr, u8 *data)
212 {
213 u8 buf[10];
214 int ret = 0;
215 memset(buf, 0, sizeof(u8)*10);
216 client->addr = client->addr& I2C_MASK_FLAG | I2C_WR_FLAG |I2C_RS_FLAG;
217 buf[0] = addr;
218 ret = i2c_master_send(client, (const char*)&buf, 6<<8 | 1);
219 //ret = i2c_master_send(client, (const char*)&buf, 1);
220 if (ret < 0) {
221 MSE_ERR("send command error!!\n");
222 return -EFAULT;
223 }
224
225 *data = buf;
226 client->addr = client->addr& I2C_MASK_FLAG;
227 return 0;
228 }
229
230 static void mag3110_power(struct mag_hw *hw, unsigned int on)
231 {
232 static unsigned int power_on = 0;
233
234 if(hw->power_id != POWER_NONE_MACRO)
235 {
236 MSE_LOG("power %s\n", on ? "on" : "off");
237 if(power_on == on)
238 {
239 MSE_LOG("ignore power control: %d\n", on);
240 }
241 else if(on)
242 {
243 if(!hwPowerOn(hw->power_id, hw->power_vol, "MAG3110"))
244 {
245 MSE_ERR("power on fails!!\n");
246 }
247 }
248 else
249 {
250 if(!hwPowerDown(hw->power_id, "MAG3110"))
251 {
252 MSE_ERR("power off fail!!\n");
253 }
254 }
255 }
256 power_on = on;
257 }
258 /*----------------------------------------------------------------------------*/
259
260 static int mag3110_GetOpenStatus(void)
261 {
262 wait_event_interruptible(open_wq, (atomic_read(&open_flag) != 0));
263 return atomic_read(&open_flag);
264 }
265
266
267 static int mag3110_gpio_config(void)
268 {
269 return 0;
270 }
271
272 static int MAG3110_Chipset_Init(int mode)
273 {
274
275 /* enable automatic resets */
276 u8 databuf[10];
277 int ret = 0;
278 u8 val;
279
280 memset(databuf, 0, sizeof(u8)*10);
281 databuf[0] = MAG3110_CTRL_REG2;
282 databuf[1] = 0x80;
283 ret = i2c_master_send(mag3110_i2c_client, databuf, 2);
284
285 hwmsen_read_byte_sr(mag3110_i2c_client,MAG3110_WHO_AM_I,&val);
286 val = 0;
287 /* set default data rate to 10HZ */
288 hwmsen_read_byte_sr(mag3110_i2c_client,MAG3110_CTRL_REG1,&val);
289 val |= 0x01;
290 memset(databuf, 0, sizeof(u8)*10);
291 databuf[0] = MAG3110_CTRL_REG1;
292 databuf[1] = val;
293 ret = i2c_master_send(mag3110_i2c_client, databuf, 2);
294
295 return 0;
296 }
297 /*----------------------------------------------------------------------------*/
298 static int MAG3110_SetMode(int newmode)
299 {
300
301 }
302 /*----------------------------------------------------------------------------*/
303 static int MAG3110_ReadChipInfo(char *buf, int bufsize)
304 {
305 if((!buf)||(bufsize<=30))
306 {
307 return -1;
308 }
309 if(!mag3110_i2c_client)
310 {
311 *buf = 0;
312 return -2;
313 }
314
315 sprintf(buf, "MAG3110 Chip");
316 return 0;
317 }
318 /*----------------------------------------------------------------------------*/
319 static int MAG3110_ReadSensorData(char *revbuf, int bufsize)
320 {
321 u8 addr = MAG3110_OUT_X_MSB;
322 u8 buf[6] = {0};
323 u8 tmp_data[6];
324 s16 mag[MAG3110_AXES_NUM];
325 s16 output[3];
326 struct mag3110_i2c_data *data = i2c_get_clientdata(mag3110_i2c_client);
327 buf[0] = MAG3110_OUT_X_MSB;
328 mag3110_i2c_client->addr = mag3110_i2c_client->addr& I2C_MASK_FLAG | I2C_WR_FLAG |I2C_RS_FLAG;
329 i2c_master_send(mag3110_i2c_client, (const char*)&buf, 6<<8 | 1);
330 mag3110_i2c_client->addr = mag3110_i2c_client->addr& I2C_MASK_FLAG;
331
332 output[MAG3110_AXIS_X] = (s16)((buf[MAG3110_AXIS_X*2] << 8) |
333 (buf[MAG3110_AXIS_X*2+1]));
334 output[MAG3110_AXIS_Y] = (s16)((buf[MAG3110_AXIS_Y*2] << 8) |
335 (buf[MAG3110_AXIS_Y*2+1]));
336 output[MAG3110_AXIS_Z] = (s16)((buf[MAG3110_AXIS_Z*2] << 8) |
337 (buf[MAG3110_AXIS_Z*2+1]));
338 mag[data->cvt.map[MAG3110_AXIS_X]] = data->cvt.sign[MAG3110_AXIS_X]*output[MAG3110_AXIS_X];
339 mag[data->cvt.map[MAG3110_AXIS_Y]] = data->cvt.sign[MAG3110_AXIS_Y]*output[MAG3110_AXIS_Y];
340 mag[data->cvt.map[MAG3110_AXIS_Z]] = data->cvt.sign[MAG3110_AXIS_Z]*output[MAG3110_AXIS_Z];
341 sprintf(revbuf, "%04x %04x %04x", mag[MAG3110_AXIS_X], mag[MAG3110_AXIS_Y], mag[MAG3110_AXIS_Z]);
342
343
344 return 0;
345 }
346
347
348 /*----------------------------------------------------------------------------*/
349 static int MAG3110_ReadPostureData(char *buf, int bufsize)
350 {
351 if((!buf)||(bufsize<=80))
352 {
353 return -1;
354 }
355
356 read_lock(&mag3110_mid_data.datalock);
357 sprintf(buf, "%d %d %d %d", mag3110_mid_data.yaw, mag3110_mid_data.pitch,
358 mag3110_mid_data.roll, mag3110_mid_data.mag_status);
359 read_unlock(&mag3110_mid_data.datalock);
360 return 0;
361 }
362 /*----------------------------------------------------------------------------*/
363 static int MAG3110_ReadCaliData(char *buf, int bufsize)
364 {
365 if((!buf)||(bufsize<=80))
366 {
367 return -1;
368 }
369
370 read_lock(&mag3110_mid_data.datalock);
371 sprintf(buf, "%d %d %d %d %d %d %d", mag3110_mid_data.nmx, mag3110_mid_data.nmy,
372 mag3110_mid_data.nmz,mag3110_mid_data.nax,mag3110_mid_data.nay,mag3110_mid_data.naz,mag3110_mid_data.mag_status);
373 read_unlock(&mag3110_mid_data.datalock);
374 return 0;
375 }
376 /*----------------------------------------------------------------------------*/
377 static int MAG3110_ReadMiddleControl(char *buf, int bufsize)
378 {
379 if ((!buf)||(bufsize<=80))
380 {
381 return -1;
382 }
383
384 read_lock(&mag3110_mid_data.ctrllock);
385 sprintf(buf, "%d %d %d %d %d %d %d %d %d %d",mag3110_mid_data.controldata[0], mag3110_mid_data.controldata[1],
386 mag3110_mid_data.controldata[2],mag3110_mid_data.controldata[3],mag3110_mid_data.controldata[4],
387 mag3110_mid_data.controldata[5], mag3110_mid_data.controldata[6], mag3110_mid_data.controldata[7],
388 mag3110_mid_data.controldata[8], mag3110_mid_data.controldata[9]);
389 read_unlock(&mag3110_mid_data.ctrllock);
390 return 0;
391 }
392 /*----------------------------------------------------------------------------*/
393 static ssize_t show_chipinfo_value(struct device_driver *ddri, char *buf)
394 {
395 char strbuf[MAG3110_BUFSIZE];
396 MAG3110_ReadChipInfo(strbuf, MAG3110_BUFSIZE);
397 return sprintf(buf, "%s\n", strbuf);
398 }
399 /*----------------------------------------------------------------------------*/
400 static ssize_t show_sensordata_value(struct device_driver *ddri, char *buf)
401 {
402 char strbuf[MAG3110_BUFSIZE];
403 MAG3110_ReadSensorData(strbuf, MAG3110_BUFSIZE);
404 return sprintf(buf, "%s\n", strbuf);
405 }
406 /*----------------------------------------------------------------------------*/
407 static ssize_t show_posturedata_value(struct device_driver *ddri, char *buf)
408 {
409 char strbuf[MAG3110_BUFSIZE];
410 MAG3110_ReadPostureData(strbuf, MAG3110_BUFSIZE);
411 return sprintf(buf, "%s\n", strbuf);
412 }
413 /*----------------------------------------------------------------------------*/
414 static ssize_t show_calidata_value(struct device_driver *ddri, char *buf)
415 {
416 char strbuf[MAG3110_BUFSIZE];
417 MAG3110_ReadCaliData(strbuf, MAG3110_BUFSIZE);
418 return sprintf(buf, "%s\n", strbuf);
419 }
420 /*----------------------------------------------------------------------------*/
421 static ssize_t show_midcontrol_value(struct device_driver *ddri, char *buf)
422 {
423 char strbuf[MAG3110_BUFSIZE];
424 MAG3110_ReadMiddleControl(strbuf, MAG3110_BUFSIZE);
425 return sprintf(buf, "%s\n", strbuf);
426 }
427 /*----------------------------------------------------------------------------*/
428 static ssize_t store_midcontrol_value(struct device_driver *ddri, const char *buf, size_t count)
429 {
430 int p[10];
431 if(10 == sscanf(buf, "%d %d %d %d %d %d %d %d %d %d",&p[0], &p[1], &p[2], &p[3], &p[4],
432 &p[5], &p[6], &p[7], &p[8], &p[9]))
433 {
434 write_lock(&mag3110_mid_data.ctrllock);
435 memcpy(&mag3110_mid_data.controldata[0], &p, sizeof(int)*10);
436 write_unlock(&mag3110_mid_data.ctrllock);
437 }
438 else
439 {
440 MSE_ERR("invalid format\n");
441 }
442 return sizeof(int)*10;
443 }
444 /*----------------------------------------------------------------------------*/
445 static ssize_t show_middebug_value(struct device_driver *ddri, char *buf)
446 {
447 ssize_t len;
448 read_lock(&mag3110_mid_data.ctrllock);
449 len = sprintf(buf, "0x%08X\n", mag3110_mid_data.debug);
450 read_unlock(&mag3110_mid_data.ctrllock);
451
452 return len;
453 }
454 /*----------------------------------------------------------------------------*/
455 static ssize_t store_middebug_value(struct device_driver *ddri, const char *buf, size_t count)
456 {
457 int debug;
458 if(1 == sscanf(buf, "0x%x", &debug))
459 {
460 write_lock(&mag3110_mid_data.ctrllock);
461 mag3110_mid_data.debug = debug;
462 write_unlock(&mag3110_mid_data.ctrllock);
463 }
464 else
465 {
466 MSE_ERR("invalid format\n");
467 }
468 return count;
469 }
470 /*----------------------------------------------------------------------------*/
471 static ssize_t show_mode_value(struct device_driver *ddri, char *buf)
472 {
473 int mode=0;
474 read_lock(&mag3110_data.lock);
475 mode = mag3110_data.mode;
476 read_unlock(&mag3110_data.lock);
477 return sprintf(buf, "%d\n", mode);
478 }
479 /*----------------------------------------------------------------------------*/
480 static ssize_t store_mode_value(struct device_driver *ddri, const char *buf, size_t count)
481 {
482 int mode = 0;
483 sscanf(buf, "%d", &mode);
484 MAG3110_SetMode(mode);
485 return count;
486 }
487 /*----------------------------------------------------------------------------*/
488 static ssize_t show_layout_value(struct device_driver *ddri, char *buf)
489 {
490 struct i2c_client *client = mag3110_i2c_client;
491 struct mag3110_i2c_data *data = i2c_get_clientdata(client);
492
493 return sprintf(buf, "(%d, %d)\n[%+2d %+2d %+2d]\n[%+2d %+2d %+2d]\n",
494 data->hw->direction,atomic_read(&data->layout), data->cvt.sign[0], data->cvt.sign[1],
495 data->cvt.sign[2],data->cvt.map[0], data->cvt.map[1], data->cvt.map[2]);
496 }
497 /*----------------------------------------------------------------------------*/
498 static ssize_t store_layout_value(struct device_driver *ddri, const char *buf, size_t count)
499 {
500 struct i2c_client *client = mag3110_i2c_client;
501 struct mag3110_i2c_data *data = i2c_get_clientdata(client);
502 int layout = 0;
503
504 if(1 == sscanf(buf, "%d", &layout))
505 {
506 atomic_set(&data->layout, layout);
507 if(!hwmsen_get_convert(layout, &data->cvt))
508 {
509 MSE_ERR("HWMSEN_GET_CONVERT function error!\r\n");
510 }
511 else if(!hwmsen_get_convert(data->hw->direction, &data->cvt))
512 {
513 MSE_ERR("invalid layout: %d, restore to %d\n", layout, data->hw->direction);
514 }
515 else
516 {
517 MSE_ERR("invalid layout: (%d, %d)\n", layout, data->hw->direction);
518 hwmsen_get_convert(0, &data->cvt);
519 }
520 }
521 else
522 {
523 MSE_ERR("invalid format = '%s'\n", buf);
524 }
525
526 return count;
527 }
528 /*----------------------------------------------------------------------------*/
529 static ssize_t show_status_value(struct device_driver *ddri, char *buf)
530 {
531 struct i2c_client *client = mag3110_i2c_client;
532 struct mag3110_i2c_data *data = i2c_get_clientdata(client);
533 ssize_t len = 0;
534
535 if(data->hw)
536 {
537 len += snprintf(buf+len, PAGE_SIZE-len, "CUST: %d %d (%d %d)\n",
538 data->hw->i2c_num, data->hw->direction, data->hw->power_id, data->hw->power_vol);
539 }
540 else
541 {
542 len += snprintf(buf+len, PAGE_SIZE-len, "CUST: NULL\n");
543 }
544
545 len += snprintf(buf+len, PAGE_SIZE-len, "OPEN: %d\n", atomic_read(&dev_open_count));
546 return len;
547 }
548 /*----------------------------------------------------------------------------*/
549 static ssize_t show_trace_value(struct device_driver *ddri, char *buf)
550 {
551 ssize_t res;
552 struct mag3110_i2c_data *obj = i2c_get_clientdata(mag3110_i2c_client);
553 if(NULL == obj)
554 {
555 MSE_ERR("mag3110_i2c_data is null!!\n");
556 return 0;
557 }
558
559 res = snprintf(buf, PAGE_SIZE, "0x%04X\n", atomic_read(&obj->trace));
560 return res;
561 }
562 /*----------------------------------------------------------------------------*/
563 static ssize_t store_trace_value(struct device_driver *ddri, const char *buf, size_t count)
564 {
565 struct mag3110_i2c_data *obj = i2c_get_clientdata(mag3110_i2c_client);
566 int trace;
567 if(NULL == obj)
568 {
569 MSE_ERR("mag3110_i2c_data is null!!\n");
570 return 0;
571 }
572
573 if(1 == sscanf(buf, "0x%x", &trace))
574 {
575 atomic_set(&obj->trace, trace);
576 }
577 else
578 {
579 MSE_ERR("invalid content: '%s', length = %d\n", buf, count);
580 }
581
582 return count;
583 }
584
585
586 /*----------------------------------------------------------------------------*/
587 static DRIVER_ATTR(chipinfo, S_IRUGO, show_chipinfo_value, NULL);
588 static DRIVER_ATTR(sensordata, S_IRUGO, show_sensordata_value, NULL);
589 static DRIVER_ATTR(posturedata, S_IRUGO, show_posturedata_value, NULL);
590 static DRIVER_ATTR(calidata, S_IRUGO, show_calidata_value, NULL);
591 static DRIVER_ATTR(midcontrol, S_IRUGO | S_IWUSR, show_midcontrol_value, store_midcontrol_value );
592 static DRIVER_ATTR(middebug, S_IRUGO | S_IWUSR, show_middebug_value, store_middebug_value );
593 static DRIVER_ATTR(mode, S_IRUGO | S_IWUSR, show_mode_value, store_mode_value );
594 static DRIVER_ATTR(layout, S_IRUGO | S_IWUSR, show_layout_value, store_layout_value );
595 static DRIVER_ATTR(status, S_IRUGO, show_status_value, NULL);
596 static DRIVER_ATTR(trace, S_IRUGO | S_IWUSR, show_trace_value, store_trace_value );
597 /*----------------------------------------------------------------------------*/
598 static struct driver_attribute *mag3110_attr_list[] = {
599 &driver_attr_chipinfo,
600 &driver_attr_sensordata,
601 &driver_attr_posturedata,
602 &driver_attr_calidata,
603 &driver_attr_midcontrol,
604 &driver_attr_middebug,
605 &driver_attr_mode,
606 &driver_attr_layout,
607 &driver_attr_status,
608 &driver_attr_trace,
609 };
610 /*----------------------------------------------------------------------------*/
611 static int mag3110_create_attr(struct device_driver *driver)
612 {
613 int idx, err = 0;
614 int num = (int)(sizeof(mag3110_attr_list)/sizeof(mag3110_attr_list[0]));
615 if (driver == NULL)
616 {
617 return -EINVAL;
618 }
619
620 for(idx = 0; idx < num; idx++)
621 {
622 if((err = driver_create_file(driver, mag3110_attr_list[idx])))
623 {
624 MSE_ERR("driver_create_file (%s) = %d\n", mag3110_attr_list[idx]->attr.name, err);
625 break;
626 }
627 }
628 return err;
629 }
630 /*----------------------------------------------------------------------------*/
631 static int mag3110_delete_attr(struct device_driver *driver)
632 {
633 int idx ,err = 0;
634 int num = (int)(sizeof(mag3110_attr_list)/sizeof(mag3110_attr_list[0]));
635
636 if(driver == NULL)
637 {
638 return -EINVAL;
639 }
640
641
642 for(idx = 0; idx < num; idx++)
643 {
644 driver_remove_file(driver, mag3110_attr_list[idx]);
645 }
646
647
648 return err;
649 }
650
651
652 static int mag3110_open(struct inode *inode, struct file *file)
653 {
654 struct mag3110_i2c_data *obj = i2c_get_clientdata(mag3110_i2c_client);
655 int ret = -1;
656 atomic_inc(&dev_open_count);
657
658 if(atomic_read(&obj->trace) & AMI_TRC_DEBUG)
659 {
660 MSE_LOG("Open device node:mag3110\n");
661 }
662 ret = nonseekable_open(inode, file);
663
664 return ret;
665 }
666 /*----------------------------------------------------------------------------*/
667 static int mag3110_release(struct inode *inode, struct file *file)
668 {
669 struct mag3110_i2c_data *obj = i2c_get_clientdata(mag3110_i2c_client);
670 atomic_dec(&dev_open_count);
671 if(atomic_read(&obj->trace) & AMI_TRC_DEBUG)
672 {
673 MSE_LOG("Release device node:mag3110\n");
674 }
675 return 0;
676 }
677 /*----------------------------------------------------------------------------*/
678 static int mag3110_unlocked_ioctl(struct file *file, unsigned int cmd,unsigned long arg)
679 {
680 void __user *argp = (void __user *)arg;
681 int delay;
682 int valuebuf[4];
683 int calidata[7];
684 int controlbuf[10];
685 char strbuf[MAG3110_BUFSIZE];
686 void __user *data;
687 int retval=0;
688 int mode=0;
689 hwm_sensor_data* osensor_data;
690 uint32_t enable;
691 char buff[512];
692 int status; /* for OPEN/CLOSE_STATUS */
693 short sensor_status; /* for Orientation and Msensor status */
694 // MSE_FUN(f);
695
696 switch (cmd)
697 {
698 case ECOMPASS_IOC_GET_DELAY:
699 delay = mag3110_mid_data.controldata[0];
700 if(copy_to_user(argp, &delay, sizeof(delay)))
701 {
702 printk(KERN_ERR "copy_to_user failed.");
703 return -EFAULT;
704 }
705 break;
706
707 case MSENSOR_IOCTL_INIT:
708 read_lock(&mag3110_data.lock);
709 mode = mag3110_data.mode;
710 read_unlock(&mag3110_data.lock);
711 MAG3110_Chipset_Init(mode);
712 break;
713
714 case MSENSOR_IOCTL_SET_POSTURE:
715 data = (void __user *) arg;
716 if(data == NULL)
717 {
718 MSE_ERR("IO parameter pointer is NULL!\r\n");
719 break;
720 }
721
722 if(copy_from_user(&valuebuf, data, sizeof(valuebuf)))
723 {
724 retval = -EFAULT;
725 goto err_out;
726 }
727
728 write_lock(&mag3110_mid_data.datalock);
729 mag3110_mid_data.yaw = valuebuf[0];
730 mag3110_mid_data.pitch = valuebuf[1];
731 mag3110_mid_data.roll = valuebuf[2];
732 mag3110_mid_data.mag_status = valuebuf[3];
733 write_unlock(&mag3110_mid_data.datalock);
734 break;
735
736 case ECOMPASS_IOC_GET_OFLAG:
737 sensor_status = atomic_read(&o_flag);
738 if(copy_to_user(argp, &sensor_status, sizeof(sensor_status)))
739 {
740 MSE_ERR("copy_to_user failed.");
741 return -EFAULT;
742 }
743 break;
744
745 case ECOMPASS_IOC_GET_MFLAG:
746 sensor_status = atomic_read(&m_flag);
747 if(copy_to_user(argp, &sensor_status, sizeof(sensor_status)))
748 {
749 MSE_ERR("copy_to_user failed.");
750 return -EFAULT;
751 }
752 break;
753
754 case ECOMPASS_IOC_GET_OPEN_STATUS:
755 status = mag3110_GetOpenStatus();
756 if(copy_to_user(argp, &status, sizeof(status)))
757 {
758 MSE_LOG("copy_to_user failed.");
759 return -EFAULT;
760 }
761 break;
762
763 case MSENSOR_IOCTL_SET_CALIDATA:
764 data = (void __user *) arg;
765 if (data == NULL)
766 {
767 MSE_ERR("IO parameter pointer is NULL!\r\n");
768 break;
769 }
770 if(copy_from_user(&calidata, data, sizeof(calidata)))
771 {
772 retval = -EFAULT;
773 goto err_out;
774 }
775
776 write_lock(&mag3110_mid_data.datalock);
777 mag3110_mid_data.nmx = calidata[0];
778 mag3110_mid_data.nmy = calidata[1];
779 mag3110_mid_data.nmz = calidata[2];
780 mag3110_mid_data.nax = calidata[3];
781 mag3110_mid_data.nay = calidata[4];
782 mag3110_mid_data.naz = calidata[5];
783 mag3110_mid_data.mag_status = calidata[6];
784 mag3110_mid_data.yaw = calidata[3];
785 mag3110_mid_data.pitch = calidata[4];
786 mag3110_mid_data.roll = calidata[5];
787 write_unlock(&mag3110_mid_data.datalock);
788 break;
789
790 case MSENSOR_IOCTL_READ_CHIPINFO:
791 data = (void __user *) arg;
792 if(data == NULL)
793 {
794 MSE_ERR("IO parameter pointer is NULL!\r\n");
795 break;
796 }
797
798 MAG3110_ReadChipInfo(strbuf, MAG3110_BUFSIZE);
799 if(copy_to_user(data, strbuf, strlen(strbuf)+1))
800 {
801 retval = -EFAULT;
802 goto err_out;
803 }
804 break;
805
806 case MSENSOR_IOCTL_SENSOR_ENABLE:
807
808 data = (void __user *) arg;
809 if (data == NULL)
810 {
811 MSE_ERR("IO parameter pointer is NULL!\r\n");
812 break;
813 }
814 if(copy_from_user(&enable, data, sizeof(enable)))
815 {
816 MSE_ERR("copy_from_user failed.");
817 return -EFAULT;
818 }
819 else
820 {
821 read_lock(&mag3110_mid_data.ctrllock);
822 if(enable == 1)
823 {
824 mag3110_mid_data.controldata[7] |= SENSOR_ORIENTATION;
825 atomic_set(&o_flag, 1);
826 atomic_set(&open_flag, 1);
827 }
828 else
829 {
830 mag3110_mid_data.controldata[7] &= ~SENSOR_ORIENTATION;
831 atomic_set(&o_flag, 0);
832 if(atomic_read(&m_flag) == 0)
833 {
834 atomic_set(&open_flag, 0);
835 }
836 }
837 wake_up(&open_wq);
838 read_unlock(&mag3110_mid_data.ctrllock);
839
840 }
841
842 break;
843
844 case MSENSOR_IOCTL_READ_SENSORDATA:
845 data = (void __user *) arg;
846 if(data == NULL)
847 {
848 MSE_ERR("IO parameter pointer is NULL!\r\n");
849 break;
850 }
851 MAG3110_ReadSensorData(strbuf, MAG3110_BUFSIZE);
852 if(copy_to_user(data, strbuf, strlen(strbuf)+1))
853 {
854 retval = -EFAULT;
855 goto err_out;
856 }
857 break;
858
859 case MSENSOR_IOCTL_READ_FACTORY_SENSORDATA:
860
861 data = (void __user *) arg;
862 if (data == NULL)
863 {
864 MSE_ERR("IO parameter pointer is NULL!\r\n");
865 break;
866 }
867
868 osensor_data = (hwm_sensor_data *)buff;
869
870 read_lock(&mag3110_mid_data.datalock);
871 osensor_data->values[0] = mag3110_mid_data.yaw;
872 osensor_data->values[1] = mag3110_mid_data.pitch;
873 osensor_data->values[2] = mag3110_mid_data.roll;
874 //status = mag3110_mid_data.mag_status;
875 read_unlock(&mag3110_mid_data.datalock);
876
877 osensor_data->value_divide = ORIENTATION_ACCURACY_RATE;
878
879 switch (mag3110_mid_data.mag_status)
880 {
881 case 1: case 2:
882 osensor_data->status = SENSOR_STATUS_ACCURACY_HIGH;
883 break;
884 case 3:
885 osensor_data->status = SENSOR_STATUS_ACCURACY_MEDIUM;
886 break;
887 case 4:
888 osensor_data->status = SENSOR_STATUS_ACCURACY_LOW;
889 break;
890 default:
891 osensor_data->status = SENSOR_STATUS_UNRELIABLE;
892 break;
893 }
894
895
896 sprintf(buff, "%x %x %x %x %x", osensor_data->values[0], osensor_data->values[1],
897 osensor_data->values[2],osensor_data->status,osensor_data->value_divide);
898 if(copy_to_user(data, buff, strlen(buff)+1))
899 {
900 return -EFAULT;
901 }
902
903 break;
904
905 case MSENSOR_IOCTL_READ_POSTUREDATA:
906 data = (void __user *) arg;
907 if(data == NULL)
908 {
909 MSE_ERR("IO parameter pointer is NULL!\r\n");
910 break;
911 }
912
913 MAG3110_ReadPostureData(strbuf, MAG3110_BUFSIZE);
914 if(copy_to_user(data, strbuf, strlen(strbuf)+1))
915 {
916 retval = -EFAULT;
917 goto err_out;
918 }
919 break;
920
921 case MSENSOR_IOCTL_READ_CALIDATA:
922 data = (void __user *) arg;
923 if(data == NULL)
924 {
925 break;
926 }
927 MAG3110_ReadCaliData(strbuf, MAG3110_BUFSIZE);
928 if(copy_to_user(data, strbuf, strlen(strbuf)+1))
929 {
930 retval = -EFAULT;
931 goto err_out;
932 }
933 break;
934
935 case MSENSOR_IOCTL_READ_CONTROL:
936 read_lock(&mag3110_mid_data.ctrllock);
937 memcpy(controlbuf, &mag3110_mid_data.controldata[0], sizeof(controlbuf));
938 read_unlock(&mag3110_mid_data.ctrllock);
939 data = (void __user *) arg;
940 if(data == NULL)
941 {
942 break;
943 }
944 if(copy_to_user(data, controlbuf, sizeof(controlbuf)))
945 {
946 retval = -EFAULT;
947 goto err_out;
948 }
949 break;
950
951 case MSENSOR_IOCTL_SET_CONTROL:
952 data = (void __user *) arg;
953 if(data == NULL)
954 {
955 break;
956 }
957 if(copy_from_user(controlbuf, data, sizeof(controlbuf)))
958 {
959 retval = -EFAULT;
960 goto err_out;
961 }
962 write_lock(&mag3110_mid_data.ctrllock);
963 memcpy(&mag3110_mid_data.controldata[0], controlbuf, sizeof(controlbuf));
964 write_unlock(&mag3110_mid_data.ctrllock);
965 break;
966
967 case MSENSOR_IOCTL_SET_MODE:
968 data = (void __user *) arg;
969 if(data == NULL)
970 {
971 break;
972 }
973 if(copy_from_user(&mode, data, sizeof(mode)))
974 {
975 retval = -EFAULT;
976 goto err_out;
977 }
978
979 MAG3110_SetMode(mode);
980 break;
981
982 default:
983 MSE_ERR("%s not supported = 0x%04x", __FUNCTION__, cmd);
984 retval = -ENOIOCTLCMD;
985 break;
986 }
987
988 err_out:
989 return retval;
990 }
991 /*----------------------------------------------------------------------------*/
992 static struct file_operations mag3110_fops = {
993 // .owner = THIS_MODULE,
994 .open = mag3110_open,
995 .release = mag3110_release,
996 .unlocked_ioctl = mag3110_unlocked_ioctl,
997 };
998 /*----------------------------------------------------------------------------*/
999 static struct miscdevice mag3110_device = {
1000 .minor = MISC_DYNAMIC_MINOR,
1001 .name = "msensor",
1002 .fops = &mag3110_fops,
1003 };
1004 /*----------------------------------------------------------------------------*/
1005 int mag3110_operate(void* self, uint32_t command, void* buff_in, int size_in,
1006 void* buff_out, int size_out, int* actualout)
1007 {
1008 int err = 0;
1009 int value, sample_delay, status;
1010 hwm_sensor_data* msensor_data;
1011
1012 // MSE_FUN(f);
1013 switch (command)
1014 {
1015 case SENSOR_DELAY:
1016 if((buff_in == NULL) || (size_in < sizeof(int)))
1017 {
1018 MSE_ERR("Set delay parameter error!\n");
1019 err = -EINVAL;
1020 }
1021 else
1022 {
1023 value = *(int *)buff_in;
1024 if(value <= 20)
1025 {
1026 sample_delay = 20;
1027 }
1028 sample_delay = value;
1029
1030 mag3110_mid_data.controldata[0] = sample_delay; // Loop Delay
1031 }
1032 break;
1033
1034 case SENSOR_ENABLE:
1035 if((buff_in == NULL) || (size_in < sizeof(int)))
1036 {
1037 MSE_ERR("Enable sensor parameter error!\n");
1038 err = -EINVAL;
1039 }
1040 else
1041 {
1042 value = *(int *)buff_in;
1043 read_lock(&mag3110_mid_data.ctrllock);
1044 if(value == 1)
1045 {
1046 mag3110_mid_data.controldata[7] |= SENSOR_MAGNETIC;
1047 atomic_set(&m_flag, 1);
1048 atomic_set(&open_flag, 1);
1049 }
1050 else
1051 {
1052 mag3110_mid_data.controldata[7] &= ~SENSOR_MAGNETIC;
1053 atomic_set(&m_flag, 0);
1054 if(atomic_read(&o_flag) == 0)
1055 {
1056 atomic_set(&open_flag, 0);
1057 }
1058 }
1059 wake_up(&open_wq);
1060 read_unlock(&mag3110_mid_data.ctrllock);
1061 // TODO: turn device into standby or normal mode
1062 }
1063 break;
1064
1065 case SENSOR_GET_DATA:
1066 if((buff_out == NULL) || (size_out< sizeof(hwm_sensor_data)))
1067 {
1068 MSE_ERR("get sensor data parameter error!\n");
1069 err = -EINVAL;
1070 }
1071 else
1072 {
1073 msensor_data = (hwm_sensor_data *)buff_out;
1074 read_lock(&mag3110_mid_data.datalock);
1075 msensor_data->values[0] = mag3110_mid_data.nmx;
1076 msensor_data->values[1] = mag3110_mid_data.nmy;
1077 msensor_data->values[2] = mag3110_mid_data.nmz;
1078 status = mag3110_mid_data.mag_status;
1079 read_unlock(&mag3110_mid_data.datalock);
1080
1081 msensor_data->values[0] = msensor_data->values[0] * CONVERT_M;
1082 msensor_data->values[1] = msensor_data->values[1] * CONVERT_M;
1083 msensor_data->values[2] = msensor_data->values[2] * CONVERT_M;
1084 msensor_data->value_divide = 100;
1085
1086 switch (status)
1087 {
1088 case 1: case 2:
1089 msensor_data->status = SENSOR_STATUS_ACCURACY_HIGH;
1090 break;
1091 case 3:
1092 msensor_data->status = SENSOR_STATUS_ACCURACY_MEDIUM;
1093 break;
1094 case 4:
1095 msensor_data->status = SENSOR_STATUS_ACCURACY_LOW;
1096 break;
1097 default:
1098 msensor_data->status = SENSOR_STATUS_UNRELIABLE;
1099 break;
1100 }
1101
1102 }
1103 break;
1104 default:
1105 MSE_ERR("msensor operate function no this parameter %d!\n", command);
1106 err = -1;
1107 break;
1108 }
1109
1110 return err;
1111 }
1112
1113 /*----------------------------------------------------------------------------*/
1114 int mag3110_orientation_operate(void* self, uint32_t command, void* buff_in, int size_in,
1115 void* buff_out, int size_out, int* actualout)
1116 {
1117 int err = 0;
1118 int value, sample_delay, status=0;
1119 hwm_sensor_data* osensor_data=NULL;
1120
1121 //MSE_FUN(f);
1122 switch (command)
1123 {
1124 case SENSOR_DELAY:
1125 if((buff_in == NULL) || (size_in < sizeof(int)))
1126 {
1127 MSE_ERR("Set delay parameter error!\n");
1128 err = -EINVAL;
1129 }
1130 else
1131 {
1132 value = *(int *)buff_in;
1133 if(value <= 20)
1134 {
1135 sample_delay = 20;
1136 }
1137 sample_delay = value;
1138
1139 mag3110_mid_data.controldata[0] = sample_delay; // Loop Delay
1140 }
1141 break;
1142
1143 case SENSOR_ENABLE:
1144 if((buff_in == NULL) || (size_in < sizeof(int)))
1145 {
1146 MSE_ERR("Enable sensor parameter error!\n");
1147 err = -EINVAL;
1148 }
1149 else
1150 {
1151 value = *(int *)buff_in;
1152 read_lock(&mag3110_mid_data.ctrllock);
1153 if(value == 1)
1154 {
1155 mag3110_mid_data.controldata[7] |= SENSOR_ORIENTATION;
1156 atomic_set(&o_flag, 1);
1157 atomic_set(&open_flag, 1);
1158 }
1159 else
1160 {
1161 mag3110_mid_data.controldata[7] &= ~SENSOR_ORIENTATION;
1162 atomic_set(&o_flag, 0);
1163 if(atomic_read(&m_flag) == 0)
1164 {
1165 atomic_set(&open_flag, 0);
1166 }
1167 }
1168 wake_up(&open_wq);
1169 read_unlock(&mag3110_mid_data.ctrllock);
1170 // Do nothing
1171 }
1172 break;
1173
1174 case SENSOR_GET_DATA:
1175 if((buff_out == NULL) || (size_out< sizeof(hwm_sensor_data)))
1176 {
1177 MSE_ERR("get sensor data parameter error!\n");
1178 err = -EINVAL;
1179 }
1180 else
1181 {
1182 osensor_data = (hwm_sensor_data *)buff_out;
1183 read_lock(&mag3110_mid_data.datalock);
1184 osensor_data->values[0] = mag3110_mid_data.yaw;
1185 osensor_data->values[1] = mag3110_mid_data.pitch;
1186 osensor_data->values[2] = mag3110_mid_data.roll;
1187 status = mag3110_mid_data.mag_status;
1188 read_unlock(&mag3110_mid_data.datalock);
1189
1190
1191 osensor_data->value_divide = ORIENTATION_ACCURACY_RATE;
1192 }
1193
1194 switch (status)
1195 {
1196 case 1: case 2:
1197 osensor_data->status = SENSOR_STATUS_ACCURACY_HIGH;
1198 break;
1199 case 3:
1200 osensor_data->status = SENSOR_STATUS_ACCURACY_MEDIUM;
1201 break;
1202 case 4:
1203 osensor_data->status = SENSOR_STATUS_ACCURACY_LOW;
1204 break;
1205 default:
1206 osensor_data->status = SENSOR_STATUS_UNRELIABLE;
1207 break;
1208 }
1209 break;
1210 default:
1211 MSE_ERR("gsensor operate function no this parameter %d!\n", command);
1212 err = -1;
1213 break;
1214 }
1215
1216 return err;
1217 }
1218
1219 /*----------------------------------------------------------------------------*/
1220 #ifndef CONFIG_HAS_EARLYSUSPEND
1221 /*----------------------------------------------------------------------------*/
1222 static int mag3110_suspend(struct i2c_client *client, pm_message_t msg)
1223 {
1224 int err;
1225 struct mag3110_i2c_data *obj = i2c_get_clientdata(client)
1226 MSE_FUN();
1227
1228 if(msg.event == PM_EVENT_SUSPEND)
1229 {
1230
1231 mag3110_power(obj->hw, 0);
1232 }
1233 return 0;
1234 }
1235 /*----------------------------------------------------------------------------*/
1236 static int mag3110_resume(struct i2c_client *client)
1237 {
1238 int err;
1239 struct mag3110_i2c_data *obj = i2c_get_clientdata(client)
1240 MSE_FUN();
1241
1242 mag3110_power(obj->hw, 1);
1243
1244 return 0;
1245 }
1246 /*----------------------------------------------------------------------------*/
1247 #else /*CONFIG_HAS_EARLY_SUSPEND is defined*/
1248 /*----------------------------------------------------------------------------*/
1249 static void mag3110_early_suspend(struct early_suspend *h)
1250 {
1251 struct mag3110_i2c_data *obj = container_of(h, struct mag3110_i2c_data, early_drv);
1252 int err;
1253 MSE_FUN();
1254
1255 if(NULL == obj)
1256 {
1257 MSE_ERR("null pointer!!\n");
1258 return;
1259 }
1260
1261 }
1262 /*----------------------------------------------------------------------------*/
1263 static void mag3110_late_resume(struct early_suspend *h)
1264 {
1265 struct mag3110_i2c_data *obj = container_of(h, struct mag3110_i2c_data, early_drv);
1266 int err;
1267 MSE_FUN();
1268
1269 if(NULL == obj)
1270 {
1271 MSE_ERR("null pointer!!\n");
1272 return;
1273 }
1274
1275 mag3110_power(obj->hw, 1);
1276
1277 }
1278 /*----------------------------------------------------------------------------*/
1279 #endif /*CONFIG_HAS_EARLYSUSPEND*/
1280 /*----------------------------------------------------------------------------*/
1281 #if 0
1282 static int mag3110_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info)
1283 {
1284 strcpy(info->type, MAG3110_DEV_NAME);
1285 return 0;
1286 }
1287 #endif
1288 /*----------------------------------------------------------------------------*/
1289 static int mag3110_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
1290 {
1291 struct i2c_client *new_client;
1292 struct mag3110_i2c_data *data;
1293 int err = 0;
1294 struct hwmsen_object sobj_m, sobj_o;
1295
1296 if (!(data = kmalloc(sizeof(struct mag3110_i2c_data), GFP_KERNEL)))
1297 {
1298 err = -ENOMEM;
1299 goto exit;
1300 }
1301 memset(data, 0, sizeof(struct mag3110_i2c_data));
1302
1303 data->hw = get_cust_mag_hw();
1304 if((err = hwmsen_get_convert(data->hw->direction, &data->cvt)))
1305 {
1306 MSE_ERR("invalid direction: %d\n", data->hw->direction);
1307 goto exit;
1308 }
1309
1310 atomic_set(&data->layout, data->hw->direction);
1311 atomic_set(&data->trace, 0);
1312 init_waitqueue_head(&data_ready_wq);
1313 init_waitqueue_head(&open_wq);
1314
1315 data->client = client;
1316 new_client = data->client;
1317 i2c_set_clientdata(new_client, data);
1318
1319 mag3110_i2c_client = new_client;
1320
1321 if((err = MAG3110_Chipset_Init(MAG3110_FORCE_MODE)))
1322 {
1323 goto exit_init_failed;
1324 }
1325 if((err = misc_register(&mag3110_device)))
1326 {
1327 MSE_ERR("mag3110_device register failed\n");
1328 goto exit_misc_device_register_failed; }
1329
1330 sobj_m.self = data;
1331 sobj_m.polling = 1;
1332 sobj_m.sensor_operate = mag3110_operate;
1333 if((err = hwmsen_attach(ID_MAGNETIC, &sobj_m)))
1334 {
1335 MSE_ERR("attach fail = %d\n", err);
1336 goto exit_kfree;
1337 }
1338
1339 sobj_o.self = data;
1340 sobj_o.polling = 1;
1341 sobj_o.sensor_operate = mag3110_orientation_operate;
1342 if((err = hwmsen_attach(ID_ORIENTATION, &sobj_o)))
1343 {
1344 MSE_ERR("attach fail = %d\n", err);
1345 goto exit_kfree;
1346 }
1347
1348 #if CONFIG_HAS_EARLYSUSPEND
1349 data->early_drv.level = EARLY_SUSPEND_LEVEL_STOP_DRAWING - 2,
1350 data->early_drv.suspend = mag3110_early_suspend,
1351 data->early_drv.resume = mag3110_late_resume,
1352 register_early_suspend(&data->early_drv);
1353 #endif
1354
1355 MSE_LOG("%s: OK\n", __func__);
1356 return 0;
1357
1358 exit_misc_device_register_failed:
1359 exit_init_failed:
1360 //i2c_detach_client(new_client);
1361 //exit_misc_device_register_failed:
1362 exit_kfree:
1363 kfree(data);
1364 exit:
1365 MSE_ERR("%s: err = %d\n", __func__, err);
1366 return err;
1367 }
1368 /*----------------------------------------------------------------------------*/
1369 static int mag3110_i2c_remove(struct i2c_client *client)
1370 {
1371 int err;
1372 mag3110_i2c_client = NULL;
1373 i2c_unregister_device(client);
1374 kfree(i2c_get_clientdata(client));
1375 misc_deregister(&mag3110_device);
1376 return 0;
1377 }
1378 /*----------------------------------------------------------------------------*/
1379 static int mag_probe(struct platform_device *pdev)
1380 {
1381 struct mag_hw *hw = get_cust_mag_hw();
1382
1383 mag3110_power(hw, 1);
1384 rwlock_init(&mag3110_mid_data.ctrllock);
1385 rwlock_init(&mag3110_mid_data.datalock);
1386 rwlock_init(&mag3110_data.lock);
1387 mag3110_mid_data.controldata[0] = 20; // Loop Delay
1388 mag3110_mid_data.controldata[1] = 0; // Run
1389 mag3110_mid_data.controldata[2] = 0; // Disable Start-AccCali
1390 mag3110_mid_data.controldata[3] = 1; // Enable Start-Cali
1391 mag3110_mid_data.controldata[4] = 350; // MW-Timout
1392 mag3110_mid_data.controldata[5] = 10; // MW-IIRStrength_M
1393 mag3110_mid_data.controldata[6] = 10; // MW-IIRStrength_G
1394 mag3110_mid_data.controldata[7] = 0; // Active Sensors
1395 mag3110_mid_data.controldata[8] = 0; // Wait for define
1396 mag3110_mid_data.controldata[9] = 0; // Wait for define
1397 atomic_set(&dev_open_count, 0);
1398 //mag3110_force[0] = hw->i2c_num;
1399
1400 if(i2c_add_driver(&mag3110_i2c_driver))
1401 {
1402 MSE_ERR("add driver error\n");
1403 return -1;
1404 }
1405 return 0;
1406 }
1407 /*----------------------------------------------------------------------------*/
1408 static int mag_remove(struct platform_device *pdev)
1409 {
1410 struct mag_hw *hw = get_cust_mag_hw();
1411
1412 MSE_FUN();
1413 mag3110_power(hw, 0);
1414 atomic_set(&dev_open_count, 0);
1415 i2c_del_driver(&mag3110_i2c_driver);
1416 return 0;
1417 }
1418 /*----------------------------------------------------------------------------*/
1419 #if 0
1420 static struct platform_driver mag_sensor_driver = {
1421 .probe = mag_probe,
1422 .remove = mag_remove,
1423 .driver = {
1424 .name = "msensor",
1425 // .owner = THIS_MODULE,
1426 }
1427 };
1428 #endif
1429
1430 #ifdef CONFIG_OF
1431 static const struct of_device_id mag_of_match[] = {
1432 { .compatible = "mediatek,msensor", },
1433 {},
1434 };
1435 #endif
1436
1437 static struct platform_driver mag_sensor_driver =
1438 {
1439 .probe = mag_probe,
1440 .remove = mag_remove,
1441 .driver =
1442 {
1443 .name = "msensor",
1444 #ifdef CONFIG_OF
1445 .of_match_table = mag_of_match,
1446 #endif
1447 }
1448 };
1449
1450 /*----------------------------------------------------------------------------*/
1451 static int __init mag3110_init(void)
1452 {
1453 MSE_FUN();
1454 struct mag_hw *hw = get_cust_mag_hw();
1455 MSE_LOG("%s: i2c_number=%d\n", __func__,hw->i2c_num);
1456 i2c_register_board_info(hw->i2c_num, &i2c_mag3110, 1);
1457 if(platform_driver_register(&mag_sensor_driver))
1458 {
1459 MSE_ERR("failed to register driver");
1460 return -ENODEV;
1461 }
1462 return 0;
1463 }
1464 /*----------------------------------------------------------------------------*/
1465 static void __exit mag3110_exit(void)
1466 {
1467 MSE_FUN();
1468 platform_driver_unregister(&mag_sensor_driver);
1469 }
1470 /*----------------------------------------------------------------------------*/
1471 module_init(mag3110_init);
1472 module_exit(mag3110_exit);
1473 /*----------------------------------------------------------------------------*/
1474 MODULE_AUTHOR("Kyle K.Y. Chen");
1475 MODULE_DESCRIPTION("MAG3110 MI-Sensor driver without DRDY");
1476 MODULE_LICENSE("GPL");
1477 MODULE_VERSION(DRIVER_VERSION);
1478