mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-10 04:48:04 +09:00
camera: ov5640 add support touch focus
This commit is contained in:
@@ -68,6 +68,7 @@ module_param(debug, int, S_IRUGO|S_IWUSR);
|
||||
#define CONFIG_SENSOR_Flip 0
|
||||
#ifdef CONFIG_OV5640_AUTOFOCUS
|
||||
#define CONFIG_SENSOR_Focus 1
|
||||
#define CONFIG_SENSOR_FocusCenterInCapture 0
|
||||
#include "ov5640_af_firmware.c"
|
||||
#else
|
||||
#define CONFIG_SENSOR_Focus 0
|
||||
@@ -128,9 +129,7 @@ module_param(debug, int, S_IRUGO|S_IWUSR);
|
||||
#define STA_FOCUS_Reg 0x3029
|
||||
|
||||
/* ov5640 VCM Command */
|
||||
#define OverlayEn_Cmd 0x01
|
||||
#define OverlayDis_Cmd 0x02
|
||||
#define SingleFocus_Cmd 0x03
|
||||
|
||||
#define ConstFocus_Cmd 0x04
|
||||
#define StepMode_Cmd 0x05
|
||||
#define PauseFocus_Cmd 0x06
|
||||
@@ -138,12 +137,15 @@ module_param(debug, int, S_IRUGO|S_IWUSR);
|
||||
#define SetZone_Cmd 0x10
|
||||
#define UpdateZone_Cmd 0x12
|
||||
#define SetMotor_Cmd 0x20
|
||||
#define SingleFocus_Cmd 0x03
|
||||
#define GetFocusResult_Cmd 0x07
|
||||
#define ReleaseFocus_Cmd 0x08
|
||||
#define ZoneRelaunch_Cmd 0x12
|
||||
#define DefaultZoneConfig_Cmd 0x80
|
||||
#define TouchZoneConfig_Cmd 0x81
|
||||
#define CustomZoneConfig_Cmd 0x8f
|
||||
|
||||
|
||||
#define Zone_configuration_Cmd 0x12
|
||||
#define Trig_autofocus_Cmd 0x03
|
||||
#define Get_focus_result_Cmd 0x07
|
||||
|
||||
/* ov5640 Focus State */
|
||||
//#define S_FIRWRE 0xFF /*Firmware is downloaded and not run*/
|
||||
#define S_STARTUP 0x7e /*Firmware is initializing*/
|
||||
@@ -1423,6 +1425,14 @@ static struct v4l2_queryctrl sensor_controls[] =
|
||||
.default_value = 125,
|
||||
},*/
|
||||
{
|
||||
.id = V4L2_CID_FOCUSZONE,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "FocusZone Control",
|
||||
.minimum = -1,
|
||||
.maximum = 1,
|
||||
.step = 1,
|
||||
.default_value = 0,
|
||||
},{
|
||||
.id = V4L2_CID_FOCUS_AUTO,
|
||||
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
||||
.name = "Focus Control",
|
||||
@@ -1529,6 +1539,7 @@ struct sensor_work
|
||||
enum sensor_wq_result result;
|
||||
bool wait;
|
||||
int var;
|
||||
int zone_center_pos[2];
|
||||
};
|
||||
|
||||
typedef struct sensor_info_priv_s
|
||||
@@ -1876,6 +1887,16 @@ static int sensor_af_cmdset(struct i2c_client *client, int cmd_main, struct af_c
|
||||
char read_tag=0xff,cnt;
|
||||
|
||||
if (cmdinfo) {
|
||||
for (i=0; i<4; i++) {
|
||||
if (cmdinfo->validate_bit & (1<<i)) {
|
||||
if (sensor_write(client, CMD_PARA0_Reg+i, cmdinfo->cmd_para[i])) {
|
||||
SENSOR_TR("%s write CMD_PARA_Reg(main:0x%x para%d:0x%x) error!\n",SENSOR_NAME_STRING(),cmd_main,i,cmdinfo->cmd_para[i]);
|
||||
goto sensor_af_cmdset_err;
|
||||
}
|
||||
SENSOR_DG("%s write CMD_PARA_Reg(main:0x%x para%d:0x%x) success!\n",SENSOR_NAME_STRING(),cmd_main,i,cmdinfo->cmd_para[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (cmdinfo->validate_bit & 0x80) {
|
||||
if (sensor_write(client, CMD_ACK_Reg, cmdinfo->cmd_tag)) {
|
||||
SENSOR_TR("%s write CMD_ACK_Reg(main:0x%x tag:0x%x) error!\n",SENSOR_NAME_STRING(),cmd_main,cmdinfo->cmd_tag);
|
||||
@@ -1883,15 +1904,7 @@ static int sensor_af_cmdset(struct i2c_client *client, int cmd_main, struct af_c
|
||||
}
|
||||
SENSOR_DG("%s write CMD_ACK_Reg(main:0x%x tag:0x%x) success!\n",SENSOR_NAME_STRING(),cmd_main,cmdinfo->cmd_tag);
|
||||
}
|
||||
for (i=0; i<4; i++) {
|
||||
if (cmdinfo->validate_bit & (1<<i)) {
|
||||
if (sensor_write(client, CMD_PARA0_Reg-i, cmdinfo->cmd_para[i])) {
|
||||
SENSOR_TR("%s write CMD_PARA_Reg(main:0x%x para%d:0x%x) error!\n",SENSOR_NAME_STRING(),cmd_main,i,cmdinfo->cmd_para[i]);
|
||||
goto sensor_af_cmdset_err;
|
||||
}
|
||||
SENSOR_DG("%s write CMD_PARA_Reg(main:0x%x para%d:0x%x) success!\n",SENSOR_NAME_STRING(),cmd_main,i,cmdinfo->cmd_para[i]);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if (sensor_write(client, CMD_ACK_Reg, 0xff)) {
|
||||
SENSOR_TR("%s write CMD_ACK_Reg(main:0x%x no tag) error!\n",SENSOR_NAME_STRING(),cmd_main);
|
||||
@@ -1952,13 +1965,42 @@ static int sensor_af_idlechk(struct i2c_client *client)
|
||||
sensor_af_idlechk_end:
|
||||
return ret;
|
||||
}
|
||||
static int sensor_af_touch_zone(struct i2c_client *client, int *zone_center_pos)
|
||||
{
|
||||
int ret = 0;
|
||||
struct af_cmdinfo cmdinfo;
|
||||
|
||||
cmdinfo.cmd_tag = 0x01;
|
||||
cmdinfo.validate_bit = 0x83;
|
||||
if (zone_center_pos[0]<=8)
|
||||
cmdinfo.cmd_para[0] = 0;
|
||||
else if ((zone_center_pos[0]>8) && (zone_center_pos[0]<64))
|
||||
cmdinfo.cmd_para[0] = zone_center_pos[0]-8;
|
||||
else
|
||||
cmdinfo.cmd_para[0] = 64;
|
||||
|
||||
if (zone_center_pos[1]<=6)
|
||||
cmdinfo.cmd_para[1] = 0;
|
||||
else if ((zone_center_pos[1]>6) && (zone_center_pos[1]<48))
|
||||
cmdinfo.cmd_para[1] = zone_center_pos[1]-6;
|
||||
else
|
||||
cmdinfo.cmd_para[1] = 48;
|
||||
|
||||
ret = sensor_af_cmdset(client, TouchZoneConfig_Cmd, &cmdinfo);
|
||||
if(0 != ret) {
|
||||
SENSOR_TR("%s touch zone config error!\n",SENSOR_NAME_STRING());
|
||||
ret = -1;
|
||||
goto sensor_af_zone_end;
|
||||
}
|
||||
sensor_af_zone_end:
|
||||
return ret;
|
||||
}
|
||||
static int sensor_af_single(struct i2c_client *client)
|
||||
{
|
||||
int ret = 0;
|
||||
char state,cnt;
|
||||
struct af_cmdinfo cmdinfo;
|
||||
|
||||
|
||||
cmdinfo.cmd_tag = 0x01;
|
||||
cmdinfo.validate_bit = 0x80;
|
||||
ret = sensor_af_cmdset(client, SingleFocus_Cmd, &cmdinfo);
|
||||
@@ -2109,7 +2151,10 @@ static void sensor_af_workqueue(struct work_struct *work)
|
||||
break;
|
||||
}
|
||||
case WqCmd_af_single:
|
||||
{
|
||||
{
|
||||
if ((sensor_work->zone_center_pos[0] >=0) && (sensor_work->zone_center_pos[1]>=0))
|
||||
sensor_af_touch_zone(client,sensor_work->zone_center_pos);
|
||||
|
||||
if (sensor_af_single(client) < 0) {
|
||||
SENSOR_TR("%s Sensor_af_single is failed in sensor_af_workqueue!\n",SENSOR_NAME_STRING());
|
||||
sensor_work->result = WqRet_fail;
|
||||
@@ -2183,7 +2228,7 @@ set_end:
|
||||
return;
|
||||
}
|
||||
|
||||
static int sensor_af_workqueue_set(struct soc_camera_device *icd, enum sensor_wq_cmd cmd, int var, bool wait)
|
||||
static int sensor_af_workqueue_set(struct soc_camera_device *icd, enum sensor_wq_cmd cmd, int var, bool wait, int *zone_pos)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
|
||||
struct sensor *sensor = to_sensor(client);
|
||||
@@ -2211,6 +2256,26 @@ static int sensor_af_workqueue_set(struct soc_camera_device *icd, enum sensor_wq
|
||||
wk->result = WqRet_inval;
|
||||
wk->wait = wait;
|
||||
wk->var = var;
|
||||
|
||||
if (zone_pos) {
|
||||
if (*zone_pos || *(zone_pos+1) || *(zone_pos+2) || *(zone_pos+3)) {
|
||||
*zone_pos += 1000;
|
||||
*(zone_pos+1) += 1000;
|
||||
*(zone_pos+2) += 1000;
|
||||
*(zone_pos+3) += 1000;
|
||||
wk->zone_center_pos[0] = ((*zone_pos + *(zone_pos+2))>>1)*80/2000;
|
||||
wk->zone_center_pos[1] = ((*(zone_pos+1) + *(zone_pos+3))>>1)*60/2000;
|
||||
} else {
|
||||
#if CONFIG_SENSOR_FocusCenterInCapture
|
||||
wk->zone_center_pos[0] = 32;
|
||||
wk->zone_center_pos[1] = 24;
|
||||
#else
|
||||
wk->zone_center_pos[0] = -1;
|
||||
wk->zone_center_pos[1] = -1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
init_waitqueue_head(&wk->done);
|
||||
|
||||
queue_delayed_work(sensor->sensor_wq,&(wk->dwork),0);
|
||||
@@ -2261,11 +2326,11 @@ static int sensor_parameter_record(struct i2c_client *client)
|
||||
sensor->parameter.preview_exposure = ((tp_h<<12) & 0xF000) | ((tp_m<<4) & 0x0FF0) | ((tp_l>>4) & 0x0F);
|
||||
|
||||
//Read back AGC Gain for preview
|
||||
sensor_read(client,0x350b, &tp_l);
|
||||
sensor->parameter.preview_gain = tp_l;
|
||||
sensor_read(client,0x350b, &ret_l);
|
||||
sensor->parameter.preview_gain = ret_l;
|
||||
|
||||
SENSOR_DG(" %s Read 0x350b=0x%02x PreviewExposure:%d 0x3500=0x%02x 0x3501=0x%02x 0x3502=0x%02x \n",
|
||||
SENSOR_NAME_STRING(), tp_l,sensor->parameter.preview_exposure,ret_h, ret_m, ret_l);
|
||||
SENSOR_NAME_STRING(), tp_l,sensor->parameter.preview_exposure,tp_h, tp_m, tp_l);
|
||||
return 0;
|
||||
}
|
||||
#define OV5640_FULL_PERIOD_PIXEL_NUMS_HTS (2844)
|
||||
@@ -2278,14 +2343,8 @@ static int sensor_ae_transfer(struct i2c_client *client)
|
||||
u8 ExposureMid;
|
||||
u8 ExposureHigh;
|
||||
u16 ulCapture_Exposure;
|
||||
u32 ulCapture_Exposure_Gain;
|
||||
u16 iCapture_Gain;
|
||||
u8 Lines_10ms;
|
||||
bool m_60Hz = 0;
|
||||
u8 reg_l = 0,reg_h =0;
|
||||
u16 Preview_Maxlines;
|
||||
u8 Gain;
|
||||
u32 Capture_MaxLines;
|
||||
u16 OV5640_g_iExtra_ExpLines;
|
||||
struct sensor *sensor = to_sensor(client);
|
||||
|
||||
@@ -2299,9 +2358,7 @@ static int sensor_ae_transfer(struct i2c_client *client)
|
||||
SENSOR_DG("cap shutter calutaed = %d, 0x%x\n", ulCapture_Exposure,ulCapture_Exposure);
|
||||
|
||||
// write the gain and exposure to 0x350* registers
|
||||
sensor_write(client,0x350b, Gain);
|
||||
//Gain = (Gain >> 8) & 0x01;
|
||||
//sensor_write(client,0x350a, Gain);
|
||||
sensor_write(client,0x350b, Gain);
|
||||
|
||||
if (ulCapture_Exposure <= 1940) {
|
||||
OV5640_g_iExtra_ExpLines = 0;
|
||||
@@ -2392,7 +2449,7 @@ static int sensor_init(struct v4l2_subdev *sd, u32 val)
|
||||
struct sensor *sensor = to_sensor(client);
|
||||
const struct v4l2_queryctrl *qctrl;
|
||||
const struct sensor_datafmt *fmt;
|
||||
char value,ret_h,ret_l;
|
||||
char value;
|
||||
int ret,pid = 0;
|
||||
|
||||
SENSOR_DG("\n%s..%s.. \n",SENSOR_NAME_STRING(),__FUNCTION__);
|
||||
@@ -2656,7 +2713,6 @@ static int sensor_s_fmt(struct v4l2_subdev *sd,struct v4l2_mbus_framefmt *mf)
|
||||
struct soc_camera_device *icd = client->dev.platform_data;
|
||||
struct reginfo *winseqe_set_addr=NULL;
|
||||
int ret = 0, set_w,set_h;
|
||||
char ret_h,ret_l;
|
||||
|
||||
fmt = sensor_find_datafmt(mf->code, sensor_colour_fmts,
|
||||
ARRAY_SIZE(sensor_colour_fmts));
|
||||
@@ -2848,7 +2904,7 @@ static int sensor_s_fmt(struct v4l2_subdev *sd,struct v4l2_mbus_framefmt *mf)
|
||||
}
|
||||
#if CONFIG_SENSOR_Focus
|
||||
if (sensor->info_priv.auto_focus == SENSOR_AF_MODE_AUTO) {
|
||||
sensor_af_workqueue_set(icd,WqCmd_af_return_idle,0,true);
|
||||
sensor_af_workqueue_set(icd,WqCmd_af_return_idle,0,true,NULL);
|
||||
msleep(200);
|
||||
} else {
|
||||
msleep(500);
|
||||
@@ -3252,7 +3308,7 @@ static int sensor_set_focus_absolute(struct soc_camera_device *icd, const struct
|
||||
|
||||
if ((sensor->info_priv.funmodule_state & SENSOR_AF_IS_OK) && (sensor->info_priv.affm_reinit == 0)) {
|
||||
if ((value >= qctrl_info->minimum) && (value <= qctrl_info->maximum)) {
|
||||
ret = sensor_af_workqueue_set(icd, WqCmd_af_special_pos, value, true);
|
||||
ret = sensor_af_workqueue_set(icd, WqCmd_af_special_pos, value, true,NULL);
|
||||
SENSOR_DG("%s..%s : %d ret:0x%x\n",SENSOR_NAME_STRING(),__FUNCTION__, value,ret);
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
@@ -3280,9 +3336,9 @@ static int sensor_set_focus_relative(struct soc_camera_device *icd, const struct
|
||||
if ((sensor->info_priv.funmodule_state & SENSOR_AF_IS_OK) && (sensor->info_priv.affm_reinit == 0)) {
|
||||
if ((value >= qctrl_info->minimum) && (value <= qctrl_info->maximum)) {
|
||||
if (value > 0) {
|
||||
ret = sensor_af_workqueue_set(icd, WqCmd_af_near_pos, 0, true);
|
||||
ret = sensor_af_workqueue_set(icd, WqCmd_af_near_pos, 0, true,NULL);
|
||||
} else {
|
||||
ret = sensor_af_workqueue_set(icd, WqCmd_af_far_pos, 0, true);
|
||||
ret = sensor_af_workqueue_set(icd, WqCmd_af_far_pos, 0, true,NULL);
|
||||
}
|
||||
SENSOR_DG("%s..%s : %d ret:0x%x\n",SENSOR_NAME_STRING(),__FUNCTION__, value,ret);
|
||||
} else {
|
||||
@@ -3297,7 +3353,7 @@ static int sensor_set_focus_relative(struct soc_camera_device *icd, const struct
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sensor_set_focus_mode(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
|
||||
static int sensor_set_focus_mode(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value, int *zone_pos)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
|
||||
struct sensor *sensor = to_sensor(client);
|
||||
@@ -3308,7 +3364,7 @@ static int sensor_set_focus_mode(struct soc_camera_device *icd, const struct v4l
|
||||
{
|
||||
case SENSOR_AF_MODE_AUTO:
|
||||
{
|
||||
ret = sensor_af_workqueue_set(icd, WqCmd_af_single, 0, true);
|
||||
ret = sensor_af_workqueue_set(icd, WqCmd_af_single, 0, true, zone_pos);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3326,7 +3382,7 @@ static int sensor_set_focus_mode(struct soc_camera_device *icd, const struct v4l
|
||||
|
||||
case SENSOR_AF_MODE_CONTINUOUS:
|
||||
{
|
||||
ret = sensor_af_workqueue_set(icd, WqCmd_af_continues, 0, true);
|
||||
ret = sensor_af_workqueue_set(icd, WqCmd_af_continues, 0, true,NULL);
|
||||
break;
|
||||
}*/
|
||||
default:
|
||||
@@ -3597,7 +3653,7 @@ static int sensor_s_ext_control(struct soc_camera_device *icd, struct v4l2_ext_c
|
||||
const struct v4l2_queryctrl *qctrl;
|
||||
struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
|
||||
struct sensor *sensor = to_sensor(client);
|
||||
int val_offset,ret;
|
||||
int val_offset;
|
||||
|
||||
qctrl = soc_camera_find_qctrl(&sensor_ops, ext_ctrl->id);
|
||||
|
||||
@@ -3685,7 +3741,7 @@ static int sensor_s_ext_control(struct soc_camera_device *icd, struct v4l2_ext_c
|
||||
case V4L2_CID_FOCUS_AUTO:
|
||||
{
|
||||
if (ext_ctrl->value == 1) {
|
||||
if (sensor_set_focus_mode(icd, qctrl,SENSOR_AF_MODE_AUTO) != 0) {
|
||||
if (sensor_set_focus_mode(icd, qctrl,SENSOR_AF_MODE_AUTO,ext_ctrl->rect) != 0) {
|
||||
if(0 == (sensor->info_priv.funmodule_state & SENSOR_AF_IS_OK)) {
|
||||
sensor->info_priv.auto_focus = SENSOR_AF_MODE_AUTO;
|
||||
}
|
||||
@@ -3800,7 +3856,7 @@ static int sensor_s_stream(struct v4l2_subdev *sd, int enable)
|
||||
/* If auto focus firmware haven't download success, must download firmware again when in video or preview stream on */
|
||||
if (sensor_fmt_capturechk(sd, &mf) == false) {
|
||||
if ((sensor->info_priv.affm_reinit == 1) || ((sensor->info_priv.funmodule_state & SENSOR_AF_IS_OK)==0)) {
|
||||
sensor_af_workqueue_set(icd, WqCmd_af_init, 0, false);
|
||||
sensor_af_workqueue_set(icd, WqCmd_af_init, 0, false,NULL);
|
||||
sensor->info_priv.affm_reinit = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user