diff options
Diffstat (limited to 'drivers/media/video/s5k5ccgx.c')
-rw-r--r-- | drivers/media/video/s5k5ccgx.c | 143 |
1 files changed, 85 insertions, 58 deletions
diff --git a/drivers/media/video/s5k5ccgx.c b/drivers/media/video/s5k5ccgx.c index 2123304..51ffd6f 100644 --- a/drivers/media/video/s5k5ccgx.c +++ b/drivers/media/video/s5k5ccgx.c @@ -1309,15 +1309,15 @@ static int s5k5ccgx_af_start_preflash(struct v4l2_subdev *sd) break; } - /* We wait for 200ms after pre flash on. - * check whether AE is stable.*/ - msleep(200); - /* Check AE-stable */ if (state->focus.preflash == PREFLASH_ON) { + /* We wait for 200ms after pre flash on. + * check whether AE is stable.*/ + msleep(200); + /* Do checking AE-stable */ for (count = 0; count < AE_STABLE_SEARCH_COUNT; count++) { - if (state->focus.start == AUTO_FOCUS_OFF) { + if (state->focus.cancel) { cam_info("af_start_preflash: \ AF is cancelled!\n"); state->focus.status = AF_RESULT_CANCELLED; @@ -1332,11 +1332,11 @@ static int s5k5ccgx_af_start_preflash(struct v4l2_subdev *sd) if (read_value == 0x0001) { af_dbg("AE-stable success," " count=%d, delay=%dms\n", count, - state->one_frame_delay_ms); + AE_STABLE_SEARCH_DELAY); break; } - msleep(state->one_frame_delay_ms); + msleep(AE_STABLE_SEARCH_DELAY); } /* restore write mode */ @@ -1345,10 +1345,10 @@ static int s5k5ccgx_af_start_preflash(struct v4l2_subdev *sd) if (unlikely(count >= AE_STABLE_SEARCH_COUNT)) { cam_err("%s: ERROR, AE unstable." " count=%d, delay=%dms\n", - __func__, count, state->one_frame_delay_ms); + __func__, count, AE_STABLE_SEARCH_DELAY); /* return -ENODEV; */ } - } else if (state->focus.start == AUTO_FOCUS_OFF) { + } else if (state->focus.cancel) { cam_info("af_start_preflash: AF is cancelled!\n"); state->focus.status = AF_RESULT_CANCELLED; } @@ -1364,6 +1364,7 @@ static int s5k5ccgx_af_start_preflash(struct v4l2_subdev *sd) state->focus.preflash = PREFLASH_NONE; } + state->focus.cancel = 0; if (state->focus.touch) state->focus.touch = 0; } @@ -1408,7 +1409,7 @@ static int s5k5ccgx_do_af(struct v4l2_subdev *sd) /*1st search*/ for (count = 0; count < FIRST_AF_SEARCH_COUNT; count++) { - if (state->focus.start == AUTO_FOCUS_OFF) { + if (state->focus.cancel) { cam_dbg("do_af: AF is cancelled while doing(1st)\n"); state->focus.status = AF_RESULT_CANCELLED; goto check_done; @@ -1423,7 +1424,7 @@ static int s5k5ccgx_do_af(struct v4l2_subdev *sd) if (read_value != 0x01) break; - msleep(state->one_frame_delay_ms); + msleep(AF_SEARCH_DELAY); } if (read_value != 0x02) { @@ -1436,14 +1437,14 @@ static int s5k5ccgx_do_af(struct v4l2_subdev *sd) /*2nd search*/ cam_dbg("AF 2nd search\n"); for (count = 0; count < SECOND_AF_SEARCH_COUNT; count++) { - msleep(state->one_frame_delay_ms); - - if (state->focus.start == AUTO_FOCUS_OFF) { + if (state->focus.cancel) { cam_dbg("do_af: AF is cancelled while doing(2nd)\n"); state->focus.status = AF_RESULT_CANCELLED; goto check_done; } + msleep(AF_SEARCH_DELAY); + read_value = 0x0FFFF; s5k5ccgx_i2c_write_twobyte(client, 0x002C, 0x7000); s5k5ccgx_i2c_write_twobyte(client, 0x002E, 0x1F2F); @@ -1472,11 +1473,12 @@ check_done: * But we now unlock it unconditionally if AF is started, */ if (state->focus.status == AF_RESULT_CANCELLED) { - cam_dbg("%s: Single AF cancelled.\n", __func__); + cam_dbg("do_af: Single AF cancelled\n"); s5k5ccgx_set_lock(sd, AEAWB_UNLOCK, false); + state->focus.cancel = 0; } else { state->focus.start = AUTO_FOCUS_OFF; - cam_dbg("%s: Single AF finished\n", __func__); + cam_dbg("do_af: Single AF finished\n"); } if ((state->focus.preflash == PREFLASH_ON) && @@ -1519,14 +1521,18 @@ static int s5k5ccgx_set_af(struct v4l2_subdev *sd, s32 val) state->focus.start = val; if (val == AUTO_FOCUS_ON) { + state->focus.cancel = 0; err = queue_work(state->workqueue, &state->af_work); - if (likely(err)) - state->focus.status = AF_RESULT_DOING; - else - cam_warn("WARNING, AF is still processing. So new AF cannot start\n"); + if (unlikely(!err)) { + cam_warn("AF is still operating!\n"); + return 0; + } + + state->focus.status = AF_RESULT_DOING; } else { /* Cancel AF */ cam_info("set_af: AF cancel requested!\n"); + state->focus.cancel = 1; } cam_trace("X\n"); @@ -1540,7 +1546,7 @@ static int s5k5ccgx_stop_af(struct v4l2_subdev *sd) int err = 0; cam_trace("E\n"); - mutex_lock(&state->af_lock); + /* mutex_lock(&state->af_lock); */ switch (state->focus.status) { case AF_RESULT_FAILED: @@ -1568,23 +1574,15 @@ static int s5k5ccgx_stop_af(struct v4l2_subdev *sd) break; } - if (!state->focus.touch) { - /* We move lens to default position if af is cancelled.*/ - err = s5k5ccgx_return_focus(sd); - if (unlikely(err)) { - cam_err("%s: ERROR, fail to af_norma_mode (%d)\n", - __func__, err); - goto err_out; - } - } else + if (state->focus.touch) state->focus.touch = 0; - mutex_unlock(&state->af_lock); + /* mutex_unlock(&state->af_lock); */ cam_trace("X\n"); return 0; err_out: - mutex_unlock(&state->af_lock); + /* mutex_unlock(&state->af_lock); */ return err; } @@ -1593,22 +1591,39 @@ static void s5k5ccgx_af_worker(struct work_struct *work) struct s5k5ccgx_state *state = container_of(work, \ struct s5k5ccgx_state, af_work); struct v4l2_subdev *sd = &state->sd; + struct s5k5ccgx_interval *win_stable = &state->focus.win_stable; + u32 touch_win_delay = 0; + s32 interval = 0; int err = -EINVAL; cam_trace("E\n"); mutex_lock(&state->af_lock); + state->focus.reset_done = 0; if (state->sensor_mode == SENSOR_CAMERA) { state->one_frame_delay_ms = ONE_FRAME_DELAY_MS_NORMAL; + touch_win_delay = ONE_FRAME_DELAY_MS_LOW; err = s5k5ccgx_af_start_preflash(sd); if (unlikely(err)) goto out; if (state->focus.status == AF_RESULT_CANCELLED) goto out; - } else { - state->one_frame_delay_ms = 50; + } else + state->one_frame_delay_ms = touch_win_delay = 50; + + /* sleep here for the time needed for af window before do_af. */ + if (state->focus.touch) { + do_gettimeofday(&win_stable->curr_time); + interval = GET_ELAPSED_TIME(win_stable->curr_time, \ + win_stable->before_time) / 1000; + if (interval < touch_win_delay) { + cam_dbg("window stable: %dms + %dms\n", interval, + touch_win_delay - interval); + debug_msleep(sd, touch_win_delay - interval); + } else + cam_dbg("window stable: %dms\n", interval); } s5k5ccgx_do_af(sd); @@ -1623,19 +1638,36 @@ out: static int s5k5ccgx_set_focus_mode(struct v4l2_subdev *sd, s32 val) { struct s5k5ccgx_state *state = to_state(sd); - u32 af_cancel = 0; + u32 cancel = 0; + u8 focus_mode = (u8)val; int err = -EINVAL; /* cam_trace("E\n");*/ - cam_dbg("%s val =%d(0x%X)\n", __func__, val, val); if (state->focus.mode == val) return 0; - af_cancel = (u32)val & FOCUS_MODE_DEFAULT; + cancel = (u32)val & FOCUS_MODE_DEFAULT; + + /* Do nothing if cancel request occurs when af is being finished*/ + if (cancel && (state->focus.status == AF_RESULT_DOING)) { + state->focus.cancel = 1; + return 0; + } + + cam_dbg("%s val =%d(0x%X)\n", __func__, val, val); + mutex_lock(&state->af_lock); + if (cancel) { + s5k5ccgx_stop_af(sd); + if (state->focus.reset_done) { + cam_dbg("AF is already cancelled fully\n"); + goto out; + } + state->focus.reset_done = 1; + } - switch (val) { + switch (focus_mode) { case FOCUS_MODE_MACRO: err = s5k5ccgx_set_from_table(sd, "af_macro_mode", &state->regs->af_macro_mode, 1, 0); @@ -1645,7 +1677,7 @@ static int s5k5ccgx_set_focus_mode(struct v4l2_subdev *sd, s32 val) goto err_out; } - state->focus.mode = FOCUS_MODE_MACRO; + state->focus.mode = focus_mode; break; case FOCUS_MODE_INFINITY: @@ -1659,7 +1691,7 @@ static int s5k5ccgx_set_focus_mode(struct v4l2_subdev *sd, s32 val) goto err_out; } - state->focus.mode = val; + state->focus.mode = focus_mode; break; case FOCUS_MODE_FACEDETECT: @@ -1668,18 +1700,14 @@ static int s5k5ccgx_set_focus_mode(struct v4l2_subdev *sd, s32 val) break; default: - if (!af_cancel) { - cam_err("%s: ERROR, invalid val(0x%X)\n:", - __func__, val); - goto err_out; - } + cam_err("%s: ERROR, invalid val(0x%X)\n:", + __func__, val); + goto err_out; break; } - mutex_unlock(&state->af_lock); - - if (af_cancel) - s5k5ccgx_stop_af(sd); +out: + mutex_unlock(&state->af_lock); return 0; err_out: @@ -1820,11 +1848,11 @@ static int s5k5ccgx_set_af_window(struct v4l2_subdev *sd) err |= s5k5ccgx_i2c_write_twobyte(client, 0x002A, 0x023C); err |= s5k5ccgx_i2c_write_twobyte(client, 0x0F12, 0x0001); - debug_msleep(sd, 60); + do_gettimeofday(&state->focus.win_stable.before_time); mutex_unlock(&state->af_lock); CHECK_ERR(err); - cam_dbg("%s: AF window position completed.\n", __func__); + cam_info("AF window position completed.\n"); cam_trace("X\n"); return 0; @@ -1842,17 +1870,15 @@ static int s5k5ccgx_set_touch_af(struct v4l2_subdev *sd, s32 val) if (val) { if (mutex_is_locked(&state->af_lock)) { - cam_warn("%s: WARNING, AF is busy\n", __func__); + cam_warn("%s: AF is still operating!\n", __func__); return 0; } err = queue_work(state->workqueue, &state->af_win_work); if (likely(!err)) cam_warn("WARNING, AF window is still processing\n"); - } else { - err = s5k5ccgx_stop_af(sd); - CHECK_ERR_MSG(err, "val=%d\n", 0) - } + } else + cam_info("set_touch_af: invalid value %d\n", val); cam_trace("X\n"); return 0; @@ -2005,7 +2031,7 @@ static void s5k5ccgx_set_framesize(struct v4l2_subdev *sd, static int s5k5ccgx_wait_steamoff(struct v4l2_subdev *sd) { struct s5k5ccgx_state *state = to_state(sd); - struct s5k5ccgx_stream_time *stream_time = &state->stream_time; + struct s5k5ccgx_interval *stream_time = &state->stream_time; s32 elapsed_msec = 0; cam_trace("E\n"); @@ -2204,6 +2230,8 @@ static inline void s5k5ccgx_get_exif_flash(struct v4l2_subdev *sd, { struct s5k5ccgx_state *state = to_state(sd); + *flash = 0; + switch (state->flash_mode) { case FLASH_MODE_OFF: *flash |= EXIF_FLASH_MODE_SUPPRESSION; @@ -2247,7 +2275,6 @@ static int s5k5ccgx_get_exif(struct v4l2_subdev *sd) s5k5ccgx_get_exif_iso(sd, &state->exif.iso); /* flash */ - state->exif.flash = 0; s5k5ccgx_get_exif_flash(sd, &state->exif.flash); cam_dbg("EXIF: ex_time_den=%d, iso=%d, flash=0x%02X\n", |