#define CONFIG_SENSOR_Mirror 0
#define CONFIG_SENSOR_Flip 0
-#define CONFIG_SENSOR_I2C_SPEED 400000 /* Hz */
+#define CONFIG_SENSOR_I2C_SPEED 100000 /* Hz */
+/* Sensor write register continues by preempt_disable/preempt_enable for current process not be scheduled */
+#define CONFIG_SENSOR_I2C_NOSCHED 1
+#define CONFIG_SENSOR_I2C_RDWRCHK 1
#define CONFIG_SENSOR_TR 1
#define CONFIG_SENSOR_DEBUG 1
struct i2c_client *client;
sensor_info_priv_t info_priv;
int model; /* V4L2_IDENT_OV* codes from v4l2-chip-ident.h */
+#if CONFIG_SENSOR_I2C_NOSCHED
+ atomic_t tasklock_cnt;
+#endif
};
static struct sensor* to_sensor(const struct i2c_client *client)
return container_of(i2c_get_clientdata(client), struct sensor, subdev);
}
+static int sensor_task_lock(struct i2c_client *client, int lock)
+{
+#if CONFIG_SENSOR_I2C_NOSCHED
+ struct sensor *sensor = to_sensor(client);
+
+ if (lock) {
+ if (atomic_read(&sensor->tasklock_cnt) == 0)
+ preempt_disable();
+
+ atomic_add(1, &sensor->tasklock_cnt);
+ } else {
+ atomic_sub(1, &sensor->tasklock_cnt);
+
+ if (atomic_read(&sensor->tasklock_cnt) == 0)
+ preempt_enable();
+ }
+#endif
+ return 0;
+}
+
/* sensor register write */
static int sensor_write(struct i2c_client *client, u16 reg, u8 val)
{
msg->scl_rate = CONFIG_SENSOR_I2C_SPEED; /* ddl@rock-chips.com : 100kHz */
msg->read_type = 0; /* fpga i2c:0==I2C_NORMAL : direct use number not enum for don't want include spi_fpga.h */
- cnt = 1;
+ cnt = 3;
err = -EAGAIN;
- while ((cnt--) && (err < 0)) { /* ddl@rock-chips.com : Transfer again if transent is failed */
+ while ((cnt-- > 0) && (err < 0)) { /* ddl@rock-chips.com : Transfer again if transent is failed */
err = i2c_transfer(client->adapter, msg, 1);
if (err >= 0) {
return 0;
} else {
- SENSOR_TR("\n %s write reg failed, try to write again!\n",SENSOR_NAME_STRING());
+ SENSOR_TR("\n %s write reg(0x%x, val:0x%x) failed, try to write again!\n",SENSOR_NAME_STRING(),reg, val);
udelay(10);
}
}
msg[1].scl_rate = CONFIG_SENSOR_I2C_SPEED; /* ddl@rock-chips.com : 100kHz */
msg[1].read_type = 2; /* fpga i2c:0==I2C_NO_STOP : direct use number not enum for don't want include spi_fpga.h */
- cnt = 1;
+ cnt = 3;
err = -EAGAIN;
- while ((cnt--) && (err < 0)) { /* ddl@rock-chips.com : Transfer again if transent is failed */
+ while ((cnt-- > 0) && (err < 0)) { /* ddl@rock-chips.com : Transfer again if transent is failed */
err = i2c_transfer(client->adapter, msg, 2);
if (err >= 0) {
*val = buf[0];
return 0;
} else {
- SENSOR_TR("\n %s read reg failed, try to read again! reg:0x%x \n",SENSOR_NAME_STRING(),(unsigned int)val);
+ SENSOR_TR("\n %s read reg(0x%x val:0x%x) failed, try to read again! \n",SENSOR_NAME_STRING(),reg, *val);
udelay(10);
}
}
/* write a array of registers */
static int sensor_write_array(struct i2c_client *client, struct reginfo *regarray)
{
- int err, cnt;
+ int err = 0, cnt;
int i = 0;
+ char valchk;
cnt = 0;
+ sensor_task_lock(client, 1);
while (regarray[i].reg != 0)
{
err = sensor_write(client, regarray[i].reg, regarray[i].val);
continue;
} else {
SENSOR_TR("%s..write array failed!!!\n", SENSOR_NAME_STRING());
- return -EPERM;
+ err = -EPERM;
+ goto sensor_write_array_end;
}
+ } else {
+ #if CONFIG_SENSOR_I2C_RDWRCHK
+ sensor_read(client, regarray[i].reg, &valchk);
+ if (valchk != regarray[i].val)
+ SENSOR_TR("%s Reg:0x%x write(0x%x, 0x%x) fail\n",SENSOR_NAME_STRING(), regarray[i].reg, regarray[i].val, valchk);
+ #endif
}
i++;
}
+
+sensor_write_array_end:
+ sensor_task_lock(client,0);
+ return err;
+}
+static int sensor_readchk_array(struct i2c_client *client, struct reginfo *regarray)
+{
+ int cnt;
+ int i = 0;
+ char valchk;
+
+ cnt = 0;
+ valchk = 0;
+ while (regarray[i].reg != 0)
+ {
+ sensor_read(client, regarray[i].reg, &valchk);
+ if (valchk != regarray[i].val)
+ SENSOR_TR("%s Reg:0x%x read(0x%x, 0x%x) error\n",SENSOR_NAME_STRING(), regarray[i].reg, regarray[i].val, valchk);
+
+ i++;
+ }
return 0;
}
SENSOR_DG("\n%s..%s.. \n",SENSOR_NAME_STRING(),__FUNCTION__);
/* soft reset */
+ sensor_task_lock(client,1);
ret = sensor_write(client, 0x3012, 0x80);
if (ret != 0)
{
SENSOR_TR("error: %s initial failed\n",SENSOR_NAME_STRING());
goto sensor_INIT_ERR;
}
-
+ sensor_task_lock(client,0);
icd->user_width = SENSOR_INIT_WIDTH;
icd->user_height = SENSOR_INIT_HEIGHT;
sensor->info_priv.winseqe_cur_addr = (int)SENSOR_INIT_WINSEQADR;
sensor->info_priv.flash = qctrl->default_value;
#endif
- SENSOR_DG("\n%s..%s.. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),__FUNCTION__,icd->user_width,icd->user_height);
+ SENSOR_DG("\n%s..%s.. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),((val == 0)?__FUNCTION__:"sensor_reinit"),icd->user_width,icd->user_height);
return 0;
sensor_INIT_ERR:
SENSOR_DG("\n%s..%s.. \n",SENSOR_NAME_STRING(),__FUNCTION__);
/* ddl@rock-chips.com : all sensor output pin must change to input for other sensor */
+ sensor_task_lock(client, 1);
sensor_write(client, 0x30b0, 0x00);
sensor_write(client, 0x30b1, 0x00);
-
+ sensor_task_lock(client, 0);
return 0;
}
/* Second stage probe - when a capture adapter is there */
icd->ops = &sensor_ops;
icd->y_skip_top = 0;
+ #if CONFIG_SENSOR_I2C_NOSCHED
+ atomic_set(&sensor->tasklock_cnt,0);
+ #endif
ret = sensor_video_probe(icd, client);
if (ret) {
#define CONFIG_SENSOR_Flip 0
#define CONFIG_SENSOR_I2C_SPEED 100000 /* Hz */
+/* Sensor write register continues by preempt_disable/preempt_enable for current process not be scheduled */
+#define CONFIG_SENSOR_I2C_NOSCHED 1
+#define CONFIG_SENSOR_I2C_RDWRCHK 1
#define CONFIG_SENSOR_TR 1
#define CONFIG_SENSOR_DEBUG 1
u16 reg;
u8 val;
};
-
/* init 800*600 SVGA */
static struct reginfo sensor_init_data[] =
{
- {0x0103, 0x01},
{0x3000, 0x0f},
{0x3001, 0xff},
{0x3002, 0xff},
{0x3a0e, 0x06},
{0x3a14, 0x02},
{0x3a15, 0x28},
-
- {0x4708,0x00},
-
+ {0x4708, 0x00},
{0x3623, 0x00},
{0x3634, 0x76},
{0x3701, 0x44},
{0x5062, 0x7d},
{0x5063, 0x69},
{0x3004, 0x20},
+ {0x0100,0x00},
+ {0x0100,0x01},
{0x0000, 0x00}
};
struct i2c_client *client;
sensor_info_priv_t info_priv;
int model; /* V4L2_IDENT_OV* codes from v4l2-chip-ident.h */
+#if CONFIG_SENSOR_I2C_NOSCHED
+ atomic_t tasklock_cnt;
+#endif
};
+
+
static struct sensor* to_sensor(const struct i2c_client *client)
{
return container_of(i2c_get_clientdata(client), struct sensor, subdev);
}
+static int sensor_task_lock(struct i2c_client *client, int lock)
+{
+#if CONFIG_SENSOR_I2C_NOSCHED
+ struct sensor *sensor = to_sensor(client);
+
+ if (lock) {
+ if (atomic_read(&sensor->tasklock_cnt) == 0)
+ preempt_disable();
+
+ atomic_add(1, &sensor->tasklock_cnt);
+ } else {
+ atomic_sub(1, &sensor->tasklock_cnt);
+
+ if (atomic_read(&sensor->tasklock_cnt) == 0)
+ preempt_enable();
+ }
+#endif
+ return 0;
+}
+
/* sensor register write */
static int sensor_write(struct i2c_client *client, u16 reg, u8 val)
{
if (err >= 0) {
return 0;
} else {
- SENSOR_TR("\n %s write reg failed, try to write again!\n",SENSOR_NAME_STRING());
+ SENSOR_TR("\n %s write reg(0x%x, val:0x%x) failed, try to write again!\n",SENSOR_NAME_STRING(),reg, val);
udelay(10);
}
}
*val = buf[0];
return 0;
} else {
- SENSOR_TR("\n %s read reg failed, try to read again! reg:0x%x \n",SENSOR_NAME_STRING(),(unsigned int)val);
+ SENSOR_TR("\n %s read reg(0x%x val:0x%x) failed, try to read again! \n",SENSOR_NAME_STRING(),reg, *val);
udelay(10);
}
}
/* write a array of registers */
static int sensor_write_array(struct i2c_client *client, struct reginfo *regarray)
{
- int err, cnt;
+ int err = 0, cnt;
int i = 0;
- char val00;
+ char valchk;
cnt = 0;
+ sensor_task_lock(client, 1);
while (regarray[i].reg != 0)
{
err = sensor_write(client, regarray[i].reg, regarray[i].val);
continue;
} else {
SENSOR_TR("%s..write array failed!!!\n", SENSOR_NAME_STRING());
- return -EPERM;
+ err = -EPERM;
+ goto sensor_write_array_end;
}
} else {
- sensor_read(client, regarray[i].reg, &val00);
- if (val00 != regarray[i].val)
- SENSOR_TR("%s Reg:0x%x write(0x%x, 0x%x) fail\n",SENSOR_NAME_STRING(), regarray[i].reg, regarray[i].val, val00);
+ #if CONFIG_SENSOR_I2C_RDWRCHK
+ sensor_read(client, regarray[i].reg, &valchk);
+ if (valchk != regarray[i].val)
+ SENSOR_TR("%s Reg:0x%x write(0x%x, 0x%x) fail\n",SENSOR_NAME_STRING(), regarray[i].reg, regarray[i].val, valchk);
+ #endif
}
i++;
}
- return 0;
+
+sensor_write_array_end:
+ sensor_task_lock(client,0);
+ return err;
}
+static int sensor_readchk_array(struct i2c_client *client, struct reginfo *regarray)
+{
+ int cnt;
+ int i = 0;
+ char valchk;
+
+ cnt = 0;
+ valchk = 0;
+ while (regarray[i].reg != 0)
+ {
+ sensor_read(client, regarray[i].reg, &valchk);
+ if (valchk != regarray[i].val)
+ SENSOR_TR("%s Reg:0x%x read(0x%x, 0x%x) error\n",SENSOR_NAME_STRING(), regarray[i].reg, regarray[i].val, valchk);
+ i++;
+ }
+ return 0;
+}
static int sensor_init(struct v4l2_subdev *sd, u32 val)
{
struct i2c_client *client = sd->priv;
SENSOR_DG("\n%s..%s.. \n",SENSOR_NAME_STRING(),__FUNCTION__);
/* soft reset */
+ sensor_task_lock(client,1);
ret = sensor_write(client, 0x0103, 0x01);
if (ret != 0)
{
}
mdelay(5); //delay 5 microseconds
+
/* check if it is an sensor sensor */
ret = sensor_read(client, 0x300a, &value);
if (ret != 0) {
SENSOR_TR("error: %s initial failed\n",SENSOR_NAME_STRING());
goto sensor_INIT_ERR;
}
-
+ sensor_task_lock(client,0);
icd->user_width = SENSOR_INIT_WIDTH;
icd->user_height = SENSOR_INIT_HEIGHT;
sensor->info_priv.winseqe_cur_addr = (int)SENSOR_INIT_WINSEQADR;
sensor->info_priv.flash = qctrl->default_value;
#endif
- SENSOR_DG("\n%s..%s.. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),__FUNCTION__,icd->user_width,icd->user_height);
+ SENSOR_DG("\n%s..%s.. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),((val == 0)?__FUNCTION__:"sensor_reinit"),icd->user_width,icd->user_height);
return 0;
sensor_INIT_ERR:
{
struct i2c_client *client = sd->priv;
u8 reg_val;
- int ret;
-
- ret = sensor_write(client, 0x0103, 0x01);
- SENSOR_DG("\n%s..%s enter, reset ret:0x%x \n",SENSOR_NAME_STRING(),__FUNCTION__,ret);
- msleep(5);
/* ddl@rock-chips.com : all sensor output pin must change to input for other sensor */
+ sensor_task_lock(client, 1);
sensor_read(client,0x3000,®_val);
sensor_write(client, 0x3000, reg_val&0xfc);
sensor_write(client, 0x3001, 0x00);
sensor_read(client,0x3002,®_val);
sensor_write(client, 0x3002, reg_val&0x1f);
-
- msleep(100);
+ sensor_task_lock(client, 0);
return 0;
}
static struct reginfo sensor_power_down_sequence[]=
{
- {0x30ab, 0x00},
- {0x30ad, 0x0a},
- {0x30ae,0x27},
- {0x363b,0x01},
{0x00,0x00}
};
static int sensor_suspend(struct soc_camera_device *icd, pm_message_t pm_msg)
/* Second stage probe - when a capture adapter is there */
icd->ops = &sensor_ops;
icd->y_skip_top = 0;
+ #if CONFIG_SENSOR_I2C_NOSCHED
+ atomic_set(&sensor->tasklock_cnt,0);
+ #endif
ret = sensor_video_probe(icd, client);
if (ret) {
#endif
#define CONFIG_SENSOR_I2C_SPEED 100000 /* Hz */
+/* Sensor write register continues by preempt_disable/preempt_enable for current process not be scheduled */
+#define CONFIG_SENSOR_I2C_NOSCHED 0
+#define CONFIG_SENSOR_I2C_RDWRCHK 1
#define CONFIG_SENSOR_TR 1
#define CONFIG_SENSOR_DEBUG 1
struct sensor_work sensor_wk;
struct mutex wq_lock;
int model; /* V4L2_IDENT_OV* codes from v4l2-chip-ident.h */
+#if CONFIG_SENSOR_I2C_NOSCHED
+ atomic_t tasklock_cnt;
+#endif
};
static struct sensor* to_sensor(const struct i2c_client *client)
return container_of(i2c_get_clientdata(client), struct sensor, subdev);
}
+static int sensor_task_lock(struct i2c_client *client, int lock)
+{
+#if CONFIG_SENSOR_I2C_NOSCHED
+ struct sensor *sensor = to_sensor(client);
+
+ if (lock) {
+ if (atomic_read(&sensor->tasklock_cnt) == 0)
+ preempt_disable();
+
+ atomic_add(1, &sensor->tasklock_cnt);
+ } else {
+ atomic_sub(1, &sensor->tasklock_cnt);
+
+ if (atomic_read(&sensor->tasklock_cnt) == 0)
+ preempt_enable();
+ }
+#endif
+ return 0;
+}
+
/* sensor register write */
static int sensor_write(struct i2c_client *client, u16 reg, u8 val)
{
int err = 0, cnt;
int i = 0;
struct sensor *sensor = to_sensor(client);
- char val00;
+ char valchk;
cnt = 0;
+ sensor_task_lock(client, 1);
while (regarray[i].reg != 0)
{
#if CONFIG_SENSOR_Focus
if ((regarray == sensor_af_firmware) && (sensor->info_priv.enable == 0)) {
SENSOR_DG("%s disable, Download af firmware terminated!\n",SENSOR_NAME_STRING());
err = -EINVAL;
- goto sensor_af_init_end;
+ goto sensor_write_array_end;
}
#endif
} else {
SENSOR_TR("%s..write array failed!!!\n", SENSOR_NAME_STRING());
err = -EPERM;
- goto sensor_af_init_end;
+ goto sensor_write_array_end;
}
} else {
- sensor_read(client, regarray[i].reg, &val00);
- if (val00 != regarray[i].val)
- SENSOR_TR("%s Reg:0x%x write(0x%x, 0x%x) fail\n",SENSOR_NAME_STRING(), regarray[i].reg, regarray[i].val, val00);
-
+ #if CONFIG_SENSOR_I2C_RDWRCHK
+ sensor_read(client, regarray[i].reg, &valchk);
+ if (valchk != regarray[i].val)
+ SENSOR_TR("%s Reg:0x%x write(0x%x, 0x%x) fail\n",SENSOR_NAME_STRING(), regarray[i].reg, regarray[i].val, valchk);
+ #endif
}
i++;
}
#endif
-sensor_af_init_end:
+sensor_write_array_end:
+ sensor_task_lock(client,0);
return err;
}
+static int sensor_readchk_array(struct i2c_client *client, struct reginfo *regarray)
+{
+ int cnt;
+ int i = 0;
+ char valchk;
+
+ cnt = 0;
+ valchk = 0;
+ while (regarray[i].reg != 0)
+ {
+ sensor_read(client, regarray[i].reg, &valchk);
+ if (valchk != regarray[i].val)
+ SENSOR_TR("%s Reg:0x%x read(0x%x, 0x%x) error\n",SENSOR_NAME_STRING(), regarray[i].reg, regarray[i].val, valchk);
+
+ i++;
+ }
+ return 0;
+}
+
#if CONFIG_SENSOR_Focus
struct af_cmdinfo
{
sensor->parameter.preview_line_width = ret_h & 0xff;
sensor->parameter.preview_line_width = (sensor->parameter.preview_line_width << 8) +ret_l;
//Read back AGC Gain for preview
- sensor_read(client,0x350b, &sensor->parameter.preview_gain);
+ sensor_read(client,0x350b, &tp_l);
+ sensor->parameter.preview_gain = tp_l;
sensor->parameter.capture_framerate = 900;
sensor->parameter.preview_framerate = 1500;
SENSOR_DG("\n%s..%s.. \n",SENSOR_NAME_STRING(),__FUNCTION__);
/* soft reset */
+ sensor_task_lock(client,1);
ret = sensor_write(client, 0x3008, 0x80);
if (ret != 0) {
SENSOR_TR("%s soft reset sensor failed\n",SENSOR_NAME_STRING());
SENSOR_TR("error: %s initial failed\n",SENSOR_NAME_STRING());
goto sensor_INIT_ERR;
}
-
+ sensor_task_lock(client,0);
icd->user_width = SENSOR_INIT_WIDTH;
icd->user_height = SENSOR_INIT_HEIGHT;
sensor->info_priv.winseqe_cur_addr = SENSOR_INIT_WINSEQADR;
if (qctrl)
sensor->info_priv.flash = qctrl->default_value;
#endif
- SENSOR_DG("\n%s..%s.. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),__FUNCTION__,icd->user_width,icd->user_height);
+ SENSOR_DG("\n%s..%s.. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),((val == 0)?__FUNCTION__:"sensor_reinit"),icd->user_width,icd->user_height);
return 0;
sensor_INIT_ERR:
static int sensor_deactivate(struct v4l2_subdev *sd)
{
struct i2c_client *client = sd->priv;
- struct sensor *sensor = to_sensor(client);
- int ret;
-
- ret = sensor_write(client, 0x3008, 0x80);
- SENSOR_DG("\n%s..%s enter, reset ret:0x%x \n",SENSOR_NAME_STRING(),__FUNCTION__,ret);
- msleep(5);
/* ddl@rock-chips.com : all sensor output pin must change to input for other sensor */
+ sensor_task_lock(client, 1);
sensor_write(client, 0x3017, 0x00); // FREX,VSYNC,HREF,PCLK,D9-D6
sensor_write(client, 0x3018, 0x03); // D5-D0
sensor_write(client,0x3019,0X00); // STROBE,SDA
SENSOR_DG("\n%s..%s exit \n",SENSOR_NAME_STRING(),__FUNCTION__);
- msleep(100);
+ sensor_task_lock(client, 0);
return 0;
}
static struct reginfo sensor_power_down_sequence[]=
}
if (ret == true)
- SENSOR_DG("%s %dx%d is capture format", __FUNCTION__, f->fmt.pix.width, f->fmt.pix.height);
+ SENSOR_DG("%s %dx%d is capture format\n", __FUNCTION__, f->fmt.pix.width, f->fmt.pix.height);
return ret;
}
static int sensor_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
{
struct i2c_client *client = sd->priv;
struct sensor *sensor = to_sensor(client);
- int val;
if (enable == 1) {
sensor->info_priv.enable = 1;
/* Second stage probe - when a capture adapter is there */
icd->ops = &sensor_ops;
icd->y_skip_top = 0;
+ #if CONFIG_SENSOR_I2C_NOSCHED
+ atomic_set(&sensor->tasklock_cnt,0);
+ #endif
ret = sensor_video_probe(icd, client);
if (ret) {