1 /* drivers/i2c/chips/mag3110.c - MAG3110 compass driver
3 * Copyright (C) 2009 AMIT Technology Inc.
4 * Author: Kyle Chen <sw-support@amit-inc.com>
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.
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.
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>
31 #include <linux/hwmsensor.h>
32 #include <linux/hwmsen_dev.h>
33 #include <linux/sensors_io.h>
37 #include <linux/hwmsen_helper.h>
38 #include <linux/ioctl.h>
40 #include <mach/mt_typedefs.h>
41 #include <mach/mt_gpio.h>
42 #include <mach/mt_pm_ldo.h>
45 /*-------------------------MT6516&MT6573 define-------------------------------*/
47 #define POWER_NONE_MACRO MT65XX_POWER_NONE
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
59 /* register enum for mag3110 registers */
61 MAG3110_DR_STATUS
= 0x00,
79 MAG3110_CTRL_REG1
= 0x10,
84 /*----------------------------------------------------------------------------*/
85 #define I2C_DRIVERID_MAG3110 304
87 #define MAG3110_DEV_NAME "mag3110"
88 #define DRIVER_VERSION "1.0.6.11"
89 /*-----------------------------------------------------------------------------*/
91 #define MAG3110_BUFSIZE 256
92 #define MAG3110_NORMAL_MODE 0
93 #define MAG3110_FORCE_MODE 1
94 #define MAG3110_IRQ IRQ_EINT9
96 // conversion of magnetic data to nT units
98 #define ORIENTATION_ACCURACY_RATE 10
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
);
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);
133 static struct platform_driver ami_sensor_driver
;
135 /*----------------------------------------------------------------------------*/
137 AMI_TRC_DEBUG
= 0x01,
139 /*----------------------------------------------------------------------------*/
140 struct _ami302_data
{
144 volatile int updated
;
146 /*----------------------------------------------------------------------------*/
147 struct _mag3110_mid_data
{
163 /*----------------------------------------------------------------------------*/
164 struct mag3110_i2c_data
{
165 struct i2c_client
*client
;
167 struct hwmsen_convert cvt
;
170 #if defined(CONFIG_HAS_EARLYSUSPEND)
171 struct early_suspend early_drv
;
174 /*----------------------------------------------------------------------------*/
175 static struct i2c_driver mag3110_i2c_driver
= {
177 // .owner = THIS_MODULE,
178 .name
= MAG3110_DEV_NAME
,
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
,
187 .id_table
= mag3110_i2c_id
,
188 // .address_data = &mag3110_addr_data,
190 /*----------------------------------------------------------------------------*/
191 static atomic_t dev_open_count
;
192 /*----------------------------------------------------------------------------*/
193 static int hwmsen_read_byte_sr(struct i2c_client
*client
, u8 addr
, u8
*data
)
198 client
->addr
= client
->addr
& I2C_MASK_FLAG
| I2C_WR_FLAG
|I2C_RS_FLAG
;
200 ret
= i2c_master_send(client
, (const char*)&buf
, 1<<8 | 1);
201 //ret = i2c_master_send(client, (const char*)&buf, 1);
203 MSE_ERR("send command error!!\n");
208 client
->addr
= client
->addr
& I2C_MASK_FLAG
;
211 static int hwmsen_read_block_sr(struct i2c_client
*client
, u8 addr
, u8
*data
)
215 memset(buf
, 0, sizeof(u8
)*10);
216 client
->addr
= client
->addr
& I2C_MASK_FLAG
| I2C_WR_FLAG
|I2C_RS_FLAG
;
218 ret
= i2c_master_send(client
, (const char*)&buf
, 6<<8 | 1);
219 //ret = i2c_master_send(client, (const char*)&buf, 1);
221 MSE_ERR("send command error!!\n");
226 client
->addr
= client
->addr
& I2C_MASK_FLAG
;
230 static void mag3110_power(struct mag_hw
*hw
, unsigned int on
)
232 static unsigned int power_on
= 0;
234 if(hw
->power_id
!= POWER_NONE_MACRO
)
236 MSE_LOG("power %s\n", on
? "on" : "off");
239 MSE_LOG("ignore power control: %d\n", on
);
243 if(!hwPowerOn(hw
->power_id
, hw
->power_vol
, "MAG3110"))
245 MSE_ERR("power on fails!!\n");
250 if(!hwPowerDown(hw
->power_id
, "MAG3110"))
252 MSE_ERR("power off fail!!\n");
258 /*----------------------------------------------------------------------------*/
260 static int mag3110_GetOpenStatus(void)
262 wait_event_interruptible(open_wq
, (atomic_read(&open_flag
) != 0));
263 return atomic_read(&open_flag
);
267 static int mag3110_gpio_config(void)
272 static int MAG3110_Chipset_Init(int mode
)
275 /* enable automatic resets */
280 memset(databuf
, 0, sizeof(u8
)*10);
281 databuf
[0] = MAG3110_CTRL_REG2
;
283 ret
= i2c_master_send(mag3110_i2c_client
, databuf
, 2);
285 hwmsen_read_byte_sr(mag3110_i2c_client
,MAG3110_WHO_AM_I
,&val
);
287 /* set default data rate to 10HZ */
288 hwmsen_read_byte_sr(mag3110_i2c_client
,MAG3110_CTRL_REG1
,&val
);
290 memset(databuf
, 0, sizeof(u8
)*10);
291 databuf
[0] = MAG3110_CTRL_REG1
;
293 ret
= i2c_master_send(mag3110_i2c_client
, databuf
, 2);
297 /*----------------------------------------------------------------------------*/
298 static int MAG3110_SetMode(int newmode
)
302 /*----------------------------------------------------------------------------*/
303 static int MAG3110_ReadChipInfo(char *buf
, int bufsize
)
305 if((!buf
)||(bufsize
<=30))
309 if(!mag3110_i2c_client
)
315 sprintf(buf
, "MAG3110 Chip");
318 /*----------------------------------------------------------------------------*/
319 static int MAG3110_ReadSensorData(char *revbuf
, int bufsize
)
321 u8 addr
= MAG3110_OUT_X_MSB
;
324 s16 mag
[MAG3110_AXES_NUM
];
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
;
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
]);
348 /*----------------------------------------------------------------------------*/
349 static int MAG3110_ReadPostureData(char *buf
, int bufsize
)
351 if((!buf
)||(bufsize
<=80))
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
);
362 /*----------------------------------------------------------------------------*/
363 static int MAG3110_ReadCaliData(char *buf
, int bufsize
)
365 if((!buf
)||(bufsize
<=80))
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
);
376 /*----------------------------------------------------------------------------*/
377 static int MAG3110_ReadMiddleControl(char *buf
, int bufsize
)
379 if ((!buf
)||(bufsize
<=80))
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
);
392 /*----------------------------------------------------------------------------*/
393 static ssize_t
show_chipinfo_value(struct device_driver
*ddri
, char *buf
)
395 char strbuf
[MAG3110_BUFSIZE
];
396 MAG3110_ReadChipInfo(strbuf
, MAG3110_BUFSIZE
);
397 return sprintf(buf
, "%s\n", strbuf
);
399 /*----------------------------------------------------------------------------*/
400 static ssize_t
show_sensordata_value(struct device_driver
*ddri
, char *buf
)
402 char strbuf
[MAG3110_BUFSIZE
];
403 MAG3110_ReadSensorData(strbuf
, MAG3110_BUFSIZE
);
404 return sprintf(buf
, "%s\n", strbuf
);
406 /*----------------------------------------------------------------------------*/
407 static ssize_t
show_posturedata_value(struct device_driver
*ddri
, char *buf
)
409 char strbuf
[MAG3110_BUFSIZE
];
410 MAG3110_ReadPostureData(strbuf
, MAG3110_BUFSIZE
);
411 return sprintf(buf
, "%s\n", strbuf
);
413 /*----------------------------------------------------------------------------*/
414 static ssize_t
show_calidata_value(struct device_driver
*ddri
, char *buf
)
416 char strbuf
[MAG3110_BUFSIZE
];
417 MAG3110_ReadCaliData(strbuf
, MAG3110_BUFSIZE
);
418 return sprintf(buf
, "%s\n", strbuf
);
420 /*----------------------------------------------------------------------------*/
421 static ssize_t
show_midcontrol_value(struct device_driver
*ddri
, char *buf
)
423 char strbuf
[MAG3110_BUFSIZE
];
424 MAG3110_ReadMiddleControl(strbuf
, MAG3110_BUFSIZE
);
425 return sprintf(buf
, "%s\n", strbuf
);
427 /*----------------------------------------------------------------------------*/
428 static ssize_t
store_midcontrol_value(struct device_driver
*ddri
, const char *buf
, size_t count
)
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]))
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
);
440 MSE_ERR("invalid format\n");
442 return sizeof(int)*10;
444 /*----------------------------------------------------------------------------*/
445 static ssize_t
show_middebug_value(struct device_driver
*ddri
, char *buf
)
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
);
454 /*----------------------------------------------------------------------------*/
455 static ssize_t
store_middebug_value(struct device_driver
*ddri
, const char *buf
, size_t count
)
458 if(1 == sscanf(buf
, "0x%x", &debug
))
460 write_lock(&mag3110_mid_data
.ctrllock
);
461 mag3110_mid_data
.debug
= debug
;
462 write_unlock(&mag3110_mid_data
.ctrllock
);
466 MSE_ERR("invalid format\n");
470 /*----------------------------------------------------------------------------*/
471 static ssize_t
show_mode_value(struct device_driver
*ddri
, char *buf
)
474 read_lock(&mag3110_data
.lock
);
475 mode
= mag3110_data
.mode
;
476 read_unlock(&mag3110_data
.lock
);
477 return sprintf(buf
, "%d\n", mode
);
479 /*----------------------------------------------------------------------------*/
480 static ssize_t
store_mode_value(struct device_driver
*ddri
, const char *buf
, size_t count
)
483 sscanf(buf
, "%d", &mode
);
484 MAG3110_SetMode(mode
);
487 /*----------------------------------------------------------------------------*/
488 static ssize_t
show_layout_value(struct device_driver
*ddri
, char *buf
)
490 struct i2c_client
*client
= mag3110_i2c_client
;
491 struct mag3110_i2c_data
*data
= i2c_get_clientdata(client
);
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]);
497 /*----------------------------------------------------------------------------*/
498 static ssize_t
store_layout_value(struct device_driver
*ddri
, const char *buf
, size_t count
)
500 struct i2c_client
*client
= mag3110_i2c_client
;
501 struct mag3110_i2c_data
*data
= i2c_get_clientdata(client
);
504 if(1 == sscanf(buf
, "%d", &layout
))
506 atomic_set(&data
->layout
, layout
);
507 if(!hwmsen_get_convert(layout
, &data
->cvt
))
509 MSE_ERR("HWMSEN_GET_CONVERT function error!\r\n");
511 else if(!hwmsen_get_convert(data
->hw
->direction
, &data
->cvt
))
513 MSE_ERR("invalid layout: %d, restore to %d\n", layout
, data
->hw
->direction
);
517 MSE_ERR("invalid layout: (%d, %d)\n", layout
, data
->hw
->direction
);
518 hwmsen_get_convert(0, &data
->cvt
);
523 MSE_ERR("invalid format = '%s'\n", buf
);
528 /*----------------------------------------------------------------------------*/
529 static ssize_t
show_status_value(struct device_driver
*ddri
, char *buf
)
531 struct i2c_client
*client
= mag3110_i2c_client
;
532 struct mag3110_i2c_data
*data
= i2c_get_clientdata(client
);
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
);
542 len
+= snprintf(buf
+len
, PAGE_SIZE
-len
, "CUST: NULL\n");
545 len
+= snprintf(buf
+len
, PAGE_SIZE
-len
, "OPEN: %d\n", atomic_read(&dev_open_count
));
548 /*----------------------------------------------------------------------------*/
549 static ssize_t
show_trace_value(struct device_driver
*ddri
, char *buf
)
552 struct mag3110_i2c_data
*obj
= i2c_get_clientdata(mag3110_i2c_client
);
555 MSE_ERR("mag3110_i2c_data is null!!\n");
559 res
= snprintf(buf
, PAGE_SIZE
, "0x%04X\n", atomic_read(&obj
->trace
));
562 /*----------------------------------------------------------------------------*/
563 static ssize_t
store_trace_value(struct device_driver
*ddri
, const char *buf
, size_t count
)
565 struct mag3110_i2c_data
*obj
= i2c_get_clientdata(mag3110_i2c_client
);
569 MSE_ERR("mag3110_i2c_data is null!!\n");
573 if(1 == sscanf(buf
, "0x%x", &trace
))
575 atomic_set(&obj
->trace
, trace
);
579 MSE_ERR("invalid content: '%s', length = %d\n", buf
, count
);
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
,
610 /*----------------------------------------------------------------------------*/
611 static int mag3110_create_attr(struct device_driver
*driver
)
614 int num
= (int)(sizeof(mag3110_attr_list
)/sizeof(mag3110_attr_list
[0]));
620 for(idx
= 0; idx
< num
; idx
++)
622 if((err
= driver_create_file(driver
, mag3110_attr_list
[idx
])))
624 MSE_ERR("driver_create_file (%s) = %d\n", mag3110_attr_list
[idx
]->attr
.name
, err
);
630 /*----------------------------------------------------------------------------*/
631 static int mag3110_delete_attr(struct device_driver
*driver
)
634 int num
= (int)(sizeof(mag3110_attr_list
)/sizeof(mag3110_attr_list
[0]));
642 for(idx
= 0; idx
< num
; idx
++)
644 driver_remove_file(driver
, mag3110_attr_list
[idx
]);
652 static int mag3110_open(struct inode
*inode
, struct file
*file
)
654 struct mag3110_i2c_data
*obj
= i2c_get_clientdata(mag3110_i2c_client
);
656 atomic_inc(&dev_open_count
);
658 if(atomic_read(&obj
->trace
) & AMI_TRC_DEBUG
)
660 MSE_LOG("Open device node:mag3110\n");
662 ret
= nonseekable_open(inode
, file
);
666 /*----------------------------------------------------------------------------*/
667 static int mag3110_release(struct inode
*inode
, struct file
*file
)
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
)
673 MSE_LOG("Release device node:mag3110\n");
677 /*----------------------------------------------------------------------------*/
678 static int mag3110_unlocked_ioctl(struct file
*file
, unsigned int cmd
,unsigned long arg
)
680 void __user
*argp
= (void __user
*)arg
;
685 char strbuf
[MAG3110_BUFSIZE
];
689 hwm_sensor_data
* osensor_data
;
692 int status
; /* for OPEN/CLOSE_STATUS */
693 short sensor_status
; /* for Orientation and Msensor status */
698 case ECOMPASS_IOC_GET_DELAY
:
699 delay
= mag3110_mid_data
.controldata
[0];
700 if(copy_to_user(argp
, &delay
, sizeof(delay
)))
702 printk(KERN_ERR
"copy_to_user failed.");
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
);
714 case MSENSOR_IOCTL_SET_POSTURE
:
715 data
= (void __user
*) arg
;
718 MSE_ERR("IO parameter pointer is NULL!\r\n");
722 if(copy_from_user(&valuebuf
, data
, sizeof(valuebuf
)))
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
);
736 case ECOMPASS_IOC_GET_OFLAG
:
737 sensor_status
= atomic_read(&o_flag
);
738 if(copy_to_user(argp
, &sensor_status
, sizeof(sensor_status
)))
740 MSE_ERR("copy_to_user failed.");
745 case ECOMPASS_IOC_GET_MFLAG
:
746 sensor_status
= atomic_read(&m_flag
);
747 if(copy_to_user(argp
, &sensor_status
, sizeof(sensor_status
)))
749 MSE_ERR("copy_to_user failed.");
754 case ECOMPASS_IOC_GET_OPEN_STATUS
:
755 status
= mag3110_GetOpenStatus();
756 if(copy_to_user(argp
, &status
, sizeof(status
)))
758 MSE_LOG("copy_to_user failed.");
763 case MSENSOR_IOCTL_SET_CALIDATA
:
764 data
= (void __user
*) arg
;
767 MSE_ERR("IO parameter pointer is NULL!\r\n");
770 if(copy_from_user(&calidata
, data
, sizeof(calidata
)))
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
);
790 case MSENSOR_IOCTL_READ_CHIPINFO
:
791 data
= (void __user
*) arg
;
794 MSE_ERR("IO parameter pointer is NULL!\r\n");
798 MAG3110_ReadChipInfo(strbuf
, MAG3110_BUFSIZE
);
799 if(copy_to_user(data
, strbuf
, strlen(strbuf
)+1))
806 case MSENSOR_IOCTL_SENSOR_ENABLE
:
808 data
= (void __user
*) arg
;
811 MSE_ERR("IO parameter pointer is NULL!\r\n");
814 if(copy_from_user(&enable
, data
, sizeof(enable
)))
816 MSE_ERR("copy_from_user failed.");
821 read_lock(&mag3110_mid_data
.ctrllock
);
824 mag3110_mid_data
.controldata
[7] |= SENSOR_ORIENTATION
;
825 atomic_set(&o_flag
, 1);
826 atomic_set(&open_flag
, 1);
830 mag3110_mid_data
.controldata
[7] &= ~SENSOR_ORIENTATION
;
831 atomic_set(&o_flag
, 0);
832 if(atomic_read(&m_flag
) == 0)
834 atomic_set(&open_flag
, 0);
838 read_unlock(&mag3110_mid_data
.ctrllock
);
844 case MSENSOR_IOCTL_READ_SENSORDATA
:
845 data
= (void __user
*) arg
;
848 MSE_ERR("IO parameter pointer is NULL!\r\n");
851 MAG3110_ReadSensorData(strbuf
, MAG3110_BUFSIZE
);
852 if(copy_to_user(data
, strbuf
, strlen(strbuf
)+1))
859 case MSENSOR_IOCTL_READ_FACTORY_SENSORDATA
:
861 data
= (void __user
*) arg
;
864 MSE_ERR("IO parameter pointer is NULL!\r\n");
868 osensor_data
= (hwm_sensor_data
*)buff
;
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
);
877 osensor_data
->value_divide
= ORIENTATION_ACCURACY_RATE
;
879 switch (mag3110_mid_data
.mag_status
)
882 osensor_data
->status
= SENSOR_STATUS_ACCURACY_HIGH
;
885 osensor_data
->status
= SENSOR_STATUS_ACCURACY_MEDIUM
;
888 osensor_data
->status
= SENSOR_STATUS_ACCURACY_LOW
;
891 osensor_data
->status
= SENSOR_STATUS_UNRELIABLE
;
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))
905 case MSENSOR_IOCTL_READ_POSTUREDATA
:
906 data
= (void __user
*) arg
;
909 MSE_ERR("IO parameter pointer is NULL!\r\n");
913 MAG3110_ReadPostureData(strbuf
, MAG3110_BUFSIZE
);
914 if(copy_to_user(data
, strbuf
, strlen(strbuf
)+1))
921 case MSENSOR_IOCTL_READ_CALIDATA
:
922 data
= (void __user
*) arg
;
927 MAG3110_ReadCaliData(strbuf
, MAG3110_BUFSIZE
);
928 if(copy_to_user(data
, strbuf
, strlen(strbuf
)+1))
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
;
944 if(copy_to_user(data
, controlbuf
, sizeof(controlbuf
)))
951 case MSENSOR_IOCTL_SET_CONTROL
:
952 data
= (void __user
*) arg
;
957 if(copy_from_user(controlbuf
, data
, sizeof(controlbuf
)))
962 write_lock(&mag3110_mid_data
.ctrllock
);
963 memcpy(&mag3110_mid_data
.controldata
[0], controlbuf
, sizeof(controlbuf
));
964 write_unlock(&mag3110_mid_data
.ctrllock
);
967 case MSENSOR_IOCTL_SET_MODE
:
968 data
= (void __user
*) arg
;
973 if(copy_from_user(&mode
, data
, sizeof(mode
)))
979 MAG3110_SetMode(mode
);
983 MSE_ERR("%s not supported = 0x%04x", __FUNCTION__
, cmd
);
984 retval
= -ENOIOCTLCMD
;
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
,
998 /*----------------------------------------------------------------------------*/
999 static struct miscdevice mag3110_device
= {
1000 .minor
= MISC_DYNAMIC_MINOR
,
1002 .fops
= &mag3110_fops
,
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
)
1009 int value
, sample_delay
, status
;
1010 hwm_sensor_data
* msensor_data
;
1016 if((buff_in
== NULL
) || (size_in
< sizeof(int)))
1018 MSE_ERR("Set delay parameter error!\n");
1023 value
= *(int *)buff_in
;
1028 sample_delay
= value
;
1030 mag3110_mid_data
.controldata
[0] = sample_delay
; // Loop Delay
1035 if((buff_in
== NULL
) || (size_in
< sizeof(int)))
1037 MSE_ERR("Enable sensor parameter error!\n");
1042 value
= *(int *)buff_in
;
1043 read_lock(&mag3110_mid_data
.ctrllock
);
1046 mag3110_mid_data
.controldata
[7] |= SENSOR_MAGNETIC
;
1047 atomic_set(&m_flag
, 1);
1048 atomic_set(&open_flag
, 1);
1052 mag3110_mid_data
.controldata
[7] &= ~SENSOR_MAGNETIC
;
1053 atomic_set(&m_flag
, 0);
1054 if(atomic_read(&o_flag
) == 0)
1056 atomic_set(&open_flag
, 0);
1060 read_unlock(&mag3110_mid_data
.ctrllock
);
1061 // TODO: turn device into standby or normal mode
1065 case SENSOR_GET_DATA
:
1066 if((buff_out
== NULL
) || (size_out
< sizeof(hwm_sensor_data
)))
1068 MSE_ERR("get sensor data parameter error!\n");
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
);
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;
1089 msensor_data
->status
= SENSOR_STATUS_ACCURACY_HIGH
;
1092 msensor_data
->status
= SENSOR_STATUS_ACCURACY_MEDIUM
;
1095 msensor_data
->status
= SENSOR_STATUS_ACCURACY_LOW
;
1098 msensor_data
->status
= SENSOR_STATUS_UNRELIABLE
;
1105 MSE_ERR("msensor operate function no this parameter %d!\n", command
);
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
)
1118 int value
, sample_delay
, status
=0;
1119 hwm_sensor_data
* osensor_data
=NULL
;
1125 if((buff_in
== NULL
) || (size_in
< sizeof(int)))
1127 MSE_ERR("Set delay parameter error!\n");
1132 value
= *(int *)buff_in
;
1137 sample_delay
= value
;
1139 mag3110_mid_data
.controldata
[0] = sample_delay
; // Loop Delay
1144 if((buff_in
== NULL
) || (size_in
< sizeof(int)))
1146 MSE_ERR("Enable sensor parameter error!\n");
1151 value
= *(int *)buff_in
;
1152 read_lock(&mag3110_mid_data
.ctrllock
);
1155 mag3110_mid_data
.controldata
[7] |= SENSOR_ORIENTATION
;
1156 atomic_set(&o_flag
, 1);
1157 atomic_set(&open_flag
, 1);
1161 mag3110_mid_data
.controldata
[7] &= ~SENSOR_ORIENTATION
;
1162 atomic_set(&o_flag
, 0);
1163 if(atomic_read(&m_flag
) == 0)
1165 atomic_set(&open_flag
, 0);
1169 read_unlock(&mag3110_mid_data
.ctrllock
);
1174 case SENSOR_GET_DATA
:
1175 if((buff_out
== NULL
) || (size_out
< sizeof(hwm_sensor_data
)))
1177 MSE_ERR("get sensor data parameter error!\n");
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
);
1191 osensor_data
->value_divide
= ORIENTATION_ACCURACY_RATE
;
1197 osensor_data
->status
= SENSOR_STATUS_ACCURACY_HIGH
;
1200 osensor_data
->status
= SENSOR_STATUS_ACCURACY_MEDIUM
;
1203 osensor_data
->status
= SENSOR_STATUS_ACCURACY_LOW
;
1206 osensor_data
->status
= SENSOR_STATUS_UNRELIABLE
;
1211 MSE_ERR("gsensor operate function no this parameter %d!\n", command
);
1219 /*----------------------------------------------------------------------------*/
1220 #ifndef CONFIG_HAS_EARLYSUSPEND
1221 /*----------------------------------------------------------------------------*/
1222 static int mag3110_suspend(struct i2c_client
*client
, pm_message_t msg
)
1225 struct mag3110_i2c_data
*obj
= i2c_get_clientdata(client
)
1228 if(msg
.event
== PM_EVENT_SUSPEND
)
1231 mag3110_power(obj
->hw
, 0);
1235 /*----------------------------------------------------------------------------*/
1236 static int mag3110_resume(struct i2c_client
*client
)
1239 struct mag3110_i2c_data
*obj
= i2c_get_clientdata(client
)
1242 mag3110_power(obj
->hw
, 1);
1246 /*----------------------------------------------------------------------------*/
1247 #else /*CONFIG_HAS_EARLY_SUSPEND is defined*/
1248 /*----------------------------------------------------------------------------*/
1249 static void mag3110_early_suspend(struct early_suspend
*h
)
1251 struct mag3110_i2c_data
*obj
= container_of(h
, struct mag3110_i2c_data
, early_drv
);
1257 MSE_ERR("null pointer!!\n");
1262 /*----------------------------------------------------------------------------*/
1263 static void mag3110_late_resume(struct early_suspend
*h
)
1265 struct mag3110_i2c_data
*obj
= container_of(h
, struct mag3110_i2c_data
, early_drv
);
1271 MSE_ERR("null pointer!!\n");
1275 mag3110_power(obj
->hw
, 1);
1278 /*----------------------------------------------------------------------------*/
1279 #endif /*CONFIG_HAS_EARLYSUSPEND*/
1280 /*----------------------------------------------------------------------------*/
1282 static int mag3110_i2c_detect(struct i2c_client
*client
, int kind
, struct i2c_board_info
*info
)
1284 strcpy(info
->type
, MAG3110_DEV_NAME
);
1288 /*----------------------------------------------------------------------------*/
1289 static int mag3110_i2c_probe(struct i2c_client
*client
, const struct i2c_device_id
*id
)
1291 struct i2c_client
*new_client
;
1292 struct mag3110_i2c_data
*data
;
1294 struct hwmsen_object sobj_m
, sobj_o
;
1296 if (!(data
= kmalloc(sizeof(struct mag3110_i2c_data
), GFP_KERNEL
)))
1301 memset(data
, 0, sizeof(struct mag3110_i2c_data
));
1303 data
->hw
= get_cust_mag_hw();
1304 if((err
= hwmsen_get_convert(data
->hw
->direction
, &data
->cvt
)))
1306 MSE_ERR("invalid direction: %d\n", data
->hw
->direction
);
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
);
1315 data
->client
= client
;
1316 new_client
= data
->client
;
1317 i2c_set_clientdata(new_client
, data
);
1319 mag3110_i2c_client
= new_client
;
1321 if((err
= MAG3110_Chipset_Init(MAG3110_FORCE_MODE
)))
1323 goto exit_init_failed
;
1325 if((err
= misc_register(&mag3110_device
)))
1327 MSE_ERR("mag3110_device register failed\n");
1328 goto exit_misc_device_register_failed
; }
1332 sobj_m
.sensor_operate
= mag3110_operate
;
1333 if((err
= hwmsen_attach(ID_MAGNETIC
, &sobj_m
)))
1335 MSE_ERR("attach fail = %d\n", err
);
1341 sobj_o
.sensor_operate
= mag3110_orientation_operate
;
1342 if((err
= hwmsen_attach(ID_ORIENTATION
, &sobj_o
)))
1344 MSE_ERR("attach fail = %d\n", err
);
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
);
1355 MSE_LOG("%s: OK\n", __func__
);
1358 exit_misc_device_register_failed
:
1360 //i2c_detach_client(new_client);
1361 //exit_misc_device_register_failed:
1365 MSE_ERR("%s: err = %d\n", __func__
, err
);
1368 /*----------------------------------------------------------------------------*/
1369 static int mag3110_i2c_remove(struct i2c_client
*client
)
1372 mag3110_i2c_client
= NULL
;
1373 i2c_unregister_device(client
);
1374 kfree(i2c_get_clientdata(client
));
1375 misc_deregister(&mag3110_device
);
1378 /*----------------------------------------------------------------------------*/
1379 static int mag_probe(struct platform_device
*pdev
)
1381 struct mag_hw
*hw
= get_cust_mag_hw();
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;
1400 if(i2c_add_driver(&mag3110_i2c_driver
))
1402 MSE_ERR("add driver error\n");
1407 /*----------------------------------------------------------------------------*/
1408 static int mag_remove(struct platform_device
*pdev
)
1410 struct mag_hw
*hw
= get_cust_mag_hw();
1413 mag3110_power(hw
, 0);
1414 atomic_set(&dev_open_count
, 0);
1415 i2c_del_driver(&mag3110_i2c_driver
);
1418 /*----------------------------------------------------------------------------*/
1420 static struct platform_driver mag_sensor_driver
= {
1422 .remove
= mag_remove
,
1425 // .owner = THIS_MODULE,
1431 static const struct of_device_id mag_of_match
[] = {
1432 { .compatible
= "mediatek,msensor", },
1437 static struct platform_driver mag_sensor_driver
=
1440 .remove
= mag_remove
,
1445 .of_match_table
= mag_of_match
,
1450 /*----------------------------------------------------------------------------*/
1451 static int __init
mag3110_init(void)
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
))
1459 MSE_ERR("failed to register driver");
1464 /*----------------------------------------------------------------------------*/
1465 static void __exit
mag3110_exit(void)
1468 platform_driver_unregister(&mag_sensor_driver
);
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
);