[Meego-kernel] [PATCH] MRST Tablet camera driver ver-0.953, fix 9411 and 9541
He, Yong M
yong.m.he at intel.com
Fri Jun 10 01:38:55 PDT 2011
From: Yong He <yong.m.he at intel.com>
Subject: [PATCH] MRST Tablet camera driver ver-0.953, fix 9411 and 9541
=====This patch is going to fix these bugs ===
Bug 9541<https://bugzilla.otcshare.org/show_bug.cgi?id=9541> - Flip settings of driver is not correct
Bug 9411<https://bugzilla.otcshare.org/show_bug.cgi?id=9411> - power regression test failed for camera driver version 0.941
=====solution ===
Bug 9541<https://bugzilla.otcshare.org/show_bug.cgi?id=9541> - the solution is to keep flip status in the sensor's global status structure. When waked up, restore the previous saved settings.
Bug 9411<https://bugzilla.otcshare.org/show_bug.cgi?id=9411> - 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 change back to software power down instead for now. I'll investigate this later.
Signed-off-by: He, Yong <yong.m.he at intel.com<mailto:yong.m.he at intel.com>>
---
Index: a/drivers/staging/mrstci/mrstov5640/mrstov5640.c
===================================================================
--- a/drivers/staging/mrstci/mrstov5640/mrstov5640.c (revision 87)
+++ a/drivers/staging/mrstci/mrstov5640/mrstov5640.c (revision 88)
@@ -49,7 +49,7 @@
#include "ci_sensor_common.h"
#include "ov5640.h"
-#define DRIVER_VERSION "0.952"
+#define DRIVER_VERSION "0.953"
static int mrstov5640_debug=5;
module_param(mrstov5640_debug, int, 0644);
@@ -229,11 +229,8 @@
int exp_comp_val;
int af_x, af_y, af_mode;
int ae_x, ae_y, ae_w, ae_h,ae_mode;
+ int hflip,vflip;
- // hw status
- u8 REG20;
- u8 REG21;
-
ov5640_exp_info_1_t snapshot;
ov5640_exp_info_1_t preview;
ov5640_exp_info_2_t expo;
@@ -242,10 +239,10 @@
.power = OV5640_POWER_OFF,
.reg_inited = OV5640_REG_BEFORE_PROBE,
.fw_inited = OV5640_FW_RESET,
- .REG20 = 0,
- .REG21 = 0,
.anti_banding = 0,
.iso_mode = 0,
+ .hflip = 0,
+ .vflip = 1,
.iso_val = 100,
};
@@ -597,6 +594,7 @@
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
@@ -612,7 +610,8 @@
}
ov5640_status.fw_inited = OV5640_FW_RESET;
- gpio_set_value(GPIO_STDBY_PIN, 1);
+ ov5640_s_stream(sd , 0);
+ //gpio_set_value(GPIO_STDBY_PIN, 1);
ov5640_status.power = OV5640_POWER_OFF;
dprintk(1, "PM: ov5640 standby called\n");
@@ -689,7 +688,6 @@
memcpy(info->name, "ov5640", 7);
ov5640_status.reg_inited = OV5640_REG_RESET; // need do init reg here
- ret = ov5640_write(c, 0x3008, 0x82);
ret = ov5640_write(c, 0x3013, 0x11);
ret = ov5640_write(c, 0x3008, 0x82);
ret = ov5640_hw_init(c);
@@ -1220,6 +1218,7 @@
//info->bpat = SENSOR_BPAT_BGBGGRGR;
}
err += ov5640_write(client, 0x3821, v);
+ ov5640_status.hflip = value;
msleep(10); /* FIXME */
return err;
@@ -1250,6 +1249,7 @@
else
v &= ~0x06;
err += ov5640_write(client, 0x3820, v);
+ ov5640_status.vflip = value;
msleep(10); /* FIXME */
return err;
@@ -2693,6 +2693,7 @@
} else {
ov5640_set_aec_agc(client,0);
ov5640_save_expo_val(sd);
+ ov5640_save_hw_status(client);
ov5640_write(client, 0x3008, 0x42);
//ov5640_set_data_pin_in(client);
}
@@ -2815,9 +2816,7 @@
{
struct v4l2_subdev *sd = i2c_get_clientdata(c);
- // save original flip status
- ov5640_read(c,0x3820,&ov5640_status.REG20);
- ov5640_read(c,0x3821,&ov5640_status.REG21);
+ // save original flip status, (already saved in ioctl)
// save anti-banding status
ov5640_q_anti_banding(sd, &ov5640_status.anti_banding);
@@ -2827,13 +2826,10 @@
static int ov5640_restore_hw_status(struct i2c_client *c)
{
struct v4l2_subdev *sd = i2c_get_clientdata(c);
- u8 REG20_new,REG21_new;
// restore original flip status
- ov5640_read(c,0x3820,®20_new);
- ov5640_read(c,0x3821,®21_new);
- ov5640_write(c,0x3820,((REG20_new & 0xf9) | (ov5640_status.REG20& 0x6)));
- ov5640_write(c,0x3821,((REG21_new & 0xf9) | (ov5640_status.REG21& 0x6)));
+ ov5640_t_hflip(sd, ov5640_status.hflip);
+ ov5640_t_vflip(sd, ov5640_status.vflip);
// restore anti-banding status
ov5640_t_anti_banding(sd, ov5640_status.anti_banding);
Index: a/drivers/staging/mrstci/mrstov9740/mrstov9740.c
===================================================================
--- a/drivers/staging/mrstci/mrstov9740/mrstov9740.c (revision 87)
+++ a/drivers/staging/mrstci/mrstov9740/mrstov9740.c (revision 88)
@@ -48,7 +48,7 @@
#include "ci_sensor_common.h"
#include "ov9740.h"
-#define DRIVER_VERSION "0.941"
+#define DRIVER_VERSION "0.953"
//#define pr_fmt(fmt) "ov9740: " fmt
static int mrstov9740_debug=5;
@@ -131,6 +131,31 @@
#define N_RES (ARRAY_SIZE(ov9740_res))
+#define OV9740_POWER_OFF 0
+#define OV9740_POWER_ON 1
+
+#define OV9740_REG_RESET 2
+#define OV9740_REG_INITED 1
+#define OV9740_REG_BEFORE_PROBE 0
+
+static struct __ov9740_status_ {
+ // sw status
+ int current_res_i;
+ int power;
+ int reg_inited;
+
+ // hw status
+ int anti_banding;
+ int hflip,vflip;
+} ov9740_status = {
+ .current_res_i = 2,//SENSOR_RES_VGA;
+ .power = OV9740_POWER_OFF,
+ .reg_inited = OV9740_REG_BEFORE_PROBE,
+ .anti_banding = 0,
+ .hflip = 0,
+ .vflip = 0,
+};
+
/*
* I2C Read & Write stuff
*/
@@ -230,29 +255,82 @@
*/
return ret;
}
+
+static int ov9740_save_hw_status(struct i2c_client *c);
+static int ov9740_restore_hw_status(struct i2c_client *c);
+
+static int ov9740_hw_init(struct i2c_client *c)
+{
+ int ret;
+ DBG_entering;
+
+ if (ov9740_status.reg_inited != OV9740_REG_RESET) {
+ return 0;
+ }
+
+ /* Set registers into default config value */
+ ret = ov9740_write_array(c, ov9740_def);
+ ret += ov9740_write_array(c, ov9740_reg_vga);
+ //ov9740_write(c, 0x0100, 0x00);
+
+ dprintk( 1, "[ov9740-wr-reg] <----------- load ov9740 default settings\n");
+
+ ov9740_set_data_pin_in(c);
+ ov9740_status.reg_inited = OV9740_REG_INITED;
+ ov9740_status.current_res_i = 2 ;
+
+ DBG_leaving;
+ return ret;
+}
+
/*
* Sensor specific helper function
*/
-static int ov9740_standby(void)
+static int ov9740_standby(struct v4l2_subdev *sd)
{
- gpio_set_value(GPIO_STDBY_PIN, 1);
+ if (ov9740_status.reg_inited == OV9740_REG_INITED)
+ {
+ struct i2c_client *c = v4l2_get_subdevdata(sd);
+ ov9740_save_hw_status(c);
+ ov9740_status.reg_inited = OV9740_REG_RESET;
+ }
+
+ //ov9740_s_stream(sd , 0);
+ gpio_set_value(GPIO_STDBY_PIN, 1);
+ ov9740_status.power = OV9740_POWER_OFF;
+
dprintk(1, "PM: ov9740 standby called\n");
return 0;
}
-static int ov9740_wakeup(void)
+static int ov9740_wakeup(struct v4l2_subdev *sd, int hw_reinit)
{
- gpio_set_value(GPIO_STDBY_PIN, 0);
- dprintk(1, "PM: ov9740 wakeup called\n");
+ dprintk(1, "PM: ov9740 wakeup called (%d)\n",hw_reinit);
+
+ if (ov9740_status.power == OV9740_POWER_OFF)
+ {
+ dprintk(1, "PM: ov9740 switch OFF to ON.\n");
+ gpio_set_value(GPIO_STDBY_PIN, 0);
+ ov9740_status.power = OV9740_POWER_ON;
+ }
+
+ if (hw_reinit)
+ {
+ struct i2c_client *c = v4l2_get_subdevdata(sd);
+ //ov9740_hw_init(c);
+ ov9740_status.reg_inited = OV9740_REG_INITED;
+ ov9740_restore_hw_status(c);
+ }
+
return 0;
}
static int ov9740_s_power(struct v4l2_subdev *sd, u32 val)
{
if (val == 1)
- ov9740_standby();
+ ov9740_standby(sd);
if (val == 0)
- ov9740_wakeup();
+ ov9740_wakeup(sd,0);
return 0;
}
@@ -291,19 +369,10 @@
info->cie_profile = 0;
memcpy(info->name, "ov9740", 7);
- //
- // added
- // ret = ov9740_write(c, OV9740_SYS, 0x80);
/* Set registers into default config value */
- ret = ov9740_write_array(c, ov9740_def);
- ret += ov9740_write_array(c, ov9740_reg_vga);
-
- /* added by wen to stop sensor from streaming */
- // ov9740_write(c, 0x3086, 0x0f);
- // commented out in workshop
- //
-/// ov9740_set_data_pin_in(c);
- ssleep(1);
+ ov9740_status.reg_inited = OV9740_REG_RESET; // need do init reg here
+ ov9740_hw_init(c);
+ msleep(300);
DBG_leaving;
@@ -453,8 +522,6 @@
return index;
}
-static int previous_res = 2;//SENSOR_RES_VGA;
-
static int ov9740_set_fmt(struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *fmt)
{
@@ -473,7 +540,7 @@
ret = ov9740_try_res(&width, &height);
res_index = ov9740_to_res(width, height);
- ov9740_wakeup();
+ ov9740_wakeup(sd,1);
/* if ((info->res != res_index->res) && (res_index->regs)) { */
if (res_index->regs) {
@@ -481,11 +548,13 @@
target_res_index = find_OV9740_TIMING_index(res_index->res);
- if (previous_res != target_res_index) {
- dprintk( 3, "[ov9740-wr-reg] <----------- changing res from index-%d to index-%d (%dx%d)", previous_res, target_res_index,width, height);
+ if (ov9740_status.current_res_i != target_res_index) {
+ dprintk( 3, "[ov9740-wr-reg] <----------- changing res from index-%d to index-%d (%dx%d)",ov9740_status.current_res_i , target_res_index,width, height);
dprintk( 3, "[ov9740-wr-reg] <----------- Set resolutiojn Configs");
+ ret += ov9740_save_hw_status(client);
ret += ov9740_write_array(client, res_index->regs);
- previous_res = target_res_index;
+ ret += ov9740_restore_hw_status(client);
+ ov9740_status.current_res_i = target_res_index;
}
else {
dprintk(3, "[ov9740-wr-reg] <----------- same res index-%d (%dx%d)", target_res_index,width, height);
@@ -522,7 +591,7 @@
unsigned char v;
err = ov9740_read(client, 0x0101, &v);
- *value = (v & 0x01) == 0x01;
+ *value = ((v & 0x01) == 0x01);
return err;
}
@@ -543,6 +612,7 @@
//info->bpat = SENSOR_BPAT_BGBGGRGR;
}
err += ov9740_write(client, 0x0101, v);
+ ov9740_status.hflip = value;
msleep(10); /* FIXME */
return err;
@@ -555,7 +625,7 @@
unsigned char v;
err = ov9740_read(client, 0x0101, &v);
- *value = (v & 0x02) == 0x02;
+ *value = ((v & 0x02) == 0x02);
return err;
}
@@ -577,6 +647,7 @@
//info->bpat = SENSOR_BPAT_BGBGGRGR;
}
err += ov9740_write(client, 0x0101, v);
+ ov9740_status.vflip = value;
msleep(10); /* FIXME */
return err;
@@ -820,6 +891,7 @@
msleep(300);
}
} else {
+ ov9740_save_hw_status(client);
ov9740_write(client, 0x0100, 0x00);
}
@@ -895,16 +967,16 @@
target_fps = param->parm.capture.timeperframe.denominator / param->parm.capture.timeperframe.numerator;
- if (ov9740_res[previous_res].used) {
+ if (ov9740_res[ov9740_status.current_res_i].used) {
for (fps_i = 0; fps_i < OV9740_N_FPS; fps_i++) {
- if (target_fps == ov9740_res[previous_res].fps[fps_i]) {
+ if (target_fps == ov9740_res[ov9740_status.current_res_i].fps[fps_i]) {
// found the target fps
u8 val;
dprintk( 1, "set sensor FPS to %d\n", target_fps);
ov9740_read(client, 0x0100, &val);
if (val == 0x01) ov9740_s_stream(sd, 0);
- target_vts = (ov9740_vts_setting[previous_res] * ov9740_res[previous_res].fps[0]) / target_fps;
+ target_vts = (ov9740_vts_setting[ov9740_status.current_res_i] * ov9740_res[ov9740_status.current_res_i].fps[0]) / target_fps;
ov9740_write(client, 0x0340, (target_vts>>8)&0xff);
ov9740_write(client, 0x0341, target_vts&0xff);
@@ -919,7 +991,7 @@
}
} else {
dprintk( 1, "Warning!! current_res (%d) is not used??\n",
- previous_res);
+ ov9740_status.current_res_i);
}
DBG_leaving;
@@ -937,6 +1009,25 @@
return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_OV9740, 0);
}
+static int ov9740_save_hw_status(struct i2c_client *c)
+{
+ struct v4l2_subdev *sd = i2c_get_clientdata(c);
+
+ // save original flip status (already saved in the ioctl)
+
+ return 0;
+}
+
+static int ov9740_restore_hw_status(struct i2c_client *c)
+{
+ struct v4l2_subdev *sd = i2c_get_clientdata(c);
+
+ // restore flip status
+ ov9740_t_hflip(sd, ov9740_status.hflip);
+ ov9740_t_vflip(sd, ov9740_status.vflip);
+ return 0;
+}
+
#ifdef CONFIG_VIDEO_ADV_DEBUG
static int ov9740_g_register(struct v4l2_subdev *sd,
struct v4l2_dbg_register *reg)
@@ -1027,6 +1118,7 @@
#endif
static int ov9740_detect(struct i2c_client *client)
{
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
struct i2c_adapter *adapter = client->adapter;
int adap_id = i2c_adapter_id(adapter);
u8 value;
@@ -1045,7 +1137,7 @@
}
/* if (ov9740_wakeup()) */
/* return -ENODEV; */
- ov9740_wakeup();
+ ov9740_wakeup(sd, 0);
ov9740_read(client, 0x300b, &value);
if (value != 0x40)
@@ -1091,7 +1183,7 @@
*/
/* ov9740_standby(); */
ret += ov9740_init(client);
- ov9740_standby();
+ ov9740_standby(sd);
printk(KERN_INFO "Init ov9740 (Version-%s) sensor success, ret = %d\n", DRIVER_VERSION, ret);
Best Regards,
Yong He
Software Engineer, PCSD SW Solutions,
Intel Asia-Pacific R&D Ltd.
Phone (+86) 21-61166334
Lab (+86) 21-61167881
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.meego.com/pipermail/meego-kernel/attachments/20110610/9647f682/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: linux-2.6.37-camera-ov5640-ov9740-version-0.952_to_0.953.patch
Type: application/octet-stream
Size: 12005 bytes
Desc: linux-2.6.37-camera-ov5640-ov9740-version-0.952_to_0.953.patch
URL: <http://lists.meego.com/pipermail/meego-kernel/attachments/20110610/9647f682/attachment-0001.obj>
More information about the MeeGo-kernel
mailing list