aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/s5k5ccgx.c
diff options
context:
space:
mode:
authorcodeworkx <codeworkx@cyanogenmod.com>2012-09-17 17:53:57 +0200
committercodeworkx <codeworkx@cyanogenmod.com>2012-09-18 16:31:59 +0200
commitc28265764ec6ad9995eb0c761a376ffc9f141fcd (patch)
tree3ad899757480d47deb2be6011509a4243e8e0dc2 /drivers/media/video/s5k5ccgx.c
parent0ddbcb39c0dc0318f68d858f25a96a074142af2f (diff)
downloadkernel_samsung_smdk4412-c28265764ec6ad9995eb0c761a376ffc9f141fcd.zip
kernel_samsung_smdk4412-c28265764ec6ad9995eb0c761a376ffc9f141fcd.tar.gz
kernel_samsung_smdk4412-c28265764ec6ad9995eb0c761a376ffc9f141fcd.tar.bz2
applied patches from i9305 jb sources, updated mali to r3p0
Change-Id: Iec4bc4e2fb59e2cf5b4d25568a644d4e3719565e
Diffstat (limited to 'drivers/media/video/s5k5ccgx.c')
-rw-r--r--drivers/media/video/s5k5ccgx.c143
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",