Hi, all checkpath errors and warnings are cleaned, Please review the updates.
From: Yong He <[email protected]> Subject: [PATCH] MRST Tablet camera driver ver-0.942 (re-send 2), fix 9411 Bug 9411 - power regression test failed for camera driver version 0.941 this is caused by the back sensor HW power down GPIO-49, when perform a HW power down using this GPIO, somewhere else is leaking, So I revert to use software power down. Also, this patch added hw status flag and save/restore ops between standby and wakeup. Signed-off-by: Yong He <[email protected]> Index: linux-2.6.37/drivers/staging/mrstci/mrstisp/mrstisp_main.c =================================================================== --- linux-2.6.37/drivers/staging/mrstci/mrstisp/mrstisp_main.c (revision 98) +++ linux-2.6.37/drivers/staging/mrstci/mrstisp/mrstisp_main.c (revision 100) @@ -1369,8 +1369,10 @@ DBG_entering; for (i = 0 ; i <= isp->sensor_max; i++) { - // power the sensor - v4l2_subdev_call(isp->cameras[i].camera, core, s_gpio, 1); + if (isp->cameras[i].camera != NULL) { + v4l2_subdev_call(isp->cameras[i].camera, + core, s_gpio, 1); + } }; DBG_leaving; @@ -2245,6 +2247,18 @@ return -EBUSY; } + /* switch to a different sensor? */ + if (isp->sensor_curr != i) { + /* suspend current sensor */ + if ((isp->sensor_curr >= 0) && + (isp->sensor_curr <= isp->sensor_max)) { + if (isp->cameras[isp->sensor_curr].camera) + v4l2_subdev_call( + isp->cameras[isp->sensor_curr].camera, + core, s_gpio, 1); + } + } + isp->sensor_curr = i; dprintk(0, "set sensor %s as input", camera->name); Index: linux-2.6.37/drivers/staging/mrstci/mrstov5640/ov5640.h =================================================================== --- linux-2.6.37/drivers/staging/mrstci/mrstov5640/ov5640.h (revision 98) +++ linux-2.6.37/drivers/staging/mrstci/mrstov5640/ov5640.h (revision 100) @@ -42,8 +42,6 @@ static struct regval_list ov5640_reg_reset[] = { - {0x3103, 0x11}, - {0x3008, 0x82}, {0x3008, 0x42}, {0x3103, 0x03}, {0x3017, 0x00}, Index: linux-2.6.37/drivers/staging/mrstci/mrstov5640/mrstov5640.c =================================================================== --- linux-2.6.37/drivers/staging/mrstci/mrstov5640/mrstov5640.c (revision 98) +++ linux-2.6.37/drivers/staging/mrstci/mrstov5640/mrstov5640.c (revision 100) @@ -48,7 +48,7 @@ #include "ci_sensor_common.h" #include "ov5640.h" -#define DRIVER_VERSION "0.941" +#define DRIVER_VERSION "0.942" static int mrstov5640_debug=5; module_param(mrstov5640_debug, int, 0644); @@ -183,17 +183,34 @@ #define OV5640_POWER_OFF 0 #define OV5640_POWER_ON 1 -#define OV5640_REG_RESET 0 +#define OV5640_REG_RESET 2 #define OV5640_REG_INITED 1 +#define OV5640_REG_BEFORE_PROBE 0 +/* + * 6 -- VGA index in the array ov5640_res[], + * which is the default resolution setting + */ + +#define RESOLUTION_INDEX_VGA 6 + static struct __ov5640_status_ { + /* lock */ + spinlock_t state_lock; + + /* sw status*/ int current_res_i; int power; int reg_inited; + int hflip, vflip; + } ov5640_status = { - .current_res_i = 6,//SENSOR_RES_VGA; - .power = OV5640_POWER_OFF, - .reg_inited = OV5640_REG_INITED, + .state_lock = __SPIN_LOCK_UNLOCKED(), + .current_res_i = RESOLUTION_INDEX_VGA, + .power = OV5640_POWER_OFF, + .reg_inited = OV5640_REG_BEFORE_PROBE, + .hflip = 0, + .vflip = 1, }; /* @@ -312,62 +329,77 @@ static int ov5640_hw_init (struct i2c_client *c) { int ret; - DBG_entering; + unsigned long flags; + DBG_entering; - if (ov5640_status.reg_inited == OV5640_REG_INITED) { - return 0; - } + spin_lock_irqsave(&ov5640_status.state_lock, flags); - ret = ov5640_write(c, 0x3008, 0x82); + if (ov5640_status.reg_inited != OV5640_REG_RESET) { + spin_unlock_irqrestore(&ov5640_status.state_lock, flags); + ret = 0; + goto __ov5640_hw_init_exit; + } + + ov5640_status.reg_inited = OV5640_REG_INITED; + ov5640_status.current_res_i = RESOLUTION_INDEX_VGA; + spin_unlock_irqrestore(&ov5640_status.state_lock, flags); + /* Set registers into default config value */ - ret += ov5640_write_array(c, ov5640_def_reg); + ret = ov5640_write_array(c, ov5640_def_reg); dprintk( 1, "[ov5640-wr-reg] <----------- load ov5640 default settings\n"); - // turn on AGC/AEC - ov5640_write(c, 0x3503, 0x0); - ov5640_status.current_res_i = 6 ; - - /* added by wen to stop sensor from streaming */ - ov5640_write(c, 0x3008, 0x42); + /* turn on AGC/AEC */ + ret += ov5640_write(c, 0x3503, 0x0); ov5640_set_data_pin_in(c); - msleep(300); - ov5640_status.reg_inited = OV5640_REG_INITED; +__ov5640_hw_init_exit: DBG_leaving; return ret; } - +static int ov5640_save_hw_status(struct i2c_client *c); +static int ov5640_restore_hw_status(struct i2c_client *c); static int ov5640_s_stream(struct v4l2_subdev *sd, int enable); - /* * Sensor specific helper function */ -static int ov5640_standby(struct v4l2_subdev *sd) +static void ov5640_standby(struct v4l2_subdev *sd) { - // set software power down instead. - ov5640_s_stream(sd, 0); - // set hw power down - //gpio_set_value(GPIO_STDBY_PIN, 1); + unsigned long flags; + struct i2c_client *c = v4l2_get_subdevdata(sd); + + ov5640_save_hw_status(c); + ov5640_s_stream(sd , 0); + spin_lock_irqsave(&ov5640_status.state_lock, flags); + ov5640_status.power = OV5640_POWER_OFF; - //ov5640_status.reg_inited = OV5640_REG_RESET; + + if (ov5640_status.reg_inited == OV5640_REG_INITED) + ov5640_status.reg_inited = OV5640_REG_RESET; + + spin_unlock_irqrestore(&ov5640_status.state_lock, flags); dprintk(1, "PM: ov5640 standby called\n"); - return 0; } -static int ov5640_wakeup(struct v4l2_subdev *sd, int hw_init) +static void ov5640_wakeup(struct v4l2_subdev *sd, int hw_reinit) { - struct i2c_client *c = v4l2_get_subdevdata(sd); - + unsigned long flags; dprintk(1, "PM: ov5640 wakeup called\n"); + spin_lock_irqsave(&ov5640_status.state_lock, flags); if (ov5640_status.power == OV5640_POWER_OFF) { + ov5640_status.power = OV5640_POWER_ON; + spin_unlock_irqrestore(&ov5640_status.state_lock, flags); dprintk(1, "PM: ov5640 switch OFF to ON.\n"); gpio_set_value(GPIO_STDBY_PIN, 0); - //if (hw_init) { ov5640_hw_init(c); } - ov5640_status.power = OV5640_POWER_ON; + if (hw_reinit) { + struct i2c_client *c = v4l2_get_subdevdata(sd); + ov5640_hw_init(c); + ov5640_restore_hw_status(c); + } + } else { + spin_unlock_irqrestore(&ov5640_status.state_lock, flags); } - return 0; } static int ov5640_s_power(struct v4l2_subdev *sd, u32 val) @@ -418,8 +450,11 @@ info->mipi_lanes = MIPI_LANES; /*MIPI lanes, 1 or 2*/ memcpy(info->name, "ov5640", 7); - ov5640_status.reg_inited = OV5640_REG_RESET; // need do init reg here + ov5640_status.reg_inited = OV5640_REG_RESET; /* need do init reg here*/ + ret = ov5640_write(c, 0x3013, 0x11); + ret = ov5640_write(c, 0x3008, 0x82); ret = ov5640_hw_init(c); + msleep(300); DBG_leaving; @@ -584,6 +619,7 @@ static int ov5640_set_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt) { + unsigned long flags; struct i2c_client *client = v4l2_get_subdevdata(sd); struct ci_sensor_config *info = to_sensor_config(sd); int ret = 0; @@ -606,25 +642,21 @@ uint8_t target_res_index; target_res_index = find_OV5640_TIMING_index(res_index->res); + spin_lock_irqsave(&ov5640_status.state_lock, flags); if (ov5640_status.current_res_i != target_res_index) { - u8 REG20,REG21,REG20_new,REG21_new; + ov5640_status.current_res_i = target_res_index; + spin_unlock_irqrestore( + &ov5640_status.state_lock, flags); dprintk( 3, "[ov5640-wr-reg] <----------- changing res from index-%d to index-%d (%dx%d)", ov5640_status.current_res_i, target_res_index,width, height); dprintk( 3, "[ov5640-wr-reg] <----------- Set resolutiojn Configs"); - - // save original flip status - ov5640_read(client,0x3820,®20); - ov5640_read(client,0x3821,®21); + ov5640_save_hw_status(client); ret += ov5640_write_array(client, res_index->regs); - // restore original flip status - ov5640_read(client,0x3820,®20_new); - ov5640_read(client,0x3821,®21_new); - ov5640_write(client,0x3820,((REG20_new & 0xf9) | (REG20& 0x6))); - ov5640_write(client,0x3821,((REG21_new & 0xf9) | (REG21& 0x6))); - - ov5640_status.current_res_i = target_res_index; + ov5640_restore_hw_status(client); } else { + spin_unlock_irqrestore( + &ov5640_status.state_lock, flags); dprintk(3, "[ov5640-wr-reg] <----------- same res index-%d (%dx%d)", target_res_index,width, height); } @@ -690,6 +722,7 @@ //info->bpat = SENSOR_BPAT_BGBGGRGR; } err += ov5640_write(client, 0x3821, v); + ov5640_status.hflip = value; msleep(10); /* FIXME */ return err; @@ -720,6 +753,7 @@ else v &= ~0x06; err += ov5640_write(client, 0x3820, v); + ov5640_status.vflip = value; msleep(10); /* FIXME */ return err; @@ -980,6 +1014,29 @@ return ret; } +static int ov5640_save_hw_status(struct i2c_client *c) +{ + int ret = 0; + /* flip status has already been saved in the ioctl, + * no need to save here + * */ + + /* TODO: save original hw status*/ + + return ret; +} + +static int ov5640_restore_hw_status(struct i2c_client *c) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(c); + int ret = 0; + + /* restore original flip status*/ + ov5640_t_hflip(sd, ov5640_status.hflip); + ov5640_t_vflip(sd, ov5640_status.vflip); + return ret; +} + static int ov5640_s_stream(struct v4l2_subdev *sd, int enable) { struct i2c_client *client = v4l2_get_subdevdata(sd); @@ -995,10 +1052,8 @@ ov5640_write(client, 0x3008, 0x02); msleep(300); } - //ov5640_set_data_pin_out(client); } else { ov5640_write(client, 0x3008, 0x42); - //ov5640_set_data_pin_in(client); } DBG_leaving; @@ -1076,7 +1131,7 @@ if (ov5640_res[ov5640_status.current_res_i].used) { for (fps_i = 0; fps_i < OV5640_N_FPS; fps_i++) { if (target_fps == ov5640_res[ov5640_status.current_res_i].fps[fps_i]) { - // found the target fps + /* found the target fps*/ u8 val; dprintk( 1, "set sensor FPS to %d\n", target_fps); ov5640_read(client, 0x3008, &val); Signed-off-by: Yong He <[email protected]> Thanks, -- Yong Phone (+86) 21-61166334 Lab (+86) 21-61167881
linux-2.6.37-camera-ov5640-ov9740-version-0.941_to_0.942.patch
Description: linux-2.6.37-camera-ov5640-ov9740-version-0.941_to_0.942.patch
_______________________________________________ MeeGo-kernel mailing list [email protected] http://lists.meego.com/listinfo/meego-kernel
