2 * Copyright (C) 2012 Spreadtrum Communications Inc.
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
15 #include <linux/module.h>
16 #include <linux/kernel.h>
17 #include <linux/init.h>
18 #include <linux/bitops.h>
19 #include <linux/delay.h>
20 #include <linux/kernel.h>
21 #include <linux/kthread.h>
24 #include <video/sensor_drv_k.h>
25 #include <linux/vmalloc.h>
26 #include <linux/sprd_mm.h>
28 #include "sensor_otp.h"
31 #define DW9807_EEPROM_SLAVE_ADDR (0xB0 >> 1)
33 #define SENSOR_SUCCESS 0
34 #define cmr_bzero(b, len) memset((b), '\0', (len))
35 #define cmr_copy(b, a, len) memcpy((b), (a), (len))
43 SENSOR_VAL_TYPE_READ_OTP,
44 } SENSOR_IOCTL_VAL_TYPE;
47 typedef struct _sensor_val_tag {
50 } SENSOR_VAL_T, *SENSOR_VAL_T_PTR;
58 //static struct task_struct * otp_task = NULL;
59 static struct file *pfile = NULL;
60 static struct file *pdebugfile = NULL;
62 static int fw_version_len=0;
63 static uint8_t fw_version[12] = {0};
65 static int z_ioctl (struct file *f, unsigned int cmd, unsigned long arg)
67 if (f->f_op->compat_ioctl)
68 return f->f_op->compat_ioctl (f, cmd, arg);
69 else if (f->f_op->unlocked_ioctl)
70 return f->f_op->unlocked_ioctl (f, cmd, arg);
73 static void Sensor_PowerOn (uint32_t power_on)
75 struct sensor_power_info_tag power_cfg;
78 memset (&power_cfg, 0, sizeof (struct sensor_power_info_tag));
79 power_cfg.op_sensor_id = 0;
85 z_ioctl (pfile, SENSOR_IO_POWER_CFG, &power_cfg);
88 z_ioctl (pfile, SENSOR_IO_SET_MCLK, &mclk);
92 static int Sensor_WriteI2C (uint16_t slave_addr, uint8_t * cmd, uint16_t cmd_length)
94 struct sensor_i2c_tag i2c_tab;
95 int ret = SENSOR_SUCCESS;
97 i2c_tab.slave_addr = slave_addr;
98 i2c_tab.i2c_data = cmd;
99 i2c_tab.i2c_count = cmd_length;
101 MM_TRACE ("Sensor_ReadI2C, slave_addr=0x%x, ptr=0x%p, count=%d\n",
102 i2c_tab.slave_addr, i2c_tab.i2c_data, i2c_tab.i2c_count);
104 ret = z_ioctl (pfile, SENSOR_IO_I2C_WRITE_EXT, &i2c_tab);
109 static int Sensor_ReadI2C (uint16_t slave_addr, uint8_t * cmd, uint16_t cmd_length)
111 struct sensor_i2c_tag i2c_tab;
112 int ret = SENSOR_SUCCESS;
114 i2c_tab.slave_addr = slave_addr;
115 i2c_tab.i2c_data = cmd;
116 i2c_tab.i2c_count = cmd_length;
118 // MM_TRACE("Sensor_ReadI2C, slave_addr=0x%x, ptr=0x%p, count=%d\n",
119 // i2c_tab.slave_addr, i2c_tab.i2c_data, i2c_tab.i2c_count);
121 ret = z_ioctl (pfile, SENSOR_IO_I2C_READ_EXT, &i2c_tab);
126 static uint32_t _read_otp (void *sensor_handle, int sensor_id, int cmd, long arg)
128 uint32_t rtn = SENSOR_SUCCESS;
129 SENSOR_OTP_PARAM_T *param_ptr = (SENSOR_OTP_PARAM_T *) (((SENSOR_VAL_T *) arg)->pval);
130 uint32_t start_addr = 0;
132 uint8_t *buff = NULL;
133 uint8_t cmd_val[3] = { 0x00 };
137 if (NULL == param_ptr) {
141 MM_TRACE ("SENSOR_s5k4h5yc: _s5k4h5yc_read_otp E\n");
146 rtn = Sensor_WriteI2C (DW9807_EEPROM_SLAVE_ADDR, (uint8_t *) & cmd_val[0], cmd_len);
147 udelay (1000); //usleep(1000);
149 MM_TRACE ("write i2c rtn %d type %d\n", rtn, param_ptr->type);
151 buff = param_ptr->buff;
152 if (SENSOR_OTP_PARAM_NORMAL == param_ptr->type) {
153 start_addr = param_ptr->start_addr;
155 } else if (SENSOR_OTP_PARAM_CHECKSUM == param_ptr->type) {
158 } else if (SENSOR_OTP_PARAM_READBYTE == param_ptr->type) {
159 start_addr = param_ptr->start_addr;
160 len = param_ptr->len;
161 } else if (SENSOR_OTP_PARAM_FW_VERSION == param_ptr->type) {
167 for (i = 0; i < len; i++) {
168 cmd_val[0] = ((start_addr + i) >> 8) & 0xff;
169 cmd_val[1] = (start_addr + i) & 0xff;
170 rtn = Sensor_ReadI2C (DW9807_EEPROM_SLAVE_ADDR, (uint8_t *) & cmd_val[0], cmd_len);
171 if (SENSOR_SUCCESS == rtn) {
172 buff[i] = (cmd_val[0]) & 0xff;
174 //MM_TRACE("rtn %d value %d addr 0x%x\ns", rtn, buff[i], start_addr + i);
176 param_ptr->len = len;
178 MM_TRACE ("SENSOR_s5k4h5yc: _s5k4h5yc_read_otp X\n");
184 int sensor_reloadinfo_thread (void *data)
188 SENSOR_OTP_PARAM_T *param_ptr = (SENSOR_OTP_PARAM_T *) data;
190 uint32_t clock = 400000;
192 loff_t otp_start_addr = 0;
193 uint32_t otp_data_len = 0;
195 struct isp_data_t checksum_otp;
196 struct isp_data_t sensor_otp;
197 uint32_t is_need_checksum = 0;
200 MM_TRACE ("sensor_reloadinfo_thread start\n");
202 cmr_bzero (&checksum_otp, sizeof (checksum_otp));
203 cmr_bzero (&sensor_otp, sizeof (sensor_otp));
204 cmr_bzero (param_ptr, sizeof (SENSOR_OTP_PARAM_T));
207 pfile = filp_open ("/dev/sprd_sensor", O_RDWR, 0);
211 MM_TRACE ("open /dev/sprd_sensor mdelay 100 \n");
213 MM_TRACE ("open /dev/sprd_sensor failed\n");
223 ret = z_ioctl (pfile, SENSOR_IO_SET_I2CCLOCK, &clock);
228 cmr_bzero (param_ptr, sizeof (SENSOR_OTP_PARAM_T));
229 param_ptr->start_addr = 0;
230 param_ptr->len = fw_version_len;
231 param_ptr->buff = fw_version;
232 param_ptr->type = SENSOR_OTP_PARAM_FW_VERSION;
233 val.type = SENSOR_VAL_TYPE_READ_OTP;
234 val.pval = param_ptr;
235 ret = _read_otp (NULL, 0, SENSOR_ACCESS_VAL, (long) &val);
236 if (ret || 0 == param_ptr->len) {
237 MM_TRACE ("read otp data failed\n");
242 checksum_otp.size = 4;
243 checksum_otp.data_ptr = vmalloc (checksum_otp.size);
244 if (NULL == checksum_otp.data_ptr) {
245 MM_TRACE ("malloc checksum_otp buffer failed\n");
249 cmr_bzero (param_ptr, sizeof (SENSOR_OTP_PARAM_T));
250 param_ptr->start_addr = 0;
251 param_ptr->len = checksum_otp.size;
252 param_ptr->buff = checksum_otp.data_ptr;
253 param_ptr->type = SENSOR_OTP_PARAM_CHECKSUM;
254 val.type = SENSOR_VAL_TYPE_READ_OTP;
255 val.pval = param_ptr;
256 ret = _read_otp (NULL, 0, SENSOR_ACCESS_VAL, (long) &val);
257 if (ret || 0 == param_ptr->len) {
258 MM_TRACE ("read otp data checksum failed\n");
262 /*read lsc, awb from real otp */
263 //camera_calibrationconfigure_load(&otp_start_addr, &otp_data_len);
265 sensor_otp.data_ptr = vmalloc (otp_data_len);
266 if (NULL == sensor_otp.data_ptr) {
267 MM_TRACE ("malloc random lsc file failed\n");
271 cmr_bzero (param_ptr, sizeof (SENSOR_OTP_PARAM_T));
272 param_ptr->start_addr = 0;
274 param_ptr->buff = sensor_otp.data_ptr;
275 param_ptr->type = SENSOR_OTP_PARAM_NORMAL;
276 val.type = SENSOR_VAL_TYPE_READ_OTP;
277 val.pval = param_ptr;
278 ret = _read_otp (NULL, 0, SENSOR_ACCESS_VAL, (long) &val);
279 if (ret || 0 == param_ptr->len) {
280 MM_TRACE ("read otp data failed\n");
283 param_ptr->golden.size = checksum_otp.size;
284 param_ptr->golden.data_ptr = checksum_otp.data_ptr;
286 pdebugfile = filp_open ("/data/otp.bin", O_CREAT|O_RDWR, 0);
287 if (IS_ERR (pdebugfile)) {
288 MM_TRACE ("open /data/otp.bin failed\n");
291 vfs_write(pdebugfile, param_ptr->buff,otp_data_len, &otp_start_addr);
292 filp_close(pdebugfile, NULL);
297 filp_close (pfile, NULL);
298 MM_TRACE ("sensor_reloadinfo_thread end\n");
302 void sensor_get_fw_version_otp(void *read_fw_version)
304 if(read_fw_version) {
305 sprintf(read_fw_version, fw_version);