mirror of
https://github.com/torvalds/linux.git
synced 2026-06-08 14:42:37 +02:00
camera: ov5642 and ov5640 support auto focus in background kernel thread, qbuf and dqbuf is pause if haven't do this operation
This commit is contained in:
parent
478513bf40
commit
dae66046ab
|
|
@ -1343,6 +1343,8 @@ static unsigned long sensor_query_bus_param(struct soc_camera_device *icd);
|
|||
static int sensor_set_effect(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value);
|
||||
static int sensor_set_whiteBalance(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value);
|
||||
static int sensor_deactivate(struct i2c_client *client);
|
||||
static bool sensor_fmt_capturechk(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf);
|
||||
static bool sensor_fmt_videochk(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf);
|
||||
|
||||
static struct soc_camera_ops sensor_ops =
|
||||
{
|
||||
|
|
@ -1378,16 +1380,31 @@ static const struct sensor_datafmt sensor_colour_fmts[] = {
|
|||
{V4L2_MBUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_JPEG},
|
||||
{V4L2_MBUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG}
|
||||
};
|
||||
enum sensor_work_state
|
||||
enum sensor_wq_cmd
|
||||
{
|
||||
sensor_work_ready = 0,
|
||||
sensor_working,
|
||||
WqCmd_af_init,
|
||||
WqCmd_af_single,
|
||||
WqCmd_af_special_pos,
|
||||
WqCmd_af_far_pos,
|
||||
WqCmd_af_near_pos,
|
||||
WqCmd_af_continues,
|
||||
WqCmd_af_return_idle,
|
||||
};
|
||||
enum sensor_wq_result
|
||||
{
|
||||
WqRet_success = 0,
|
||||
WqRet_fail = -1,
|
||||
WqRet_inval = -2
|
||||
};
|
||||
struct sensor_work
|
||||
{
|
||||
struct i2c_client *client;
|
||||
struct delayed_work dwork;
|
||||
enum sensor_work_state state;
|
||||
enum sensor_wq_cmd cmd;
|
||||
wait_queue_head_t done;
|
||||
enum sensor_wq_result result;
|
||||
bool wait;
|
||||
int var;
|
||||
};
|
||||
|
||||
typedef struct sensor_info_priv_s
|
||||
|
|
@ -1435,7 +1452,6 @@ struct sensor
|
|||
sensor_info_priv_t info_priv;
|
||||
struct sensor_parameter parameter;
|
||||
struct workqueue_struct *sensor_wq;
|
||||
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
|
||||
|
|
@ -1900,19 +1916,30 @@ static int sensor_af_init(struct i2c_client *client)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int sensor_af_wq_function(struct i2c_client *client)
|
||||
static int sensor_af_downfirmware(struct i2c_client *client)
|
||||
{
|
||||
struct sensor *sensor = to_sensor(client);
|
||||
int ret=0;
|
||||
|
||||
struct af_cmdinfo cmdinfo;
|
||||
int ret=0, focus_pos = 0xfe;
|
||||
struct soc_camera_device *icd = client->dev.platform_data;
|
||||
struct v4l2_mbus_framefmt mf;
|
||||
|
||||
SENSOR_DG("%s %s Enter\n",SENSOR_NAME_STRING(), __FUNCTION__);
|
||||
|
||||
mutex_lock(&sensor->wq_lock);
|
||||
|
||||
if (sensor_af_init(client)) {
|
||||
sensor->info_priv.funmodule_state &= (~SENSOR_AF_IS_OK);
|
||||
ret = -1;
|
||||
} else {
|
||||
sensor->info_priv.funmodule_state |= SENSOR_AF_IS_OK;
|
||||
|
||||
mf.width = icd->user_width;
|
||||
mf.height = icd->user_height;
|
||||
mf.code = sensor->info_priv.fmt.code;
|
||||
mf.colorspace = sensor->info_priv.fmt.colorspace;
|
||||
mf.field = V4L2_FIELD_NONE;
|
||||
if (sensor_fmt_videochk(NULL, &mf) == true) { /* ddl@rock-chips.com: focus mode fix const auto focus in video */
|
||||
ret = sensor_af_const(client);
|
||||
} else {
|
||||
switch (sensor->info_priv.auto_focus)
|
||||
{
|
||||
/*case SENSOR_AF_MODE_INFINITY:
|
||||
|
|
@ -1941,34 +1968,165 @@ static int sensor_af_wq_function(struct i2c_client *client)
|
|||
ret = sensor_af_const(client);
|
||||
break;
|
||||
}*/
|
||||
case SENSOR_AF_MODE_CLOSE:
|
||||
{
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
SENSOR_DG("%s focus mode(0x%x) is unkonwn\n",SENSOR_NAME_STRING(),sensor->info_priv.auto_focus);
|
||||
goto sensor_af_wq_function_end;
|
||||
}
|
||||
}
|
||||
|
||||
SENSOR_DG("%s sensor_af_wq_function set focus mode(0x%x) ret:0x%x\n",SENSOR_NAME_STRING(), sensor->info_priv.auto_focus,ret);
|
||||
case SENSOR_AF_MODE_CLOSE:
|
||||
{
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
SENSOR_DG("%s focus mode(0x%x) is unkonwn\n",SENSOR_NAME_STRING(),sensor->info_priv.auto_focus);
|
||||
goto sensor_af_downfirmware_end;
|
||||
}
|
||||
}
|
||||
}
|
||||
SENSOR_DG("%s sensor_af_downfirmware set focus mode(0x%x) ret:0x%x\n",SENSOR_NAME_STRING(), sensor->info_priv.auto_focus,ret);
|
||||
}
|
||||
|
||||
sensor_af_wq_function_end:
|
||||
sensor->sensor_wk.state = sensor_work_ready;
|
||||
mutex_unlock(&sensor->wq_lock);
|
||||
sensor_af_downfirmware_end:
|
||||
|
||||
return ret;
|
||||
}
|
||||
static void sensor_af_workqueue(struct work_struct *work)
|
||||
{
|
||||
struct sensor_work *sensor_work = container_of(work, struct sensor_work, dwork.work);
|
||||
struct i2c_client *client = sensor_work->client;
|
||||
struct sensor *sensor = to_sensor(client);
|
||||
struct af_cmdinfo cmdinfo;
|
||||
|
||||
SENSOR_DG("%s %s Enter, cmd:0x%x \n",SENSOR_NAME_STRING(), __FUNCTION__,sensor_work->cmd);
|
||||
|
||||
mutex_lock(&sensor->wq_lock);
|
||||
switch (sensor_work->cmd)
|
||||
{
|
||||
case WqCmd_af_init:
|
||||
{
|
||||
if (sensor_af_downfirmware(client) < 0) {
|
||||
SENSOR_TR("%s Sensor_af_init is failed in sensor_af_workqueue!\n",SENSOR_NAME_STRING());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WqCmd_af_single:
|
||||
{
|
||||
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;
|
||||
} else {
|
||||
sensor_work->result = WqRet_success;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WqCmd_af_special_pos:
|
||||
{
|
||||
sensor_af_idlechk(client);
|
||||
|
||||
if (sensor_af_wq_function(client) < 0) {
|
||||
SENSOR_TR("%s af workqueue return false\n",SENSOR_NAME_STRING());
|
||||
}
|
||||
cmdinfo.cmd_tag = StepFocus_Spec_Tag;
|
||||
cmdinfo.cmd_para[0] = sensor_work->var;
|
||||
cmdinfo.validate_bit = 0x81;
|
||||
if (sensor_af_cmdset(client, StepMode_Cmd, &cmdinfo) < 0)
|
||||
sensor_work->result = WqRet_fail;
|
||||
else
|
||||
sensor_work->result = WqRet_success;
|
||||
break;
|
||||
}
|
||||
case WqCmd_af_near_pos:
|
||||
{
|
||||
sensor_af_idlechk(client);
|
||||
cmdinfo.cmd_tag = StepFocus_Near_Tag;
|
||||
cmdinfo.validate_bit = 0x80;
|
||||
if (sensor_af_cmdset(client, StepMode_Cmd, &cmdinfo) < 0)
|
||||
sensor_work->result = WqRet_fail;
|
||||
else
|
||||
sensor_work->result = WqRet_success;
|
||||
break;
|
||||
}
|
||||
case WqCmd_af_far_pos:
|
||||
{
|
||||
sensor_af_idlechk(client);
|
||||
cmdinfo.cmd_tag = StepFocus_Far_Tag;
|
||||
cmdinfo.validate_bit = 0x80;
|
||||
if (sensor_af_cmdset(client, StepMode_Cmd, &cmdinfo) < 0)
|
||||
sensor_work->result = WqRet_fail;
|
||||
else
|
||||
sensor_work->result = WqRet_success;
|
||||
break;
|
||||
}
|
||||
case WqCmd_af_continues:
|
||||
{
|
||||
if (sensor_af_const(client) < 0)
|
||||
sensor_work->result = WqRet_fail;
|
||||
else
|
||||
sensor_work->result = WqRet_success;
|
||||
break;
|
||||
}
|
||||
case WqCmd_af_return_idle:
|
||||
{
|
||||
if (sensor_af_idlechk(client) < 0)
|
||||
sensor_work->result = WqRet_fail;
|
||||
else
|
||||
sensor_work->result = WqRet_success;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
SENSOR_TR("Unknow command(%d) in %s af workqueue!",sensor_work->cmd,SENSOR_NAME_STRING());
|
||||
break;
|
||||
}
|
||||
|
||||
if (sensor_work->wait == false) {
|
||||
kfree((void*)sensor_work);
|
||||
} else {
|
||||
wake_up(&sensor_work->done);
|
||||
}
|
||||
mutex_unlock(&sensor->wq_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
static int sensor_af_workqueue_set(struct soc_camera_device *icd, enum sensor_wq_cmd cmd, int var, bool wait)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
|
||||
struct sensor *sensor = to_sensor(client);
|
||||
struct sensor_work *wk;
|
||||
int ret=0;
|
||||
|
||||
if (sensor->sensor_wq == NULL) {
|
||||
ret = -EINVAL;
|
||||
goto sensor_af_workqueue_set_end;
|
||||
}
|
||||
|
||||
wk = kzalloc(sizeof(struct sensor_work), GFP_KERNEL);
|
||||
if (wk) {
|
||||
wk->client = client;
|
||||
INIT_WORK(&(wk->dwork.work), sensor_af_workqueue);
|
||||
wk->cmd = cmd;
|
||||
wk->result = WqRet_inval;
|
||||
wk->wait = wait;
|
||||
wk->var = var;
|
||||
init_waitqueue_head(&wk->done);
|
||||
|
||||
queue_delayed_work(sensor->sensor_wq,&(wk->dwork),0);
|
||||
|
||||
/* ddl@rock-chips.com:
|
||||
* video_lock is been locked in v4l2_ioctl function, but auto focus may slow,
|
||||
* As a result any other ioctl calls will proceed very, very slowly since each call
|
||||
* will have to wait for the AF to finish. Camera preview is pause,because VIDIOC_QBUF
|
||||
* and VIDIOC_DQBUF is sched. so unlock video_lock here.
|
||||
*/
|
||||
if (wait == true) {
|
||||
mutex_unlock(&icd->video_lock);
|
||||
if (wait_event_timeout(wk->done, (wk->result != WqRet_inval), msecs_to_jiffies(2500)) == 0) {
|
||||
SENSOR_TR("%s %s cmd(%d) is timeout!",SENSOR_NAME_STRING(),__FUNCTION__,cmd);
|
||||
}
|
||||
ret = wk->result;
|
||||
kfree((void*)wk);
|
||||
mutex_lock(&icd->video_lock);
|
||||
}
|
||||
|
||||
} else {
|
||||
SENSOR_TR("%s %s cmd(%d) ingore,because struct sensor_work malloc failed!",SENSOR_NAME_STRING(),__FUNCTION__,cmd);
|
||||
ret = -1;
|
||||
}
|
||||
sensor_af_workqueue_set_end:
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
static int sensor_parameter_record(struct i2c_client *client)
|
||||
|
|
@ -2207,7 +2365,7 @@ static int sensor_ioctrl(struct soc_camera_device *icd,enum rk29sensor_power_cmd
|
|||
}
|
||||
static int sensor_init(struct v4l2_subdev *sd, u32 val)
|
||||
{
|
||||
struct i2c_client *client = sd->priv;
|
||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||
struct soc_camera_device *icd = client->dev.platform_data;
|
||||
struct sensor *sensor = to_sensor(client);
|
||||
const struct v4l2_queryctrl *qctrl;
|
||||
|
|
@ -2262,8 +2420,7 @@ static int sensor_init(struct v4l2_subdev *sd, u32 val)
|
|||
}
|
||||
|
||||
ret = sensor_write_array(client, sensor_init_data);
|
||||
if (ret != 0)
|
||||
{
|
||||
if (ret != 0) {
|
||||
SENSOR_TR("error: %s initial failed\n",SENSOR_NAME_STRING());
|
||||
goto sensor_INIT_ERR;
|
||||
}
|
||||
|
|
@ -2322,7 +2479,7 @@ static int sensor_init(struct v4l2_subdev *sd, u32 val)
|
|||
#endif
|
||||
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);
|
||||
|
||||
sensor->info_priv.funmodule_state |= SENSOR_INIT_IS_OK;
|
||||
sensor->info_priv.funmodule_state = SENSOR_INIT_IS_OK;
|
||||
|
||||
return 0;
|
||||
sensor_INIT_ERR:
|
||||
|
|
@ -2417,7 +2574,7 @@ static unsigned long sensor_query_bus_param(struct soc_camera_device *icd)
|
|||
|
||||
static int sensor_g_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
|
||||
{
|
||||
struct i2c_client *client = sd->priv;
|
||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||
struct soc_camera_device *icd = client->dev.platform_data;
|
||||
struct sensor *sensor = to_sensor(client);
|
||||
|
||||
|
|
@ -2466,7 +2623,7 @@ static bool sensor_fmt_videochk(struct v4l2_subdev *sd, struct v4l2_mbus_framefm
|
|||
}
|
||||
static int sensor_s_fmt(struct v4l2_subdev *sd,struct v4l2_mbus_framefmt *mf)
|
||||
{
|
||||
struct i2c_client *client = sd->priv;
|
||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||
const struct sensor_datafmt *fmt;
|
||||
struct sensor *sensor = to_sensor(client);
|
||||
const struct v4l2_queryctrl *qctrl;
|
||||
|
|
@ -2658,7 +2815,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_idlechk(client);
|
||||
sensor_af_workqueue_set(icd,WqCmd_af_return_idle,0,true);
|
||||
msleep(200);
|
||||
} else {
|
||||
msleep(500);
|
||||
|
|
@ -2683,7 +2840,7 @@ static int sensor_s_fmt(struct v4l2_subdev *sd,struct v4l2_mbus_framefmt *mf)
|
|||
|
||||
static int sensor_try_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
|
||||
{
|
||||
struct i2c_client *client = sd->priv;
|
||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||
struct sensor *sensor = to_sensor(client);
|
||||
const struct sensor_datafmt *fmt;
|
||||
int ret = 0;
|
||||
|
|
@ -2712,7 +2869,7 @@ static int sensor_try_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
|
|||
|
||||
static int sensor_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *id)
|
||||
{
|
||||
struct i2c_client *client = sd->priv;
|
||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||
|
||||
if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
|
||||
return -EINVAL;
|
||||
|
|
@ -2985,13 +3142,12 @@ static int sensor_set_focus_absolute(struct soc_camera_device *icd, const struct
|
|||
int ret = 0;
|
||||
|
||||
qctrl_info = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_FOCUS_ABSOLUTE);
|
||||
if (!qctrl_info) {
|
||||
ret = -EINVAL;
|
||||
goto sensor_set_focus_absolute_end;
|
||||
}
|
||||
|
||||
if (!qctrl_info)
|
||||
return -EINVAL;
|
||||
|
||||
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 >= qctrl_info->minimum) && (value <= qctrl_info->maximum)) {
|
||||
ret = sensor_af_workqueue_set(icd, WqCmd_af_special_pos, value, true);
|
||||
SENSOR_DG("%s..%s : %d ret:0x%x\n",SENSOR_NAME_STRING(),__FUNCTION__, value,ret);
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
|
|
@ -3003,7 +3159,6 @@ static int sensor_set_focus_absolute(struct soc_camera_device *icd, const struct
|
|||
sensor->info_priv.funmodule_state,sensor->info_priv.affm_reinit);
|
||||
}
|
||||
|
||||
sensor_set_focus_absolute_end:
|
||||
return ret;
|
||||
}
|
||||
static int sensor_set_focus_relative(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
|
||||
|
|
@ -3014,13 +3169,16 @@ static int sensor_set_focus_relative(struct soc_camera_device *icd, const struct
|
|||
int ret = 0;
|
||||
|
||||
qctrl_info = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_FOCUS_RELATIVE);
|
||||
if (!qctrl_info) {
|
||||
ret = -EINVAL;
|
||||
goto sensor_set_focus_relative_end;
|
||||
}
|
||||
if (!qctrl_info)
|
||||
return -EINVAL;
|
||||
|
||||
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 >= qctrl_info->minimum) && (value <= qctrl_info->maximum)) {
|
||||
if (value > 0) {
|
||||
ret = sensor_af_workqueue_set(icd, WqCmd_af_near_pos, 0, true);
|
||||
} else {
|
||||
ret = sensor_af_workqueue_set(icd, WqCmd_af_far_pos, 0, true);
|
||||
}
|
||||
SENSOR_DG("%s..%s : %d ret:0x%x\n",SENSOR_NAME_STRING(),__FUNCTION__, value,ret);
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
|
|
@ -3031,7 +3189,6 @@ static int sensor_set_focus_relative(struct soc_camera_device *icd, const struct
|
|||
SENSOR_TR("\n %s..%s AF module state(0x%x, 0x%x) is error!\n",SENSOR_NAME_STRING(),__FUNCTION__,
|
||||
sensor->info_priv.funmodule_state,sensor->info_priv.affm_reinit);
|
||||
}
|
||||
sensor_set_focus_relative_end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -3046,7 +3203,7 @@ static int sensor_set_focus_mode(struct soc_camera_device *icd, const struct v4l
|
|||
{
|
||||
case SENSOR_AF_MODE_AUTO:
|
||||
{
|
||||
ret = sensor_af_single(client);
|
||||
ret = sensor_af_workqueue_set(icd, WqCmd_af_single, 0, true);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -3064,7 +3221,7 @@ static int sensor_set_focus_mode(struct soc_camera_device *icd, const struct v4l
|
|||
|
||||
case SENSOR_AF_MODE_CONTINUOUS:
|
||||
{
|
||||
ret = sensor_af_const(client);
|
||||
ret = sensor_af_workqueue_set(icd, WqCmd_af_continues, 0, true);
|
||||
break;
|
||||
}*/
|
||||
default:
|
||||
|
|
@ -3102,7 +3259,7 @@ static int sensor_set_flash(struct soc_camera_device *icd, const struct v4l2_que
|
|||
#endif
|
||||
static int sensor_g_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
|
||||
{
|
||||
struct i2c_client *client = sd->priv;
|
||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||
struct sensor *sensor = to_sensor(client);
|
||||
const struct v4l2_queryctrl *qctrl;
|
||||
|
||||
|
|
@ -3161,7 +3318,7 @@ static int sensor_g_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
|
|||
|
||||
static int sensor_s_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
|
||||
{
|
||||
struct i2c_client *client = sd->priv;
|
||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||
struct sensor *sensor = to_sensor(client);
|
||||
struct soc_camera_device *icd = client->dev.platform_data;
|
||||
const struct v4l2_queryctrl *qctrl;
|
||||
|
|
@ -3335,7 +3492,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;
|
||||
int val_offset,ret;
|
||||
|
||||
qctrl = soc_camera_find_qctrl(&sensor_ops, ext_ctrl->id);
|
||||
|
||||
|
|
@ -3423,8 +3580,12 @@ 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) != 0) {
|
||||
if(0 == (sensor->info_priv.funmodule_state & SENSOR_AF_IS_OK)) {
|
||||
sensor->info_priv.auto_focus = SENSOR_AF_MODE_AUTO;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
sensor->info_priv.auto_focus = SENSOR_AF_MODE_AUTO;
|
||||
} else if (SENSOR_AF_MODE_AUTO == sensor->info_priv.auto_focus){
|
||||
if (ext_ctrl->value == 0)
|
||||
|
|
@ -3467,7 +3628,7 @@ static int sensor_s_ext_control(struct soc_camera_device *icd, struct v4l2_ext_c
|
|||
|
||||
static int sensor_g_ext_controls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ext_ctrl)
|
||||
{
|
||||
struct i2c_client *client = sd->priv;
|
||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||
struct soc_camera_device *icd = client->dev.platform_data;
|
||||
int i, error_cnt=0, error_idx=-1;
|
||||
|
||||
|
|
@ -3492,7 +3653,7 @@ static int sensor_g_ext_controls(struct v4l2_subdev *sd, struct v4l2_ext_control
|
|||
|
||||
static int sensor_s_ext_controls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ext_ctrl)
|
||||
{
|
||||
struct i2c_client *client = sd->priv;
|
||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||
struct soc_camera_device *icd = client->dev.platform_data;
|
||||
int i, error_cnt=0, error_idx=-1;
|
||||
|
||||
|
|
@ -3516,7 +3677,7 @@ static int sensor_s_ext_controls(struct v4l2_subdev *sd, struct v4l2_ext_control
|
|||
|
||||
static int sensor_s_stream(struct v4l2_subdev *sd, int enable)
|
||||
{
|
||||
struct i2c_client *client = sd->priv;
|
||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||
struct sensor *sensor = to_sensor(client);
|
||||
#if CONFIG_SENSOR_Focus
|
||||
struct soc_camera_device *icd = client->dev.platform_data;
|
||||
|
|
@ -3534,34 +3695,17 @@ 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)) {
|
||||
if (sensor->sensor_wq != NULL) {
|
||||
mutex_lock(&sensor->wq_lock);
|
||||
if (sensor->sensor_wk.state == sensor_working) {
|
||||
SENSOR_DG("%s sensor af firmware thread is runing, Ingore current work",SENSOR_NAME_STRING());
|
||||
mutex_unlock(&sensor->wq_lock);
|
||||
goto sensor_s_stream_end;
|
||||
}
|
||||
sensor->sensor_wk.state = sensor_working;
|
||||
mutex_unlock(&sensor->wq_lock);
|
||||
sensor->sensor_wk.client = client;
|
||||
INIT_WORK(&(sensor->sensor_wk.dwork.work), sensor_af_workqueue);
|
||||
queue_delayed_work(sensor->sensor_wq,&(sensor->sensor_wk.dwork), 0);
|
||||
}
|
||||
sensor_af_workqueue_set(icd, WqCmd_af_init, 0, false);
|
||||
sensor->info_priv.affm_reinit = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else if (enable == 0) {
|
||||
sensor->info_priv.enable = 0;
|
||||
#if CONFIG_SENSOR_Focus
|
||||
flush_work(&(sensor->sensor_wk.dwork.work));
|
||||
mutex_lock(&sensor->wq_lock);
|
||||
sensor->sensor_wk.state = sensor_work_ready;
|
||||
mutex_unlock(&sensor->wq_lock);
|
||||
#if CONFIG_SENSOR_Focus
|
||||
flush_workqueue(sensor->sensor_wq);
|
||||
#endif
|
||||
}
|
||||
|
||||
sensor_s_stream_end:
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -3627,7 +3771,7 @@ static int sensor_video_probe(struct soc_camera_device *icd,
|
|||
}
|
||||
static long sensor_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
|
||||
{
|
||||
struct i2c_client *client = sd->priv;
|
||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||
struct soc_camera_device *icd = client->dev.platform_data;
|
||||
struct sensor *sensor = to_sensor(client);
|
||||
int ret = 0;
|
||||
|
|
@ -3659,7 +3803,6 @@ static long sensor_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
|
|||
/* ddl@rock-chips.com : if gpio_flash havn't been set in board-xxx.c, sensor driver must notify is not support flash control
|
||||
for this project */
|
||||
#if CONFIG_SENSOR_Flash
|
||||
int i;
|
||||
if (sensor->sensor_gpio_res) {
|
||||
printk("flash io:%d\n",sensor->sensor_gpio_res->gpio_flash);
|
||||
if (sensor->sensor_gpio_res->gpio_flash == INVALID_GPIO) {
|
||||
|
|
@ -3766,11 +3909,10 @@ static int sensor_probe(struct i2c_client *client,
|
|||
sensor = NULL;
|
||||
} else {
|
||||
#if CONFIG_SENSOR_Focus
|
||||
sensor->sensor_wq = create_workqueue(SENSOR_NAME_STRING( wq));
|
||||
sensor->sensor_wq = create_workqueue(SENSOR_NAME_STRING(_af_workqueue));
|
||||
if (sensor->sensor_wq == NULL)
|
||||
SENSOR_TR("%s workqueue create fail!", SENSOR_NAME_STRING( wq));
|
||||
SENSOR_TR("%s create fail!", SENSOR_NAME_STRING(_af_workqueue));
|
||||
mutex_init(&sensor->wq_lock);
|
||||
sensor->sensor_wk.state = sensor_work_ready;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3299,19 +3299,32 @@ static const struct sensor_datafmt sensor_colour_fmts[] = {
|
|||
{V4L2_MBUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_JPEG},
|
||||
{V4L2_MBUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG}
|
||||
};
|
||||
|
||||
enum sensor_work_state
|
||||
enum sensor_wq_cmd
|
||||
{
|
||||
sensor_work_ready = 0,
|
||||
sensor_working,
|
||||
WqCmd_af_init,
|
||||
WqCmd_af_single,
|
||||
WqCmd_af_special_pos,
|
||||
WqCmd_af_far_pos,
|
||||
WqCmd_af_near_pos,
|
||||
WqCmd_af_continues,
|
||||
WqCmd_af_update_zone
|
||||
};
|
||||
enum sensor_wq_result
|
||||
{
|
||||
WqRet_success = 0,
|
||||
WqRet_fail = -1,
|
||||
WqRet_inval = -2
|
||||
};
|
||||
struct sensor_work
|
||||
{
|
||||
struct i2c_client *client;
|
||||
struct delayed_work dwork;
|
||||
enum sensor_work_state state;
|
||||
enum sensor_wq_cmd cmd;
|
||||
wait_queue_head_t done;
|
||||
enum sensor_wq_result result;
|
||||
bool wait;
|
||||
int var;
|
||||
};
|
||||
|
||||
typedef struct sensor_info_priv_s
|
||||
{
|
||||
int whiteBalance;
|
||||
|
|
@ -3356,7 +3369,6 @@ struct sensor
|
|||
sensor_info_priv_t info_priv;
|
||||
struct sensor_parameter parameter;
|
||||
struct workqueue_struct *sensor_wq;
|
||||
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
|
||||
|
|
@ -3832,7 +3844,7 @@ static int sensor_af_init(struct i2c_client *client)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int sensor_af_wq_function(struct i2c_client *client)
|
||||
static int sensor_af_downfirmware(struct i2c_client *client)
|
||||
{
|
||||
struct sensor *sensor = to_sensor(client);
|
||||
struct af_cmdinfo cmdinfo;
|
||||
|
|
@ -3841,8 +3853,7 @@ static int sensor_af_wq_function(struct i2c_client *client)
|
|||
struct v4l2_mbus_framefmt mf;
|
||||
|
||||
SENSOR_DG("%s %s Enter\n",SENSOR_NAME_STRING(), __FUNCTION__);
|
||||
|
||||
mutex_lock(&sensor->wq_lock);
|
||||
|
||||
if (sensor_af_init(client)) {
|
||||
sensor->info_priv.funmodule_state &= (~SENSOR_AF_IS_OK);
|
||||
ret = -1;
|
||||
|
|
@ -3893,26 +3904,157 @@ static int sensor_af_wq_function(struct i2c_client *client)
|
|||
default:
|
||||
{
|
||||
SENSOR_DG("%s focus mode(0x%x) is unkonwn\n",SENSOR_NAME_STRING(),sensor->info_priv.auto_focus);
|
||||
goto sensor_af_wq_function_end;
|
||||
goto sensor_af_downfirmware_end;
|
||||
}
|
||||
}
|
||||
}
|
||||
SENSOR_DG("%s sensor_af_wq_function set focus mode(0x%x) ret:0x%x\n",SENSOR_NAME_STRING(), sensor->info_priv.auto_focus,ret);
|
||||
SENSOR_DG("%s sensor_af_downfirmware set focus mode(0x%x) ret:0x%x\n",SENSOR_NAME_STRING(), sensor->info_priv.auto_focus,ret);
|
||||
}
|
||||
|
||||
sensor_af_wq_function_end:
|
||||
sensor->sensor_wk.state = sensor_work_ready;
|
||||
mutex_unlock(&sensor->wq_lock);
|
||||
sensor_af_downfirmware_end:
|
||||
|
||||
return ret;
|
||||
}
|
||||
static void sensor_af_workqueue(struct work_struct *work)
|
||||
{
|
||||
struct sensor_work *sensor_work = container_of(work, struct sensor_work, dwork.work);
|
||||
struct i2c_client *client = sensor_work->client;
|
||||
struct sensor *sensor = to_sensor(client);
|
||||
struct af_cmdinfo cmdinfo;
|
||||
|
||||
SENSOR_DG("%s %s Enter, cmd:0x%x \n",SENSOR_NAME_STRING(), __FUNCTION__,sensor_work->cmd);
|
||||
|
||||
mutex_lock(&sensor->wq_lock);
|
||||
switch (sensor_work->cmd)
|
||||
{
|
||||
case WqCmd_af_init:
|
||||
{
|
||||
if (sensor_af_downfirmware(client) < 0) {
|
||||
SENSOR_TR("%s Sensor_af_init is failed in sensor_af_workqueue!\n",SENSOR_NAME_STRING());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WqCmd_af_single:
|
||||
{
|
||||
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;
|
||||
} else {
|
||||
sensor_work->result = WqRet_success;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WqCmd_af_special_pos:
|
||||
{
|
||||
sensor_af_idlechk(client);
|
||||
|
||||
if (sensor_af_wq_function(client) < 0) {
|
||||
SENSOR_TR("%s af workqueue return false\n",SENSOR_NAME_STRING());
|
||||
}
|
||||
cmdinfo.cmd_tag = StepFocus_Spec_Tag;
|
||||
cmdinfo.cmd_para[0] = sensor_work->var;
|
||||
cmdinfo.validate_bit = 0x81;
|
||||
if (sensor_af_cmdset(client, StepMode_Cmd, &cmdinfo) < 0)
|
||||
sensor_work->result = WqRet_fail;
|
||||
else
|
||||
sensor_work->result = WqRet_success;
|
||||
break;
|
||||
}
|
||||
case WqCmd_af_near_pos:
|
||||
{
|
||||
sensor_af_idlechk(client);
|
||||
cmdinfo.cmd_tag = StepFocus_Near_Tag;
|
||||
cmdinfo.validate_bit = 0x80;
|
||||
if (sensor_af_cmdset(client, StepMode_Cmd, &cmdinfo) < 0)
|
||||
sensor_work->result = WqRet_fail;
|
||||
else
|
||||
sensor_work->result = WqRet_success;
|
||||
break;
|
||||
}
|
||||
case WqCmd_af_far_pos:
|
||||
{
|
||||
sensor_af_idlechk(client);
|
||||
cmdinfo.cmd_tag = StepFocus_Far_Tag;
|
||||
cmdinfo.validate_bit = 0x80;
|
||||
if (sensor_af_cmdset(client, StepMode_Cmd, &cmdinfo) < 0)
|
||||
sensor_work->result = WqRet_fail;
|
||||
else
|
||||
sensor_work->result = WqRet_success;
|
||||
break;
|
||||
}
|
||||
case WqCmd_af_continues:
|
||||
{
|
||||
if (sensor_af_const(client) < 0)
|
||||
sensor_work->result = WqRet_fail;
|
||||
else
|
||||
sensor_work->result = WqRet_success;
|
||||
break;
|
||||
}
|
||||
case WqCmd_af_update_zone:
|
||||
{
|
||||
if (sensor_af_zoneupdate(client) < 0)
|
||||
sensor_work->result = WqRet_fail;
|
||||
else
|
||||
sensor_work->result = WqRet_success;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
SENSOR_TR("Unknow command(%d) in %s af workqueue!",sensor_work->cmd,SENSOR_NAME_STRING());
|
||||
break;
|
||||
}
|
||||
|
||||
if (sensor_work->wait == false) {
|
||||
kfree((void*)sensor_work);
|
||||
} else {
|
||||
wake_up(&sensor_work->done);
|
||||
}
|
||||
mutex_unlock(&sensor->wq_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
static int sensor_af_workqueue_set(struct soc_camera_device *icd, enum sensor_wq_cmd cmd, int var, bool wait)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
|
||||
struct sensor *sensor = to_sensor(client);
|
||||
struct sensor_work *wk;
|
||||
int ret=0;
|
||||
|
||||
if (sensor->sensor_wq == NULL) {
|
||||
ret = -EINVAL;
|
||||
goto sensor_af_workqueue_set_end;
|
||||
}
|
||||
|
||||
wk = kzalloc(sizeof(struct sensor_work), GFP_KERNEL);
|
||||
if (wk) {
|
||||
wk->client = client;
|
||||
INIT_WORK(&(wk->dwork.work), sensor_af_workqueue);
|
||||
wk->cmd = cmd;
|
||||
wk->result = WqRet_inval;
|
||||
wk->wait = wait;
|
||||
wk->var = var;
|
||||
init_waitqueue_head(&wk->done);
|
||||
|
||||
queue_delayed_work(sensor->sensor_wq,&(wk->dwork),0);
|
||||
|
||||
/* ddl@rock-chips.com:
|
||||
* video_lock is been locked in v4l2_ioctl function, but auto focus may slow,
|
||||
* As a result any other ioctl calls will proceed very, very slowly since each call
|
||||
* will have to wait for the AF to finish. Camera preview is pause,because VIDIOC_QBUF
|
||||
* and VIDIOC_DQBUF is sched. so unlock video_lock here.
|
||||
*/
|
||||
if (wait == true) {
|
||||
mutex_unlock(&icd->video_lock);
|
||||
if (wait_event_timeout(wk->done, (wk->result != WqRet_inval), msecs_to_jiffies(2500)) == 0) {
|
||||
SENSOR_TR("%s %s cmd(%d) is timeout!",SENSOR_NAME_STRING(),__FUNCTION__,cmd);
|
||||
}
|
||||
ret = wk->result;
|
||||
kfree((void*)wk);
|
||||
mutex_lock(&icd->video_lock);
|
||||
}
|
||||
|
||||
} else {
|
||||
SENSOR_TR("%s %s cmd(%d) ingore,because struct sensor_work malloc failed!",SENSOR_NAME_STRING(),__FUNCTION__,cmd);
|
||||
ret = -1;
|
||||
}
|
||||
sensor_af_workqueue_set_end:
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
static int sensor_parameter_record(struct i2c_client *client)
|
||||
|
|
@ -4217,7 +4359,7 @@ static int sensor_init(struct v4l2_subdev *sd, u32 val)
|
|||
#endif
|
||||
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);
|
||||
|
||||
sensor->info_priv.funmodule_state |= SENSOR_INIT_IS_OK;
|
||||
sensor->info_priv.funmodule_state = SENSOR_INIT_IS_OK;
|
||||
|
||||
return 0;
|
||||
sensor_INIT_ERR:
|
||||
|
|
@ -4238,7 +4380,7 @@ static int sensor_deactivate(struct i2c_client *client)
|
|||
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_write(client,0x3019,0x00); // STROBE,SDA
|
||||
sensor_task_lock(client, 0);
|
||||
}
|
||||
sensor_ioctrl(icd, Sensor_PowerDown, 1);
|
||||
|
|
@ -4535,12 +4677,12 @@ static int sensor_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
|
|||
sensor_set_whiteBalance(icd, qctrl,sensor->info_priv.whiteBalance);
|
||||
}
|
||||
#if CONFIG_SENSOR_Focus
|
||||
if (sensor->info_priv.auto_focus != SENSOR_AF_MODE_INFINITY) {
|
||||
if (sensor_af_zoneupdate(client) == 0) {
|
||||
if ((sensor->info_priv.auto_focus == SENSOR_AF_MODE_AUTO) ||
|
||||
if (sensor->info_priv.auto_focus != SENSOR_AF_MODE_INFINITY) {
|
||||
if (sensor_af_workqueue_set(icd, WqCmd_af_update_zone,0,true) == 0) {
|
||||
if ((sensor->info_priv.auto_focus == SENSOR_AF_MODE_AUTO) ||
|
||||
(sensor->info_priv.auto_focus == SENSOR_AF_MODE_CONTINUOUS)) {
|
||||
msleep(80);
|
||||
sensor_af_single(client);
|
||||
sensor_af_workqueue_set(icd, WqCmd_af_single,0,false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4561,15 +4703,17 @@ static int sensor_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
|
|||
sensor_set_whiteBalance(icd, qctrl,sensor->info_priv.whiteBalance);
|
||||
}
|
||||
#if CONFIG_SENSOR_Focus
|
||||
if (sensor->info_priv.auto_focus != SENSOR_AF_MODE_INFINITY) {
|
||||
if (sensor_af_zoneupdate(client) == 0) {
|
||||
if (sensor->info_priv.auto_focus == SENSOR_AF_MODE_CONTINUOUS) {
|
||||
sensor_af_const(client);
|
||||
if (sensor->info_priv.auto_focus != SENSOR_AF_MODE_INFINITY) {
|
||||
/* ddl@rock-chips.com: The af operation is not necessary, if user don't care whether in focus after preview*/
|
||||
if (sensor_af_workqueue_set(icd, WqCmd_af_update_zone,0,true) == 0) {
|
||||
if (sensor->info_priv.auto_focus == SENSOR_AF_MODE_CONTINUOUS) {
|
||||
sensor_af_workqueue_set(icd, WqCmd_af_continues,0,false);
|
||||
} else if (sensor->info_priv.auto_focus == SENSOR_AF_MODE_AUTO) {
|
||||
msleep(80);
|
||||
sensor_af_single(client);
|
||||
msleep(100);
|
||||
sensor_af_workqueue_set(icd, WqCmd_af_single,0,false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
msleep(600); /* ddl@rock-chips.com : whitebalance auto must delay */
|
||||
}
|
||||
|
|
@ -4894,24 +5038,15 @@ static int sensor_set_focus_absolute(struct soc_camera_device *icd, const struct
|
|||
struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
|
||||
struct sensor *sensor = to_sensor(client);
|
||||
const struct v4l2_queryctrl *qctrl_info;
|
||||
struct af_cmdinfo cmdinfo;
|
||||
int ret = 0;
|
||||
|
||||
qctrl_info = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_FOCUS_ABSOLUTE);
|
||||
if (!qctrl_info)
|
||||
return -EINVAL;
|
||||
|
||||
|
||||
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 (sensor_af_idlechk(client))
|
||||
goto sensor_set_focus_absolute_end;
|
||||
|
||||
cmdinfo.cmd_tag = StepFocus_Spec_Tag;
|
||||
cmdinfo.cmd_para[0] = value;
|
||||
cmdinfo.validate_bit = 0x81;
|
||||
ret = sensor_af_cmdset(client, StepMode_Cmd, &cmdinfo);
|
||||
//ret |= sensor_af_cmdset(client, ReturnIdle_Cmd, NULL);
|
||||
ret = sensor_af_workqueue_set(icd, WqCmd_af_special_pos, value, true);
|
||||
SENSOR_DG("%s..%s : %d ret:0x%x\n",SENSOR_NAME_STRING(),__FUNCTION__, value,ret);
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
|
|
@ -4923,7 +5058,6 @@ static int sensor_set_focus_absolute(struct soc_camera_device *icd, const struct
|
|||
sensor->info_priv.funmodule_state,sensor->info_priv.affm_reinit);
|
||||
}
|
||||
|
||||
sensor_set_focus_absolute_end:
|
||||
return ret;
|
||||
}
|
||||
static int sensor_set_focus_relative(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
|
||||
|
|
@ -4931,27 +5065,19 @@ static int sensor_set_focus_relative(struct soc_camera_device *icd, const struct
|
|||
struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
|
||||
struct sensor *sensor = to_sensor(client);
|
||||
const struct v4l2_queryctrl *qctrl_info;
|
||||
struct af_cmdinfo cmdinfo;
|
||||
int ret = 0;
|
||||
|
||||
qctrl_info = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_FOCUS_RELATIVE);
|
||||
if (!qctrl_info)
|
||||
return -EINVAL;
|
||||
return -EINVAL;
|
||||
|
||||
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 (sensor_af_idlechk(client))
|
||||
goto sensor_set_focus_relative_end;
|
||||
|
||||
if (value > 0) {
|
||||
cmdinfo.cmd_tag = StepFocus_Near_Tag;
|
||||
} else if (value < 0) {
|
||||
cmdinfo.cmd_tag = StepFocus_Far_Tag;
|
||||
}
|
||||
cmdinfo.validate_bit = 0x80;
|
||||
ret = sensor_af_cmdset(client, StepMode_Cmd, &cmdinfo);
|
||||
|
||||
if ((value >= qctrl_info->minimum) && (value <= qctrl_info->maximum)) {
|
||||
if (value > 0) {
|
||||
ret = sensor_af_workqueue_set(icd, WqCmd_af_near_pos, 0, true);
|
||||
} else {
|
||||
ret = sensor_af_workqueue_set(icd, WqCmd_af_far_pos, 0, true);
|
||||
}
|
||||
SENSOR_DG("%s..%s : %d ret:0x%x\n",SENSOR_NAME_STRING(),__FUNCTION__, value,ret);
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
|
|
@ -4962,14 +5088,13 @@ static int sensor_set_focus_relative(struct soc_camera_device *icd, const struct
|
|||
SENSOR_TR("\n %s..%s AF module state(0x%x, 0x%x) is error!\n",SENSOR_NAME_STRING(),__FUNCTION__,
|
||||
sensor->info_priv.funmodule_state,sensor->info_priv.affm_reinit);
|
||||
}
|
||||
sensor_set_focus_relative_end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sensor_set_focus_mode(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
|
||||
struct sensor *sensor = to_sensor(client);
|
||||
struct sensor *sensor = to_sensor(client);
|
||||
int ret = 0;
|
||||
|
||||
if ((sensor->info_priv.funmodule_state & SENSOR_AF_IS_OK) && (sensor->info_priv.affm_reinit == 0)) {
|
||||
|
|
@ -4977,7 +5102,7 @@ static int sensor_set_focus_mode(struct soc_camera_device *icd, const struct v4l
|
|||
{
|
||||
case SENSOR_AF_MODE_AUTO:
|
||||
{
|
||||
ret = sensor_af_single(client);
|
||||
ret = sensor_af_workqueue_set(icd, WqCmd_af_single, 0, true);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -4995,7 +5120,7 @@ static int sensor_set_focus_mode(struct soc_camera_device *icd, const struct v4l
|
|||
|
||||
case SENSOR_AF_MODE_CONTINUOUS:
|
||||
{
|
||||
ret = sensor_af_const(client);
|
||||
ret = sensor_af_workqueue_set(icd, WqCmd_af_continues, 0, true);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
@ -5485,35 +5610,18 @@ static int sensor_s_stream(struct v4l2_subdev *sd, int enable)
|
|||
mf.field = V4L2_FIELD_NONE;
|
||||
/* 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)) {
|
||||
if (sensor->sensor_wq != NULL) {
|
||||
mutex_lock(&sensor->wq_lock);
|
||||
if (sensor->sensor_wk.state == sensor_working) {
|
||||
SENSOR_DG("%s sensor af firmware thread is runing, Ingore current work",SENSOR_NAME_STRING());
|
||||
mutex_unlock(&sensor->wq_lock);
|
||||
goto sensor_s_stream_end;
|
||||
}
|
||||
sensor->sensor_wk.state = sensor_working;
|
||||
mutex_unlock(&sensor->wq_lock);
|
||||
sensor->sensor_wk.client = client;
|
||||
INIT_WORK(&(sensor->sensor_wk.dwork.work), sensor_af_workqueue);
|
||||
queue_delayed_work(sensor->sensor_wq,&(sensor->sensor_wk.dwork), 0);
|
||||
}
|
||||
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->info_priv.affm_reinit = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else if (enable == 0) {
|
||||
sensor->info_priv.enable = 0;
|
||||
#if CONFIG_SENSOR_Focus
|
||||
flush_work(&(sensor->sensor_wk.dwork.work));
|
||||
mutex_lock(&sensor->wq_lock);
|
||||
sensor->sensor_wk.state = sensor_work_ready;
|
||||
mutex_unlock(&sensor->wq_lock);
|
||||
#if CONFIG_SENSOR_Focus
|
||||
flush_workqueue(sensor->sensor_wq);
|
||||
#endif
|
||||
}
|
||||
|
||||
sensor_s_stream_end:
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -5719,11 +5827,10 @@ static int sensor_probe(struct i2c_client *client,
|
|||
sensor = NULL;
|
||||
} else {
|
||||
#if CONFIG_SENSOR_Focus
|
||||
sensor->sensor_wq = create_workqueue(SENSOR_NAME_STRING( wq));
|
||||
sensor->sensor_wq = create_workqueue(SENSOR_NAME_STRING(_af_workqueue));
|
||||
if (sensor->sensor_wq == NULL)
|
||||
SENSOR_TR("%s workqueue create fail!", SENSOR_NAME_STRING( wq));
|
||||
SENSOR_TR("%s create fail!", SENSOR_NAME_STRING(_af_workqueue));
|
||||
mutex_init(&sensor->wq_lock);
|
||||
sensor->sensor_wk.state = sensor_work_ready;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -475,7 +475,6 @@ static void rk29_videobuf_queue(struct videobuf_queue *vq,
|
|||
else
|
||||
BUG(); /* ddl@rock-chips.com : The same videobuffer queue again */
|
||||
}
|
||||
|
||||
if (!pcdev->active) {
|
||||
pcdev->active = vb;
|
||||
rk29_videobuf_capture(vb);
|
||||
|
|
@ -643,7 +642,7 @@ static irqreturn_t rk29_camera_irq(int irq, void *data)
|
|||
wk->vb = vb;
|
||||
wk->pcdev = pcdev;
|
||||
queue_work(pcdev->camera_wq, &(wk->work));
|
||||
} else {
|
||||
} else {
|
||||
wake_up(&vb->done);
|
||||
}
|
||||
}
|
||||
|
|
@ -1994,7 +1993,7 @@ static int rk29_camera_probe(struct platform_device *pdev)
|
|||
goto exit_reqirq;
|
||||
}
|
||||
|
||||
pcdev->camera_wq = create_workqueue("camera wq");
|
||||
pcdev->camera_wq = create_workqueue("rk_camera_workqueue");
|
||||
if (pcdev->camera_wq == NULL)
|
||||
goto exit_free_irq;
|
||||
INIT_WORK(&pcdev->camera_reinit_work, rk29_camera_reinit_work);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user