From ca64f75d5a10df2c61e235b7c4f86de2be0eef4e Mon Sep 17 00:00:00 2001 From: ddl Date: Mon, 31 Jan 2011 07:16:11 +0800 Subject: [PATCH] camera: fix sensor driver obtain i2c fail in atomic, so check i2c bus is locked or not before into atomic --- drivers/media/video/ov2655.c | 21 ++++++++++++-- drivers/media/video/ov2659.c | 36 +++++++++++++++++++----- drivers/media/video/ov5640.c | 21 ++++++++++++-- drivers/media/video/ov5640_af_firmware.c | 2 +- drivers/media/video/ov5642.c | 21 ++++++++++++-- drivers/media/video/ov5642_af_firmware.c | 6 ++-- 6 files changed, 87 insertions(+), 20 deletions(-) diff --git a/drivers/media/video/ov2655.c b/drivers/media/video/ov2655.c index b422b8808211..c977cf527829 100755 --- a/drivers/media/video/ov2655.c +++ b/drivers/media/video/ov2655.c @@ -1448,11 +1448,22 @@ static struct sensor* to_sensor(const struct i2c_client *client) static int sensor_task_lock(struct i2c_client *client, int lock) { #if CONFIG_SENSOR_I2C_NOSCHED + int cnt = 3; struct sensor *sensor = to_sensor(client); if (lock) { - if (atomic_read(&sensor->tasklock_cnt) == 0) + if (atomic_read(&sensor->tasklock_cnt) == 0) { + while ((atomic_read(&client->adapter->bus_lock.count) < 1) && (cnt>0)) { + SENSOR_TR("\n %s will obtain i2c in atomic, but i2c bus is locked! Wait...\n",SENSOR_NAME_STRING()); + msleep(35); + cnt--; + } + if ((atomic_read(&client->adapter->bus_lock.count) < 1) && (cnt<=0)) { + SENSOR_TR("\n %s obtain i2c fail in atomic!!\n",SENSOR_NAME_STRING()); + goto sensor_task_lock_err; + } preempt_disable(); + } atomic_add(1, &sensor->tasklock_cnt); } else { @@ -1465,6 +1476,8 @@ static int sensor_task_lock(struct i2c_client *client, int lock) } #endif return 0; +sensor_task_lock_err: + return -1; } /* sensor register write */ @@ -1551,7 +1564,8 @@ static int sensor_write_array(struct i2c_client *client, struct reginfo *regarra char valchk; cnt = 0; - sensor_task_lock(client, 1); + if (sensor_task_lock(client, 1) < 0) + goto sensor_write_array_end; while (regarray[i].reg != 0) { err = sensor_write(client, regarray[i].reg, regarray[i].val); @@ -1658,7 +1672,8 @@ static int sensor_init(struct v4l2_subdev *sd, u32 val) } /* soft reset */ - sensor_task_lock(client,1); + if (sensor_task_lock(client,1)<0) + goto sensor_INIT_ERR; ret = sensor_write(client, 0x3012, 0x80); if (ret != 0) { diff --git a/drivers/media/video/ov2659.c b/drivers/media/video/ov2659.c index a69497793750..f598647d413c 100755 --- a/drivers/media/video/ov2659.c +++ b/drivers/media/video/ov2659.c @@ -20,7 +20,7 @@ o* Driver for MT9M001 CMOS Image Sensor from Micron #include #include #include - +#include static int debug; module_param(debug, int, S_IRUGO|S_IWUSR); @@ -70,7 +70,7 @@ module_param(debug, int, S_IRUGO|S_IWUSR); #define CONFIG_SENSOR_I2C_SPEED 250000 /* 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_NOSCHED 0 #define CONFIG_SENSOR_I2C_RDWRCHK 0 #define SENSOR_BUS_PARAM (SOCAM_MASTER | SOCAM_PCLK_SAMPLE_FALLING|\ @@ -1253,11 +1253,22 @@ static struct sensor* to_sensor(const struct i2c_client *client) static int sensor_task_lock(struct i2c_client *client, int lock) { #if CONFIG_SENSOR_I2C_NOSCHED + int cnt = 3; struct sensor *sensor = to_sensor(client); if (lock) { - if (atomic_read(&sensor->tasklock_cnt) == 0) + if (atomic_read(&sensor->tasklock_cnt) == 0) { + while ((atomic_read(&client->adapter->bus_lock.count) < 1) && (cnt>0)) { + SENSOR_TR("\n %s will obtain i2c in atomic, but i2c bus is locked! Wait...\n",SENSOR_NAME_STRING()); + msleep(35); + cnt--; + } + if ((atomic_read(&client->adapter->bus_lock.count) < 1) && (cnt<=0)) { + SENSOR_TR("\n %s obtain i2c fail in atomic!!\n",SENSOR_NAME_STRING()); + goto sensor_task_lock_err; + } preempt_disable(); + } atomic_add(1, &sensor->tasklock_cnt); } else { @@ -1270,6 +1281,8 @@ static int sensor_task_lock(struct i2c_client *client, int lock) } #endif return 0; +sensor_task_lock_err: + return -1; } /* sensor register write */ @@ -1299,8 +1312,8 @@ static int sensor_write(struct i2c_client *client, u16 reg, u8 val) if (err >= 0) { return 0; } else { - SENSOR_TR("\n %s write reg(0x%x, val:0x%x) failed, try to write again!\n",SENSOR_NAME_STRING(),reg, val); - udelay(10); + SENSOR_TR("\n %s write reg(0x%x, val:0x%x) failed, try to write again!\n",SENSOR_NAME_STRING(),reg, val); + udelay(10); } } @@ -1356,7 +1369,9 @@ static int sensor_write_array(struct i2c_client *client, struct reginfo *regarra char valchk; cnt = 0; - sensor_task_lock(client, 1); + if (sensor_task_lock(client, 1) < 0) + goto sensor_write_array_end; + while (regarray[i].reg != 0) { err = sensor_write(client, regarray[i].reg, regarray[i].val); @@ -1463,7 +1478,9 @@ static int sensor_init(struct v4l2_subdev *sd, u32 val) } /* soft reset */ - sensor_task_lock(client,1); + if (sensor_task_lock(client,1)<0) + goto sensor_INIT_ERR; + ret = sensor_write(client, 0x0103, 0x01); if (ret != 0) { @@ -1676,6 +1693,9 @@ static int sensor_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) struct reginfo *winseqe_set_addr=NULL; int ret=0, set_w,set_h; + gpio_direction_output(RK29_PIN6_PB7,1); + gpio_set_value(RK29_PIN6_PB7, 1); + if (sensor->info_priv.pixfmt != pix->pixelformat) { switch (pix->pixelformat) { @@ -1784,6 +1804,8 @@ static int sensor_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) pix->height = set_h; sensor_s_fmt_end: + gpio_direction_output(RK29_PIN6_PB7,0); + gpio_set_value(RK29_PIN6_PB7, 0); return ret; } diff --git a/drivers/media/video/ov5640.c b/drivers/media/video/ov5640.c index e66f28da30c1..bcbee7f48bb2 100755 --- a/drivers/media/video/ov5640.c +++ b/drivers/media/video/ov5640.c @@ -1361,11 +1361,22 @@ static struct sensor* to_sensor(const struct i2c_client *client) static int sensor_task_lock(struct i2c_client *client, int lock) { #if CONFIG_SENSOR_I2C_NOSCHED + int cnt = 3; struct sensor *sensor = to_sensor(client); if (lock) { - if (atomic_read(&sensor->tasklock_cnt) == 0) + if (atomic_read(&sensor->tasklock_cnt) == 0) { + while ((atomic_read(&client->adapter->bus_lock.count) < 1) && (cnt>0)) { + SENSOR_TR("\n %s will obtain i2c in atomic, but i2c bus is locked! Wait...\n",SENSOR_NAME_STRING()); + msleep(35); + cnt--; + } + if ((atomic_read(&client->adapter->bus_lock.count) < 1) && (cnt<=0)) { + SENSOR_TR("\n %s obtain i2c fail in atomic!!\n",SENSOR_NAME_STRING()); + goto sensor_task_lock_err; + } preempt_disable(); + } atomic_add(1, &sensor->tasklock_cnt); } else { @@ -1378,6 +1389,8 @@ static int sensor_task_lock(struct i2c_client *client, int lock) } #endif return 0; +sensor_task_lock_err: + return -1; } /* sensor register write */ @@ -1469,7 +1482,8 @@ static int sensor_write_array(struct i2c_client *client, struct reginfo *regarra #endif cnt = 0; - sensor_task_lock(client, 1); + if (sensor_task_lock(client, 1) < 0) + goto sensor_write_array_end; while (regarray[i].reg != SEQUENCE_END) { #if CONFIG_SENSOR_Focus @@ -2050,7 +2064,8 @@ static int sensor_init(struct v4l2_subdev *sd, u32 val) } /* soft reset */ - sensor_task_lock(client,1); + if (sensor_task_lock(client,1)<0) + goto sensor_INIT_ERR; ret = sensor_write(client, 0x3008, 0x80); if (ret != 0) { SENSOR_TR("%s soft reset sensor failed\n",SENSOR_NAME_STRING()); diff --git a/drivers/media/video/ov5640_af_firmware.c b/drivers/media/video/ov5640_af_firmware.c index bffcd9c88d8f..20d9e5336e4b 100755 --- a/drivers/media/video/ov5640_af_firmware.c +++ b/drivers/media/video/ov5640_af_firmware.c @@ -9,7 +9,7 @@ */ #include "ov5640.h" -struct reginfo sensor_af_firmware[] = +static struct reginfo sensor_af_firmware[] = { SEQUENCE_END,SEQUENCE_END }; diff --git a/drivers/media/video/ov5642.c b/drivers/media/video/ov5642.c index 09098a4daf69..066f7993c1dc 100755 --- a/drivers/media/video/ov5642.c +++ b/drivers/media/video/ov5642.c @@ -3344,11 +3344,22 @@ static struct sensor* to_sensor(const struct i2c_client *client) static int sensor_task_lock(struct i2c_client *client, int lock) { #if CONFIG_SENSOR_I2C_NOSCHED + int cnt = 3; struct sensor *sensor = to_sensor(client); if (lock) { - if (atomic_read(&sensor->tasklock_cnt) == 0) + if (atomic_read(&sensor->tasklock_cnt) == 0) { + while ((atomic_read(&client->adapter->bus_lock.count) < 1) && (cnt>0)) { + SENSOR_TR("\n %s will obtain i2c in atomic, but i2c bus is locked! Wait...\n",SENSOR_NAME_STRING()); + msleep(35); + cnt--; + } + if ((atomic_read(&client->adapter->bus_lock.count) < 1) && (cnt<=0)) { + SENSOR_TR("\n %s obtain i2c fail in atomic!!\n",SENSOR_NAME_STRING()); + goto sensor_task_lock_err; + } preempt_disable(); + } atomic_add(1, &sensor->tasklock_cnt); } else { @@ -3361,6 +3372,8 @@ static int sensor_task_lock(struct i2c_client *client, int lock) } #endif return 0; +sensor_task_lock_err: + return -1; } /* sensor register write */ @@ -3452,7 +3465,8 @@ static int sensor_write_array(struct i2c_client *client, struct reginfo *regarra #endif cnt = 0; - sensor_task_lock(client, 1); + if (sensor_task_lock(client, 1) < 0) + goto sensor_write_array_end; while (regarray[i].reg != 0) { #if CONFIG_SENSOR_Focus @@ -4032,7 +4046,8 @@ static int sensor_init(struct v4l2_subdev *sd, u32 val) } /* soft reset */ - sensor_task_lock(client,1); + if (sensor_task_lock(client,1)<0) + goto sensor_INIT_ERR; ret = sensor_write(client, 0x3008, 0x80); if (ret != 0) { SENSOR_TR("%s soft reset sensor failed\n",SENSOR_NAME_STRING()); diff --git a/drivers/media/video/ov5642_af_firmware.c b/drivers/media/video/ov5642_af_firmware.c index 4ee405a75b6e..84907b88f231 100644 --- a/drivers/media/video/ov5642_af_firmware.c +++ b/drivers/media/video/ov5642_af_firmware.c @@ -15,7 +15,7 @@ #define VCM_DRIVER VCM_DRIVER_A3907 #if (VCM_DRIVER == VCM_DRIVER_A3907) -struct reginfo sensor_af_firmware[] = +static struct reginfo sensor_af_firmware[] = { {0x3000,0x20}, {0x8000,0x02}, @@ -6065,7 +6065,7 @@ struct reginfo sensor_af_firmware[] = }; #elif (VCM_DRIVER == VCM_DRIVER_AD5820) /* support const-focus */ -struct reginfo sensor_af_firmware[] = +static struct reginfo sensor_af_firmware[] = { {0x3000,0x20}, {0x8000,0x02}, @@ -11962,7 +11962,7 @@ struct reginfo sensor_af_firmware[] = {0x0000,0x00} }; #elif (VCM_DRIVER == VCM_DRIVER_DW9710) -struct reginfo sensor_af_firmware[] = +static struct reginfo sensor_af_firmware[] = { {0x3000,0x20}, {0x8000,0x02}, -- 2.34.1