diff options
Diffstat (limited to 'drivers/media/video/isx012.c')
-rw-r--r-- | drivers/media/video/isx012.c | 1021 |
1 files changed, 685 insertions, 336 deletions
diff --git a/drivers/media/video/isx012.c b/drivers/media/video/isx012.c index ff2cbb0..8223d58 100644 --- a/drivers/media/video/isx012.c +++ b/drivers/media/video/isx012.c @@ -12,7 +12,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * - change date: 2012.04.25 + * - change date: 2012.06.28 */ #include "isx012.h" #include <linux/gpio.h> @@ -23,9 +23,15 @@ #define isx012_writeb(sd, addr, data) isx012_i2c_write(sd, addr, data, 1) #define isx012_writew(sd, addr, data) isx012_i2c_write(sd, addr, data, 2) #define isx012_writel(sd, addr, data) isx012_i2c_write(sd, addr, data, 4) +#define isx012_wait_ae_stable_af(sd) isx012_wait_ae_stable(sd, true, false) +#define isx012_wait_ae_stable_preview(sd) isx012_wait_ae_stable(sd, false, true) +#define isx012_wait_ae_stable_cap(sd) isx012_wait_ae_stable(sd, false, false) + +static int dbg_level; static const struct isx012_fps isx012_framerates[] = { { I_FPS_0, FRAME_RATE_AUTO }, + { I_FPS_7, FRAME_RATE_7}, { I_FPS_15, FRAME_RATE_15 }, { I_FPS_25, FRAME_RATE_25 }, { I_FPS_30, FRAME_RATE_30 }, @@ -48,6 +54,7 @@ static const struct isx012_framesize isx012_preview_frmsizes[] = { static const struct isx012_framesize isx012_capture_frmsizes[] = { { CAPTURE_SZ_VGA, 640, 480 }, + { CAPTURE_SZ_960_720, 960, 720 }, { CAPTURE_SZ_W1MP, 1536, 864 }, { CAPTURE_SZ_2MP, 1600, 1200 }, { CAPTURE_SZ_W2MP, 2048, 1152 }, @@ -112,6 +119,9 @@ static const struct isx012_regs reg_datas = { ISX012_REGSET(IMAGE_EFFECT_SEPIA, isx012_Effect_Sepia), ISX012_REGSET(IMAGE_EFFECT_NEGATIVE, ISX012_Effect_Negative), + ISX012_REGSET(IMAGE_EFFECT_SOLARIZE, isx012_Effect_Solar), + ISX012_REGSET(IMAGE_EFFECT_SKETCH, isx012_Effect_Sketch), + ISX012_REGSET(IMAGE_EFFECT_POINT_COLOR_3, isx012_Effect_Pastel), }, .white_balance = { ISX012_REGSET(WHITE_BALANCE_AUTO, isx012_WB_Auto), @@ -162,14 +172,13 @@ static const struct isx012_regs reg_datas = { ISX012_REGSET(SHARPNESS_PLUS_1, isx012_Sharpness_Plus_1), ISX012_REGSET(SHARPNESS_PLUS_2, isx012_Sharpness_Plus_2), }, - .fps = { ISX012_REGSET(I_FPS_0, isx012_fps_auto), + ISX012_REGSET(I_FPS_7, isx012_fps_7fix), ISX012_REGSET(I_FPS_15, isx012_fps_15fix), ISX012_REGSET(I_FPS_25, isx012_fps_25fix), ISX012_REGSET(I_FPS_30, isx012_fps_30fix), }, - .preview_size = { ISX012_REGSET(PREVIEW_SZ_320x240, isx012_320_Preview), ISX012_REGSET(PREVIEW_SZ_VGA, isx012_640_Preview), @@ -179,21 +188,10 @@ static const struct isx012_regs reg_datas = { }, .capture_size = { ISX012_REGSET(CAPTURE_SZ_VGA, isx012_VGA_Capture), + ISX012_REGSET(CAPTURE_SZ_960_720, isx012_960_720_Capture), ISX012_REGSET(CAPTURE_SZ_3MP, isx012_3M_Capture), ISX012_REGSET(CAPTURE_SZ_5MP, isx012_5M_Capture), }, -#if 0 /* DSLIM: Should be implemented */ - .preview_return = ISX012_REGSET_TABLE(s5k5ccgx_preview_return), - - .ae_lock_on = - ISX012_REGSET_TABLE(s5k5ccgx_ae_lock), - .ae_lock_off = - ISX012_REGSET_TABLE(s5k5ccgx_ae_unlock), - .awb_lock_on = - ISX012_REGSET_TABLE(s5k5ccgx_awb_lock), - .awb_lock_off = - ISX012_REGSET_TABLE(s5k5ccgx_awb_unlock), -#endif /* AF */ .af_window_reset = ISX012_REGSET_TABLE(ISX012_AF_Window_Reset), @@ -211,11 +209,11 @@ static const struct isx012_regs reg_datas = { .flash_ae_line = ISX012_REGSET_TABLE(ISX012_Flash_AELINE), .flash_on = ISX012_REGSET_TABLE(ISX012_Flash_ON), .flash_off = ISX012_REGSET_TABLE(ISX012_Flash_OFF), + .ae_manual = ISX012_REGSET_TABLE(ISX012_ae_manual_mode), + .flash_fast_ae_awb = ISX012_REGSET_TABLE(ISX012_flash_fast_ae_awb), .init_reg = ISX012_REGSET_TABLE(ISX012_Init_Reg), -#if 0 /* DSLIM: Should be implemented */ - .get_esd_status = ISX012_REGSET_TABLE(s5k5ccgx_get_esd_reg), -#endif + /* Camera mode */ .preview_mode = ISX012_REGSET_TABLE(ISX012_Preview_Mode), .capture_mode = ISX012_REGSET_TABLE(ISX012_Capture_Mode), @@ -252,13 +250,16 @@ static void msleep_debug(u32 msecs, bool dbg_on) { u32 delta_halfrange; /* in us unit */ + if (unlikely(!msecs)) + return; + if (dbg_on) cam_dbg("delay for %dms\n", msecs); - if (msecs <= 5) + if (msecs <= 7) delta_halfrange = 100; else - delta_halfrange = 500; + delta_halfrange = 300; if (msecs <= 20) usleep_range((msecs * 1000 - delta_halfrange), @@ -358,7 +359,15 @@ static int isx012_define_table(void) printk(KERN_DEBUG "isx012_define_table start!\n"); start = strstr(isx012_regs_table, "aeoffset_table"); + if (!start) { + cam_err("%s: can not find %s", __func__, "aeoffset_table"); + return -ENOENT; + } end = strstr(start, "};"); + if (!end) { + cam_err("%s: can not find %s end", __func__, "aeoffset_table"); + return -ENOENT; + } /* Find table */ index_2 = 0; @@ -440,7 +449,15 @@ static int isx012_define_read(char *name, int len_size) //printk(KERN_DEBUG "isx012_define_read start!\n"); start = strstr(isx012_regs_table, name); + if (!start) { + cam_err("%s: can not find %s", __func__, name); + return -ENOENT; + } end = strstr(start, "tuning"); + if (!end) { + cam_err("%s: can not find %s", __func__, "tuning"); + return -ENOENT; + } reg = strstr(start," "); @@ -690,7 +707,7 @@ static int isx012_i2c_read(struct v4l2_subdev *sd, struct i2c_client *client = v4l2_get_subdevdata(sd); u8 buf[16] = {0,}; struct i2c_msg msg[2]; - int err, retry = 3; + int err, retry = 5; if (unlikely(!client->adapter)) { @@ -724,7 +741,7 @@ static int isx012_i2c_read(struct v4l2_subdev *sd, msleep_debug(POLL_TIME_MS, false); } while (retry-- > 0); - CHECK_ERR_COND_MSG(err != 2, -EIO, "I2C does not working\n"); + CHECK_ERR_COND_MSG(err != 2, -EIO, "I2C does not work\n"); #ifdef CONFIG_CAM_I2C_LITTLE_ENDIAN if (len == 1) @@ -819,7 +836,7 @@ static int isx012_i2c_write(struct v4l2_subdev *sd, msleep_debug(POLL_TIME_MS, false); } while (retry_count-- > 0); - CHECK_ERR_COND_MSG(err != 1, -EIO, "I2C does not working\n"); + CHECK_ERR_COND_MSG(err != 1, -EIO, "I2C does not work\n"); return 0; } @@ -975,8 +992,7 @@ static int isx012_is_om_changed(struct v4l2_subdev *sd) for (cnt1 = 0; cnt1 < ISX012_CNT_OM_CHECK; cnt1++) { err = isx012_readb(sd, REG_INTSTS, &val); - if (unlikely(err)) - cam_err("om changed: error, readb cnt=%d\n", cnt1); + CHECK_ERR_MSG(err, "om changed: error, readb cnt=%d\n", cnt1); if ((val & REG_INTBIT_OM) == REG_INTBIT_OM) { status &= ~0x01; @@ -988,8 +1004,7 @@ static int isx012_is_om_changed(struct v4l2_subdev *sd) for (cnt2 = 0; cnt2 < ISX012_CNT_OM_CHECK; cnt2++) { err = isx012_writeb(sd, REG_INTCLR, REG_INTBIT_OM); err |= isx012_readb(sd, REG_INTSTS, &val); - if (unlikely(err)) - cam_err("om changed: error, rw cnt=%d\n", cnt2); + CHECK_ERR_MSG(err, "om changed: clear error, rw\n"); if ((val & REG_INTBIT_OM) == 0) { status &= ~0x02; @@ -998,13 +1013,13 @@ static int isx012_is_om_changed(struct v4l2_subdev *sd) msleep_debug(5, false); } - cam_dbg("om changed: sucess. int cnt=%d, clr cnt=%d\n", cnt1, cnt2); - if (unlikely(status)) { cam_err("om changed: error, fail 0x%X\n", status); return -EAGAIN; } + cam_dbg("om changed: int cnt=%d, clr cnt=%d\n", cnt1, cnt2); + return 0; } @@ -1032,8 +1047,9 @@ static int isx012_is_cm_changed(struct v4l2_subdev *sd) for (cnt2 = 0; cnt2 < ISX012_CNT_CM_CHECK; cnt2++) { err = isx012_writeb(sd, REG_INTCLR, REG_INTBIT_CM); - CHECK_ERR_MSG(err, "cm changed: error, writeb\n"); - isx012_readb(sd, REG_INTSTS, &val); + err |= isx012_readb(sd, REG_INTSTS, &val); + CHECK_ERR_MSG(err, "cm changed: clear error, rw\n"); + if ((val & REG_INTBIT_CM) == 0) { status &= ~0x02; break; @@ -1042,24 +1058,27 @@ static int isx012_is_cm_changed(struct v4l2_subdev *sd) msleep_debug(5, false); } - cam_dbg("cm changed: int cnt=%d, clr cnt=%d\n", cnt1, cnt2); - if (unlikely(status)) { cam_err("cm changed: error, fail 0x%X\n", status); return -EAGAIN; } + cam_dbg("cm changed: int cnt=%d, clr cnt=%d\n", cnt1, cnt2); + return 0; } static inline int isx012_transit_preview_mode(struct v4l2_subdev *sd) { struct isx012_state *state = to_state(sd); - int err = -EIO; - err = isx012_set_from_table(sd, "preview_mode", + isx012_restore_sensor_flash(sd); + + if (state->exposure.ae_lock || state->wb.awb_lock) + cam_info("Restore user ae(awb)-lock...\n"); + + return isx012_set_from_table(sd, "preview_mode", &state->regs->preview_mode, 1, 0); - return err; } /** @@ -1078,11 +1097,11 @@ static inline int isx012_transit_half_mode(struct v4l2_subdev *sd) if (state->scene_mode == SCENE_MODE_NIGHTSHOT && state->light_level >= LUX_LEVEL_LOW) { cam_info("half_mode: night lowlux\n"); - state->lowlux_night = 1; + state->capture.lowlux_night = 1; err = isx012_set_from_table(sd, "night_halfrelease_mode", &state->regs->halfrelease_mode_night, 1, 0); } else { - state->lowlux_night = 0; + state->capture.lowlux_night = 0; err = isx012_set_from_table(sd, "halfrelease", &state->regs->halfrelease_mode, 1, 0); } @@ -1096,11 +1115,8 @@ static inline int isx012_transit_capture_mode(struct v4l2_subdev *sd) struct isx012_state *state = to_state(sd); int err = -EIO; - if (state->lowlux_night) { + if (state->capture.lowlux_night) { cam_info("capture_mode: night lowlux\n"); -#if !defined(CONFIG_NEW_STREAM_DELAY) - state->lowlux_night = 0; -#endif err = isx012_set_from_table(sd, "capture_mode_night", &state->regs->capture_mode_night, 1, 0); } else @@ -1260,7 +1276,7 @@ static void isx012_frame_checker(struct work_struct *work) if (((u8)val & ISX012_INTSRC_VINT) == ISX012_INTSRC_VINT) { ++int_cnt; - cam_info("frame INT %d (cnt=%d)\n", int_cnt, cnt); + cam_info("frame_INT %d (cnt=%d)\n", int_cnt, cnt); if (int_cnt >= 2) { state->frame_check = false; return; @@ -1279,7 +1295,7 @@ static void isx012_frame_checker(struct work_struct *work) return; } - msleep_debug(10, false); + msleep_debug(3, false); } cam_err("frame INT Not occured!\n"); @@ -1330,7 +1346,7 @@ static void isx012_stop_frame_checker(struct v4l2_subdev *sd) /** * isx012_is_hwflash_on - check whether flash device is on * - * Refer to state->flash_on to check whether flash is in use in driver. + * Refer to state->flash.on to check whether flash is in use in driver. */ static inline int isx012_is_hwflash_on(struct v4l2_subdev *sd) { @@ -1352,7 +1368,7 @@ static int isx012_flash_en(struct v4l2_subdev *sd, s32 mode, s32 onoff) { struct isx012_state *state = to_state(sd); - if (unlikely(state->ignore_flash)) { + if (unlikely(state->flash.ignore_flash)) { cam_warn("WARNING, we ignore flash command.\n"); return 0; } @@ -1368,7 +1384,7 @@ static int isx012_flash_en(struct v4l2_subdev *sd, s32 mode, s32 onoff) * isx012_flash_torch - turn flash on/off as torch for preflash, recording * @onoff: ISX012_FLASH_ON or ISX012_FLASH_OFF * - * This func set state->flash_on properly. + * This func set state->flash.on properly. */ static inline int isx012_flash_torch(struct v4l2_subdev *sd, s32 onoff) { @@ -1376,7 +1392,7 @@ static inline int isx012_flash_torch(struct v4l2_subdev *sd, s32 onoff) int err = 0; err = isx012_flash_en(sd, ISX012_FLASH_MODE_MOVIE, onoff); - state->flash_on = (onoff == ISX012_FLASH_ON) ? 1 : 0; + state->flash.on = (onoff == ISX012_FLASH_ON) ? 1 : 0; return err; } @@ -1393,9 +1409,7 @@ static inline int isx012_flash_oneshot(struct v4l2_subdev *sd, s32 onoff) int err = 0; err = isx012_flash_en(sd, ISX012_FLASH_MODE_NORMAL, onoff); - - /* The flash_on here is only used for EXIF */ - state->flash_on = (onoff == ISX012_FLASH_ON) ? 1 : 0; + state->flash.on = (onoff == ISX012_FLASH_ON) ? 1 : 0; return err; } @@ -1441,7 +1455,8 @@ static void isx012_set_framesize(struct v4l2_subdev *sd, cam_dbg("%s: Requested Res %dx%d\n", __func__, width, height); - found_frmsize = (preview ? &state->preview : &state->capture); + found_frmsize = preview ? + &state->preview.frmsize : &state->capture.frmsize; for (i = 0; i < num_frmsize; i++) { if ((frmsizes[i].width == width) && @@ -1538,9 +1553,19 @@ static int isx012_set_exposure(struct v4l2_subdev *sd, s32 val) static inline u32 isx012_get_light_level(struct v4l2_subdev *sd, u32 *light_level) { - isx012_readb(sd, REG_USER_GAINLEVEL_NOW, light_level); + struct isx012_state *state = to_state(sd); + u32 val_lsb = 0, val_msb = 0; + + if (state->iso == ISO_AUTO) + isx012_readb(sd, REG_USER_GAINLEVEL_NOW, light_level); + else { + isx012_readw(sd, REG_SHT_TIME_OUT_L, &val_lsb); + isx012_readw(sd, REG_SHT_TIME_OUT_H, &val_msb); + + *light_level = (val_msb << 16) | (val_lsb & 0xFFFF); + } - cam_trace("X, light level = 0x%X", *light_level); + cam_trace("X, iso = %d, light level = 0x%X", state->iso, *light_level); return 0; } @@ -1549,19 +1574,23 @@ static inline u32 isx012_get_light_level(struct v4l2_subdev *sd, static int isx012_set_capture_size(struct v4l2_subdev *sd) { struct isx012_state *state = to_state(sd); + u32 width, height; - if (unlikely(!state->capture)) { + if (unlikely(!state->capture.frmsize)) { cam_warn("warning, capture resolution not set\n"); - state->capture = isx012_get_framesize(isx012_capture_frmsizes, + state->capture.frmsize = isx012_get_framesize( + isx012_capture_frmsizes, ARRAY_SIZE(isx012_capture_frmsizes), - CAPTURE_SZ_3MP); + CAPTURE_SZ_5MP); } - cam_dbg("set capture size(%dx%d)\n", - state->capture->width, state->capture->height); + width = state->capture.frmsize->width; + height = state->capture.frmsize->height; + + cam_dbg("set capture size(%dx%d)\n", width, height); - isx012_writew(sd, REG_HSIZE_CAP, state->capture->width); - isx012_writew(sd, REG_VSIZE_CAP, state->capture->height); + isx012_writew(sd, REG_HSIZE_CAP, width); + isx012_writew(sd, REG_VSIZE_CAP, height); return 0; } @@ -1571,7 +1600,7 @@ static int isx012_set_sensor_mode(struct v4l2_subdev *sd, s32 val) { struct isx012_state *state = to_state(sd); - cam_trace("mode=%d\n", val); /*DSLIM*/ + cam_trace("mode=%d\n", val); switch (val) { case SENSOR_MOVIE: @@ -1640,6 +1669,7 @@ static int isx012_set_ae_lock(struct v4l2_subdev *sd, s32 lock, bool force) isx012_readb(sd, REG_CPUEXT, &val); val |= REG_CPUEXT_AE_HOLD; isx012_writeb(sd, REG_CPUEXT, val); + state->exposure.ae_lock = 1; cam_info("AE lock by user\n"); break; @@ -1651,8 +1681,9 @@ static int isx012_set_ae_lock(struct v4l2_subdev *sd, s32 lock, bool force) isx012_readb(sd, REG_CPUEXT, &val); val &= ~REG_CPUEXT_AE_HOLD; isx012_writeb(sd, REG_CPUEXT, val); + state->exposure.ae_lock = 0; - cam_info("AE unlock by user\n"); + cam_info("AE unlock\n"); break; default: @@ -1675,6 +1706,7 @@ static int isx012_set_awb_lock(struct v4l2_subdev *sd, s32 lock, bool force) isx012_readb(sd, REG_CPUEXT, &val); val |= REG_CPUEXT_AWB_HOLD; isx012_writeb(sd, REG_CPUEXT, val); + state->wb.awb_lock = 1; cam_info("AWB lock by user\n"); break; @@ -1686,8 +1718,9 @@ static int isx012_set_awb_lock(struct v4l2_subdev *sd, s32 lock, bool force) isx012_readb(sd, REG_CPUEXT, &val); val &= ~REG_CPUEXT_AWB_HOLD; isx012_writeb(sd, REG_CPUEXT, val); + state->wb.awb_lock = 0; - cam_info("AWB unlock by user\n"); + cam_info("AWB unlock\n"); break; default: @@ -1776,8 +1809,8 @@ static int isx012_pre_sensor_flash(struct v4l2_subdev *sd) /* read preview AE scale */ isx012_readw(sd, REG_USER_AESCL_AUTO, - &state->exposure.ae_offset.ae_auto); - isx012_readw(sd, REG_ERRSCL_AUTO, &state->exposure.ae_offset.ersc_auto); + &state->flash.ae_offset.ae_auto); + isx012_readw(sd, REG_ERRSCL_AUTO, &state->flash.ae_offset.ersc_auto); if (state->wb.mode == WHITE_BALANCE_AUTO) isx012_writeb(sd, REG_AWB_SN1, 0x00); @@ -1808,28 +1841,45 @@ static int isx012_post_sensor_flash(struct v4l2_subdev *sd) isx012_writeb(sd, REG_VPARA_TRG, 0x01); + state->flash.ae_flash_lock = 0; + state->capture.ae_manual_mode = 0; + return 0; } +static inline int isx012_restore_sensor_flash(struct v4l2_subdev *sd) +{ + struct isx012_state *state = to_state(sd); + + if (!state->flash.ae_flash_lock) + return 0; + + cam_info("Flash is locked. Unlocking...\n"); + return isx012_post_sensor_flash(sd); +} + static int isx012_set_ae_gainoffset(struct v4l2_subdev *sd) { struct isx012_state *state = to_state(sd); - s16 ae_diff, ae_offset; + s16 ae_diff, ae_offset = 0; u16 ae_auto, ae_now; s16 ersc_auto, ersc_now; + u16 ae_ofsetval, ae_maxdiff; - ae_auto = (u16)state->exposure.ae_offset.ae_auto; - ae_now = (u16)state->exposure.ae_offset.ae_now; - ersc_auto = (u16)state->exposure.ae_offset.ersc_auto; - ersc_now = (u16)state->exposure.ae_offset.ersc_now; + ae_auto = (u16)state->flash.ae_offset.ae_auto; + ae_now = (u16)state->flash.ae_offset.ae_now; + ersc_auto = (u16)state->flash.ae_offset.ersc_auto; + ersc_now = (u16)state->flash.ae_offset.ersc_now; + ae_ofsetval = (u16)state->flash.ae_offset.ae_ofsetval; + ae_maxdiff = (u16)state->flash.ae_offset.ae_maxdiff; ae_diff = (ae_now + ersc_now) - (ae_auto + ersc_auto); if (ae_diff < 0) ae_diff = 0; if (ersc_now < 0) { - if (ae_diff >= AE_MAXDIFF) - ae_offset = -AE_OFSETVAL - ersc_now; + if (ae_diff >= ae_maxdiff) + ae_offset = -ae_ofsetval - ersc_now; else { #ifdef CONFIG_LOAD_FILE ae_offset = -gtable_buf[ae_diff / 10] - ersc_now; @@ -1838,21 +1888,100 @@ static int isx012_set_ae_gainoffset(struct v4l2_subdev *sd) #endif } } else { - if (ae_diff >= AE_MAXDIFF) - ae_offset = -AE_OFSETVAL; + if (ae_diff >= ae_maxdiff) + ae_offset = -ae_ofsetval; else { #ifdef CONFIG_LOAD_FILE - ae_offset = -gtable_buf[ae_offset / 10]; + ae_offset = -gtable_buf[ae_diff / 10]; #else - ae_offset = -aeoffset_table[ae_offset / 10]; + ae_offset = -aeoffset_table[ae_diff / 10]; #endif } } + /* cam_info("[ae_gainoffset] ae_offset(%d), ae_diff(%d):" + " (ae_now(%d) + ersc_now(%d)) - (ae_auto(%d) + ersc_auto(%d))", + ae_offset, ae_diff, ae_now, ersc_now, ae_auto, ersc_auto); */ isx012_writew(sd, REG_CAP_GAINOFFSET, ae_offset); return 0; } +static int isx012_wait_ae_stable(struct v4l2_subdev *sd, + bool af_doing, bool long_wait) +{ + struct isx012_state *state = to_state(sd); + u32 val = 0, mode = 0; + int count; + int max_1st, max_2nd; + + if (af_doing || long_wait) + max_1st = max_2nd = ISX012_CNT_AE_STABLE; + else { + max_1st = 20; /* 200ms + alpha */ + max_2nd = 70; /* 700ms + alpha */ + } + + /* 1st: go to Half mode */ + for (count = 0; count < max_1st; count++) { + if (af_doing && (state->focus.start == AUTO_FOCUS_OFF)) + goto cancel_out; + + isx012_readb(sd, REG_MODESEL_FIX, &mode); + if ((u8)mode == 0x01) + break; + + msleep_debug(10, false); + } + + if (count >= max_1st) + cam_info("check_ae_stable: fail to check modesel_fix\n\n"); + else + cam_dbg("check_ae_stable: 1st check count=%d\n", count); + + /* 2nd: check move_sts */ + for (count = 0; count < max_2nd; count++) { + if (af_doing && (state->focus.start == AUTO_FOCUS_OFF)) + goto cancel_out; + + isx012_readb(sd, REG_HALF_MOVE_STS, &val); + if ((u8)val == 0x00) + break; + + msleep_debug(10, false); + } + + if (count >= max_2nd) + cam_info("check_ae_stable: fail to check half_move_sts\n\n"); + else + cam_dbg("check_ae_stable: 2nd check count=%d\n", count); + + return 0; + +cancel_out: + cam_info("check_ae_stable: AF is cancelled(%s)\n", + mode == 0x01 ? "1st" : "2nd"); + return 1; +} + +static bool isx012_check_flash_fire(struct v4l2_subdev *sd, u32 light_level) +{ + struct isx012_state *state = to_state(sd); + + if (state->iso == ISO_AUTO) { + if (light_level < state->lux_level_flash) + goto flash_off; + } else if (light_level < state->shutter_level_flash) + goto flash_off; + + /* Flash on */ + return true; + +flash_off: + isx012_restore_sensor_flash(sd); + + return false; +} + static int isx012_cancel_af(struct v4l2_subdev *sd, bool flash) { struct isx012_state *state = to_state(sd); @@ -1867,17 +1996,14 @@ static int isx012_cancel_af(struct v4l2_subdev *sd, bool flash) if (flash) isx012_post_sensor_flash(sd); - isx012_return_focus(sd); - return 0; } /* PX: Prepare AF Flash */ -static int isx012_af_start_preflash(struct v4l2_subdev *sd, u32 touch) +static int isx012_af_start_preflash(struct v4l2_subdev *sd, + u32 touch, u32 flash_mode) { struct isx012_state *state = to_state(sd); - u32 val = 0; - int count; bool flash = false; cam_trace("E\n"); @@ -1885,16 +2011,18 @@ static int isx012_af_start_preflash(struct v4l2_subdev *sd, u32 touch) if (state->sensor_mode == SENSOR_MOVIE) return 0; - cam_dbg("Start SINGLE AF, flash mode %d\n", state->flash_mode); + cam_dbg("Start SINGLE AF, touch %d, flash mode %d\n", + touch, flash_mode); - state->focus.preflash = PREFLASH_OFF; + state->flash.preflash = PREFLASH_OFF; state->light_level = LUX_LEVEL_MAX; /* We unlock AE, AWB if not going to capture mode after AF * for market app. */ if (state->focus.lock) { + cam_warn("Focus is locked. Unlocking...\n"); isx012_writeb(sd, REG_MODESEL, 0x0); - msleep_debug(200, true); + msleep_debug(200, false); state->focus.lock = 0; } @@ -1904,77 +2032,32 @@ static int isx012_af_start_preflash(struct v4l2_subdev *sd, u32 touch) isx012_get_light_level(sd, &state->light_level); - switch (state->flash_mode) { + switch (flash_mode) { case FLASH_MODE_AUTO: - if (state->light_level < state->lux_level_flash) { - /* flash not needed */ + if (!isx012_check_flash_fire(sd, state->light_level)) break; - } case FLASH_MODE_ON: flash = true; - state->focus.preflash = PREFLASH_ON; + state->flash.preflash = PREFLASH_ON; isx012_pre_sensor_flash(sd); isx012_flash_torch(sd, ISX012_FLASH_ON); break; case FLASH_MODE_OFF: - break; - default: + isx012_restore_sensor_flash(sd); break; } - /* Check AE-stable */ - if (flash) { - for (count = 0; count < ISX012_CNT_AE_STABLE; count++) { - if (state->focus.start == AUTO_FOCUS_OFF) { - cam_info("af_start_preflash: " - "AF is cancelled!\n"); - state->focus.status = AF_RESULT_CANCELLED; - goto cancel_out; - } - - isx012_readb(sd, REG_MODESEL_FIX, &val); - if ((u8)val == 0x01) - break; - - msleep_debug(10, false); - } - if (count >= ISX012_CNT_AE_STABLE) - cam_info("start preflash: fail to check modesel_fix\n\n\n"); - else - cam_dbg("start preflash: 1st check count=%d\n", count); - - for (count = 0; count < ISX012_CNT_AE_STABLE; count++) { - if (state->focus.start == AUTO_FOCUS_OFF) { - cam_info("af_start_preflash: " - "AF is cancelled!\n"); - state->focus.status = AF_RESULT_CANCELLED; - goto cancel_out; - } - - isx012_readb(sd, REG_HALF_MOVE_STS, &val); - if ((u8)val == 0x00) - break; - - msleep_debug(10, false); - } - if (count >= ISX012_CNT_AE_STABLE) - cam_info("start preflash: fail to check half_move_sts\n\n\n"); - else - cam_dbg("start preflash: 2nd check count=%d\n", count); - } - -cancel_out: - /* If AF cancel, finish pre-flash process. */ - if (state->focus.status == AF_RESULT_CANCELLED) { - if (flash) { - isx012_flash_torch(sd, ISX012_FLASH_OFF); - state->focus.preflash = PREFLASH_NONE; - } + if (flash && isx012_wait_ae_stable_af(sd)) { + /* Cancel AF */ + state->focus.status = AF_RESULT_CANCELLED; + isx012_flash_torch(sd, ISX012_FLASH_OFF); + state->flash.preflash = PREFLASH_NONE; isx012_cancel_af(sd, flash); + isx012_return_focus(sd); } cam_trace("X\n"); @@ -1984,22 +2067,22 @@ cancel_out: static int isx012_do_af(struct v4l2_subdev *sd, u32 touch) { struct isx012_state *state = to_state(sd); - u32 read_value = 0, ae_scl = 0; + u32 read_value = 0; u32 count = 0; - bool flash = false; + bool flash = false, success = false; cam_trace("E\n"); /* We do not go to half-release mode if setting FLASH_ON. * And note that flash variable should only be set to true * in camera mode. */ - if (state->focus.preflash == PREFLASH_ON) + if (state->flash.preflash == PREFLASH_ON) flash = true; if (state->sensor_mode == SENSOR_MOVIE) { isx012_set_from_table(sd, "af_camcorder_start", &state->regs->af_camcorder_start, 1, 0); - } else + } else if (!flash) isx012_transit_half_mode(sd); /* Check the result of AF */ @@ -2021,26 +2104,23 @@ static int isx012_do_af(struct v4l2_subdev *sd, u32 touch) if (unlikely(count >= AF_SEARCH_COUNT)) { cam_warn("warning, AF check failed. val=0x%X\n\n", read_value); isx012_writeb(sd, REG_INTCLR, 0x10); - state->focus.status = AF_RESULT_FAILED; goto check_fail; } isx012_writeb(sd, REG_INTCLR, 0x10); isx012_readb(sd, REG_AF_RESUNT, &read_value); if ((u8)read_value == 0x01) - state->focus.status = AF_RESULT_SUCCESS; - else { - state->focus.status = AF_RESULT_FAILED; + success = true; + else af_dbg("AF Fail. AF_RESULT reg=0x%X\n", (u8)read_value); - } check_fail: if (flash) { isx012_readw(sd, REG_ERRSCL_NOW, - &state->exposure.ae_offset.ersc_now); + &state->flash.ae_offset.ersc_now); isx012_readw(sd, REG_USER_AESCL_NOW, - &state->exposure.ae_offset.ae_now); - isx012_readw(sd, REG_AESCL, &ae_scl); + &state->flash.ae_offset.ae_now); + isx012_readw(sd, REG_AESCL, &state->flash.ae_scl); } if (touch) @@ -2050,38 +2130,46 @@ check_fail: isx012_set_from_table(sd, "af_saf_off", &state->regs->af_saf_off, 1, 0); - msleep_debug(66, true); /* Wait 1V time(66ms) */ + /* Remove the exising below 66ms delay: + * many delays have been added to _saf_off recently*/ + /* msleep_debug(66, true);*/ /* Wait 1V time(66ms) */ if (state->focus.start == AUTO_FOCUS_OFF) { - cam_dbg("do_af: AF is cancelled 02\n"); + cam_dbg("do_af: AF is cancelled\n"); state->focus.status = AF_RESULT_CANCELLED; goto cancel_out; } if (flash) { isx012_writew(sd, REG_MANOUTGAIN, - (u16)ae_scl - AE_SCL_SUBRACT_VALUE); + (u16)(state->flash.ae_scl - AE_SCL_SUBRACT_VALUE)); isx012_set_ae_gainoffset(sd); isx012_flash_torch(sd, ISX012_FLASH_OFF); - state->focus.ae_manual_mode = touch ? 1 : 0; + state->capture.ae_manual_mode = touch ? 1 : 0; } cancel_out: if (state->focus.status == AF_RESULT_CANCELLED) { - cam_dbg("Single AF cancelled.\n"); + cam_info("Single AF cancelled\n"); if (flash) { isx012_flash_torch(sd, ISX012_FLASH_OFF); - state->focus.preflash = PREFLASH_NONE; + state->flash.preflash = PREFLASH_NONE; } isx012_cancel_af(sd, flash); + isx012_return_focus(sd); } else { if (state->sensor_mode == SENSOR_MOVIE) isx012_return_focus(sd); state->focus.start = AUTO_FOCUS_OFF; - cam_dbg("Single AF finished(0x%X)\n", state->focus.status); + state->focus.status = success ? + AF_RESULT_SUCCESS : AF_RESULT_FAILED; + cam_info("Single AF finished(0x%X)\n", state->focus.status); + if (!touch) state->focus.lock = 1; /* fix me */ + if (flash) + state->flash.ae_flash_lock = 1; } return 0; @@ -2093,8 +2181,8 @@ static int isx012_set_af(struct v4l2_subdev *sd, s32 val) struct isx012_state *state = to_state(sd); int err = 0; - cam_info("%s: %s, focus mode %d\n", __func__, - val ? "start" : "stop", state->focus.mode); + cam_info("set_af: %s, focus %d, touch %d\n", + val ? "start" : "stop", state->focus.mode, state->focus.touch); if (unlikely((u32)val >= AUTO_FOCUS_MAX)) { cam_err("%s: error, invalid value(%d)\n", __func__, val); @@ -2121,11 +2209,41 @@ static int isx012_set_af(struct v4l2_subdev *sd, s32 val) return 0; } +static int isx012_start_af(struct v4l2_subdev *sd) +{ + struct isx012_state *state = to_state(sd); + int err = 0; + u32 touch, flash_mode; + + mutex_lock(&state->af_lock); + touch = state->focus.touch; + state->focus.touch = 0; + + flash_mode = state->flash.mode; + + if (state->sensor_mode == SENSOR_CAMERA) { + err = isx012_af_start_preflash(sd, touch, flash_mode); + if (unlikely(err)) + goto out; + + if (state->focus.status == AF_RESULT_CANCELLED) + goto out; + } + + isx012_do_af(sd, touch); + +out: + mutex_unlock(&state->af_lock); + + return 0; +} + /* PX: Stop AF */ static int isx012_stop_af(struct v4l2_subdev *sd, s32 touch) { struct isx012_state *state = to_state(sd); int err = 0; + bool flash; cam_trace("E\n"); /* mutex_lock(&state->af_lock); */ @@ -2133,18 +2251,17 @@ static int isx012_stop_af(struct v4l2_subdev *sd, s32 touch) switch (state->focus.status) { case AF_RESULT_FAILED: case AF_RESULT_SUCCESS: - cam_dbg("Stop AF, focus mode %d, AF result %d\n", + cam_info("Stop AF, focus mode %d, AF result %d\n", state->focus.mode, state->focus.status); - if (state->focus.mode == FOCUS_MODE_MACRO) - isx012_set_from_table(sd, "cancel_af_macro", - &state->regs->cancel_af_macro, 1, 0); - else - isx012_set_from_table(sd, "cancel_af_normal", - &state->regs->cancel_af_normal, 1, 0); + flash = ((state->flash.preflash == PREFLASH_ON) || + state->flash.ae_flash_lock) ? 1 : 0; + + isx012_cancel_af(sd, flash); state->focus.status = AF_RESULT_CANCELLED; - state->focus.preflash = PREFLASH_NONE; + state->flash.preflash = PREFLASH_NONE; + state->focus.lock = 0; break; case AF_RESULT_CANCELLED: @@ -2158,17 +2275,9 @@ static int isx012_stop_af(struct v4l2_subdev *sd, s32 touch) break; } -#if 0 - if (!touch) { - /* We move lens to default position if af is cancelled.*/ - err = isx012_return_focus(sd); - if (unlikely(err)) { - cam_err("%s: error, fail to af_norma_mode (%d)\n", - __func__, err); - goto err_out; - } - } -#endif + if (state->focus.touch) + state->focus.touch = 0; + /* mutex_unlock(&state->af_lock); */ cam_trace("X\n"); return 0; @@ -2182,28 +2291,8 @@ static void isx012_af_worker(struct work_struct *work) { struct isx012_state *state = container_of(work, \ struct isx012_state, af_work); - struct v4l2_subdev *sd = &state->sd; - int err = -EINVAL; - u32 touch; - mutex_lock(&state->af_lock); - touch = state->focus.touch; - - if (state->sensor_mode == SENSOR_CAMERA) { - err = isx012_af_start_preflash(sd, touch); - if (unlikely(err)) - goto out; - - if (state->focus.status == AF_RESULT_CANCELLED) - goto out; - } - - isx012_do_af(sd, touch); - -out: - state->focus.touch = 0; - mutex_unlock(&state->af_lock); - return; + isx012_start_af(&state->sd); } /* PX: Set focus mode */ @@ -2214,7 +2303,7 @@ static int isx012_set_focus_mode(struct v4l2_subdev *sd, s32 val) u32 cancel = 0; u8 focus_mode = (u8)val; - cam_dbg("%s val =%d(0x%X)\n", __func__, val, val); + cam_info("set_focus_mode %d(0x%X)\n", val, val); if (state->focus.mode == val) return 0; @@ -2274,9 +2363,9 @@ static int isx012_set_af_window(struct v4l2_subdev *sd) struct isx012_state *state = to_state(sd); const s32 mapped_x = state->focus.pos_x; const s32 mapped_y = state->focus.pos_y; - const u32 preview_width = state->preview->width; - const u32 preview_height = state->preview->height; - const u32 preview_ratio = FRM_RATIO(state->preview); + const u32 preview_width = state->preview.frmsize->width; + const u32 preview_height = state->preview.frmsize->height; + const u32 preview_ratio = FRM_RATIO(state->preview.frmsize); u32 start_x, start_y; u32 ratio_width, ratio_height; struct isx012_rect window = {0, 0, 0, 0}; @@ -2318,9 +2407,11 @@ static int isx012_set_af_window(struct v4l2_subdev *sd) isx012_writew(sd, 0x6A56, window.height); isx012_set_from_table(sd, "af_winddow_set", &state->regs->af_winddow_set, 1, 0); + + state->focus.touch = 1; mutex_unlock(&state->af_lock); - cam_dbg("AF window position completed.\n"); + cam_info("AF window position completed.\n"); cam_trace("X\n"); return 0; @@ -2331,10 +2422,8 @@ static int isx012_set_touch_af(struct v4l2_subdev *sd, s32 val) struct isx012_state *state = to_state(sd); int err = -EIO; - cam_trace("%s, x=%d y=%d\n", val ? "start" : "stop", - state->focus.pos_x, state->focus.pos_y); - - state->focus.touch = val; + cam_info("set_touch (%d, %d)\n", + state->focus.pos_x, state->focus.pos_y); if (val) { if (mutex_is_locked(&state->af_lock)) { @@ -2345,7 +2434,8 @@ static int isx012_set_touch_af(struct v4l2_subdev *sd, s32 val) err = queue_work(state->workqueue, &state->af_win_work); if (likely(!err)) cam_warn("WARNING, AF window is still processing\n"); - } + } else + cam_err("%s: invalid val(%d)\n", __func__, val); cam_trace("X\n"); return 0; @@ -2425,54 +2515,113 @@ static int isx012_init_regs(struct v4l2_subdev *sd) } #endif -static int isx012_wait_steamoff(struct v4l2_subdev *sd) +static inline int isx012_do_wait_steamoff(struct v4l2_subdev *sd) { struct isx012_state *state = to_state(sd); struct isx012_stream_time *stream_time = &state->stream_time; s32 elapsed_msec = 0; + u32 val = 0; + int err = 0, count; cam_trace("E\n"); - if (unlikely(!(state->pdata->is_mipi & state->need_wait_streamoff))) - return 0; - do_gettimeofday(&stream_time->curr_time); elapsed_msec = GET_ELAPSED_TIME(stream_time->curr_time, \ stream_time->before_time) / 1000; - if (state->pdata->streamoff_delay > elapsed_msec) { - cam_info("stream-off: %dms + %dms\n", elapsed_msec, - state->pdata->streamoff_delay - elapsed_msec); - msleep_debug(state->pdata->streamoff_delay - elapsed_msec, - true); - } else - cam_info("stream-off: %dms\n", elapsed_msec); + for (count = 0; count < ISX012_CNT_STREAMOFF; count++) { + err = isx012_readb(sd, 0x00DC, &val); + CHECK_ERR_MSG(err, "wait_steamoff: error, readb\n") + + if ((val & 0x04) == 0) { + cam_dbg("wait_steamoff: %dms + cnt(%d)\n", + elapsed_msec, count); + break; + } + + /* cam_info("wait_steamoff: val = 0x%X\n", val);*/ + msleep_debug(2, false); + } + + if (unlikely(count >= ISX012_CNT_STREAMOFF)) + cam_info("wait_steamoff: time-out!\n\n"); state->need_wait_streamoff = 0; return 0; } -static int isx012_control_stream(struct v4l2_subdev *sd, u32 cmd) +static inline int isx012_fast_capture_switch(struct v4l2_subdev *sd) +{ + u32 val = 0; + int err = 0, count; + + cam_trace("EX\n"); + + for (count = 0; count < ISX012_CNT_STREAMOFF; count++) { + err = isx012_readb(sd, 0x00DC, &val); + CHECK_ERR_MSG(err, "fast_capture_switch: error, readb\n") + + if ((val & 0x03) == 0x02) { + cam_dbg("fast_capture_switch: cnt(%d)\n", count); + break; + } + + /* cam_info("wait_steamoff: val = 0x%X\n", val);*/ + msleep_debug(2, false); + } + + if (unlikely(count >= ISX012_CNT_STREAMOFF)) + cam_info("fast_capture_switch: time-out!\n\n"); + + return 0; +} + +static int isx012_wait_steamoff(struct v4l2_subdev *sd) { struct isx012_state *state = to_state(sd); - cam_info("STREAM %s\n", (cmd == STREAM_STOP) ? "STOP" : "START"); + if (unlikely(!state->pdata->is_mipi)) + return 0; + + if (state->need_wait_streamoff) { + isx012_do_wait_steamoff(sd); + state->need_wait_streamoff = 0; + } else if (state->format_mode == V4L2_PIX_FMT_MODE_CAPTURE) + isx012_fast_capture_switch(sd); + + cam_trace("EX\n"); + + return 0; +} + +static int isx012_control_stream(struct v4l2_subdev *sd, u32 cmd) +{ + struct isx012_state *state = to_state(sd); if (cmd == STREAM_STOP) { - isx012_writeb(sd, 0x00BF, 0x01); +#if !defined(CONFIG_VIDEO_IMPROVE_STREAMOFF) + state->capture.pre_req = 0; +#endif + if (!((state->runmode == RUNMODE_RUNNING) + && state->capture.pre_req)) { + isx012_writeb(sd, 0x00BF, 0x01); + state->need_wait_streamoff = 1; + cam_info("STREAM STOP\n"); + } + #ifdef CONFIG_DEBUG_NO_FRAME isx012_stop_frame_checker(sd); #endif -#ifdef CONFIG_VIDEO_IMPROVE_STREAMOFF do_gettimeofday(&state->stream_time.before_time); - state->need_wait_streamoff = 1; -#else - msleep_debug(150, true); + +#if !defined(CONFIG_VIDEO_IMPROVE_STREAMOFF) + isx012_wait_steamoff(sd); #endif } else { isx012_writeb(sd, 0x00BF, 0x00); + cam_info("STREAM START\n"); return 0; } @@ -2480,39 +2629,31 @@ static int isx012_control_stream(struct v4l2_subdev *sd, u32 cmd) case RUNMODE_CAPTURING: cam_dbg("Capture Stop!\n"); state->runmode = RUNMODE_CAPTURING_STOP; + state->capture.ready = 0; + state->capture.lowlux_night = 0; -#ifdef CONFIG_NEW_STREAM_DELAY - if (state->lowlux_night) { - state->pdata->streamoff_delay = 400; - state->lowlux_night = 0; - } else - state->pdata->streamoff_delay = 150; -#endif - /* We turn flash off if one shot flash is still on. */ + /* We turn flash off if one-shot flash is still on. */ if (isx012_is_hwflash_on(sd)) isx012_flash_oneshot(sd, ISX012_FLASH_OFF); + else + state->flash.on = 0; - if (state->focus.preflash == PREFLASH_ON) + if (state->flash.preflash == PREFLASH_ON) isx012_post_sensor_flash(sd); break; case RUNMODE_RUNNING: cam_dbg("Preview Stop!\n"); state->runmode = RUNMODE_RUNNING_STOP; -#ifdef CONFIG_NEW_STREAM_DELAY - if (state->scene_mode == SCENE_MODE_NIGHTSHOT) - state->pdata->streamoff_delay = 150; - else - state->pdata->streamoff_delay = 66; -#endif + if (state->capture.pre_req) { + isx012_prepare_fast_capture(sd); + state->capture.pre_req = 0; + } break; case RUNMODE_RECORDING: state->runmode = RUNMODE_RECORDING_STOP; -#ifdef CONFIG_NEW_STREAM_DELAY - state->pdata->streamoff_delay = 66; -#endif break; default: @@ -2531,7 +2672,7 @@ static int isx012_set_flash_mode(struct v4l2_subdev *sd, s32 val) /* if (state->sensor_mode == SENSOR_MOVIE && !state->recording) return 0;*/ - if (state->flash_mode == val) { + if (state->flash.mode == val) { cam_dbg("the same flash mode=%d\n", val); return 0; } @@ -2539,11 +2680,11 @@ static int isx012_set_flash_mode(struct v4l2_subdev *sd, s32 val) if (val == FLASH_MODE_TORCH) isx012_flash_torch(sd, ISX012_FLASH_ON); - if ((state->flash_mode == FLASH_MODE_TORCH) + if ((state->flash.mode == FLASH_MODE_TORCH) && (val == FLASH_MODE_OFF)) isx012_flash_torch(sd, ISX012_FLASH_OFF); - state->flash_mode = val; + state->flash.mode = val; cam_dbg("Flash mode = %d\n", val); return 0; } @@ -2603,21 +2744,32 @@ retry: switch (val) { case ISO_AUTO: case ISO_50: + state->shutter_level_flash = 0xB52A; + break; + case ISO_100: + state->shutter_level_flash = 0x9DBA; + break; + case ISO_200: + state->shutter_level_flash = 0x864A; + break; + case ISO_400: - isx012_set_from_table(sd, "iso", - state->regs->iso, ARRAY_SIZE(state->regs->iso), - val); + state->shutter_level_flash = 0x738A; break; default: cam_err("set_iso: error, not supported (%d)\n", val); val = ISO_AUTO; goto retry; - break; } + isx012_set_from_table(sd, "iso", state->regs->iso, + ARRAY_SIZE(state->regs->iso), val); + + state->iso = val; + cam_trace("X\n"); return 0; } @@ -2641,7 +2793,9 @@ static inline void isx012_get_exif_flash(struct v4l2_subdev *sd, { struct isx012_state *state = to_state(sd); - switch (state->flash_mode) { + *flash = 0; + + switch (state->flash.mode) { case FLASH_MODE_OFF: *flash |= EXIF_FLASH_MODE_SUPPRESSION; break; @@ -2659,12 +2813,8 @@ static inline void isx012_get_exif_flash(struct v4l2_subdev *sd, break; } - if (state->flash_on) { + if (state->flash.on) *flash |= EXIF_FLASH_FIRED; - if (state->sensor_mode == SENSOR_CAMERA) - state->flash_on = 0; - } - } /* PX: */ @@ -2672,14 +2822,21 @@ static int isx012_get_exif(struct v4l2_subdev *sd) { struct isx012_state *state = to_state(sd); u32 exposure_time = 0; + u32 int_dec, integer; /* exposure time */ state->exif.exp_time_den = 0; isx012_get_exif_exptime(sd, &exposure_time); - /*WARN(!exposure_time, "WARNING: exposure time is 0\n");*/ - if (exposure_time) + if (exposure_time) { state->exif.exp_time_den = 1000 * 1000 / exposure_time; - else + + int_dec = (1000 * 1000) * 10 / exposure_time; + integer = state->exif.exp_time_den * 10; + + /* Round off */ + if ((int_dec - integer) > 5) + state->exif.exp_time_den += 1; + } else state->exif.exp_time_den = 0; /* iso */ @@ -2695,20 +2852,51 @@ static int isx012_get_exif(struct v4l2_subdev *sd) return 0; } +/* for debugging */ +static int isx012_check_preview_status(struct v4l2_subdev *sd) +{ + u32 reg_val1 = 0; + u32 reg_val4 = 0; + u32 reg_val7 = 0; + u32 reg_val11 = 0; + + /* AE SN */ + isx012_readb(sd, REG_AE_SN1, ®_val1); + isx012_readb(sd, REG_AE_SN4, ®_val4); + isx012_readb(sd, REG_AE_SN7, ®_val7); + isx012_readb(sd, REG_AE_SN11, ®_val11); + + cam_info("AE_SN[0x%X, 0x%X, 0x%X, 0x%X]" + , reg_val1, reg_val4, reg_val7, reg_val11); + + return 0; +} + static int isx012_set_preview_size(struct v4l2_subdev *sd) { struct isx012_state *state = to_state(sd); + u32 width, height; - if (!state->update_frmsize) + if (!state->preview.update_frmsize) return 0; - cam_dbg("set preview size(%dx%d)\n", - state->preview->width, state->preview->height); + if (unlikely(!state->preview.frmsize)) { + cam_warn("warning, preview resolution not set\n"); + state->preview.frmsize = isx012_get_framesize( + isx012_preview_frmsizes, + ARRAY_SIZE(isx012_preview_frmsizes), + PREVIEW_SZ_XGA); + } - isx012_writew(sd, REG_HSIZE_MONI, state->preview->width); - isx012_writew(sd, REG_VSIZE_MONI, state->preview->height); + width = state->preview.frmsize->width; + height = state->preview.frmsize->height; - state->update_frmsize = 0; + cam_dbg("set preview size(%dx%d)\n", width, height); + + isx012_writew(sd, REG_HSIZE_MONI, width); + isx012_writew(sd, REG_VSIZE_MONI, height); + + state->preview.update_frmsize = 0; return 0; } @@ -2718,7 +2906,7 @@ static int isx012_start_preview(struct v4l2_subdev *sd) struct isx012_state *state = to_state(sd); int err = -EINVAL; - cam_dbg("Camera Preview start, runmode = %d\n", state->runmode); + cam_info("Camera Preview start, runmode = %d\n", state->runmode); if ((state->runmode == RUNMODE_NOTREADY) || (state->runmode == RUNMODE_CAPTURING)) { @@ -2727,9 +2915,18 @@ static int isx012_start_preview(struct v4l2_subdev *sd) } state->focus.status = AF_RESULT_NONE; - state->focus.preflash = PREFLASH_NONE; + state->flash.preflash = PREFLASH_NONE; state->focus.touch = 0; + /* Do fast-AE before preview mode if needed */ + if (state->preview.fast_ae) { + cam_info("Fast AE for preview\n"); + isx012_set_from_table(sd, "flash_fast_ae_awb", + &state->regs->flash_fast_ae_awb, 1, 0); + isx012_wait_ae_stable_preview(sd); + state->preview.fast_ae = 0; + } + /* Set movie mode if needed. */ isx012_transit_movie_mode(sd); @@ -2745,8 +2942,11 @@ static int isx012_start_preview(struct v4l2_subdev *sd) err = isx012_transit_preview_mode(sd); CHECK_ERR_MSG(err, "preview_mode(%d)\n", err); + isx012_check_preview_status(sd); + err = isx012_is_cm_changed(sd); CHECK_ERR(err); + isx012_control_stream(sd, STREAM_START); #ifdef CONFIG_DEBUG_NO_FRAME @@ -2763,55 +2963,62 @@ static int isx012_start_preview(struct v4l2_subdev *sd) return 0; } -static int isx012_start_video_preview(struct v4l2_subdev *sd) +static int isx012_set_capture(struct v4l2_subdev *sd) { struct isx012_state *state = to_state(sd); - int err = -EINVAL; + int err = 0; + u32 lux = 0, ae_scl; - cam_dbg("Video Preview start, runmode = %d (Not Implemented)\n", - state->runmode); - return err; -} + if (unlikely((state->flash.preflash == PREFLASH_ON) && + (state->flash.mode == FLASH_MODE_OFF))) + isx012_post_sensor_flash(sd); -static int isx012_start_capture(struct v4l2_subdev *sd) -{ - struct isx012_state *state = to_state(sd); - int err = -ENODEV, count; - u32 lux = 0, val = 0; + if (state->capture.ae_manual_mode) { + /* Check whether fast-AE for preview is needed after capture */ + isx012_readw(sd, REG_AESCL, &ae_scl); + cam_dbg("set_capture: pre ae_scl = %d, ae_scl = %d\n", + state->flash.ae_scl, ae_scl); + if (abs(state->flash.ae_scl - ae_scl) >= AESCL_DIFF_FASTAE) + state->preview.fast_ae = 1; - cam_trace("E\n"); + isx012_set_from_table(sd, "ae_manual_mode", + &state->regs->ae_manual, 1, 0); + } /* Set capture size */ err = isx012_set_capture_size(sd); CHECK_ERR_MSG(err, "fail to set capture size (%d)\n", err); - if (state->focus.ae_manual_mode) { - isx012_writeb(sd, REG_AE_SN1, 0x02); - isx012_writeb(sd, REG_AE_SN4, 0x02); - isx012_writeb(sd, REG_AE_SN7, 0x02); - isx012_writeb(sd, REG_AE_SN11, 0x02); - - msleep_debug(66, true); /* Wait 1v time(66ms) */ - } - /* Set flash */ - switch (state->flash_mode) { + switch (state->flash.mode) { case FLASH_MODE_AUTO: - /* 3rd party App could do capturing without AF. So we check - * whether AF is executed before capture and turn on flash - * if needed. But we do not consider low-light capture of Market - * App. */ - if (state->focus.preflash == PREFLASH_NONE) { + /* 3rd party App could do capturing without AF.*/ + if (state->flash.preflash == PREFLASH_NONE) { isx012_get_light_level(sd, &lux); - if (lux < state->lux_level_flash) + if (!isx012_check_flash_fire(sd, lux)) break; - } else if (state->focus.preflash == PREFLASH_OFF) - break; + } else if (state->flash.preflash == PREFLASH_OFF) { + /* we re-check lux if capture after touch-AF*/ + if (!state->focus.lock) { + isx012_get_light_level(sd, &lux); + if (!isx012_check_flash_fire(sd, lux)) + break; + } else + break; + } /* We do not break. */ case FLASH_MODE_ON: isx012_flash_oneshot(sd, ISX012_FLASH_ON); - /* We here don't need to set state->flash_on to 1 */ + + if (unlikely(state->flash.preflash != PREFLASH_ON)) { + cam_warn("warning: Flash capture without preflash!!\n\n"); + isx012_set_from_table(sd, "flash_fast_ae_awb", + &state->regs->flash_fast_ae_awb, 1, 0); + isx012_wait_ae_stable_cap(sd); + state->flash.awb_delay = 0; + } else + state->flash.awb_delay = 210; break; case FLASH_MODE_OFF: @@ -2819,36 +3026,78 @@ static int isx012_start_capture(struct v4l2_subdev *sd) break; } - /* Set here lowlux_night field for night shot of 3rd party App. - * Refer to comments of above switch() statements */ - /* Transit to capture mode */ err = isx012_transit_capture_mode(sd); CHECK_ERR_MSG(err, "fail to capture_mode (%d)\n", err); - err = isx012_is_cm_changed(sd); + return 0; +} + +static int isx012_prepare_fast_capture(struct v4l2_subdev *sd) +{ + struct isx012_state *state = to_state(sd); + int err = 0; + + cam_info("prepare_fast_capture\n"); + + state->req_fmt.width = (state->capture.pre_req >> 16); + state->req_fmt.height = (state->capture.pre_req & 0xFFFF); + isx012_set_framesize(sd, isx012_capture_frmsizes, + ARRAY_SIZE(isx012_capture_frmsizes), false); + + err = isx012_set_capture(sd); CHECK_ERR(err); - isx012_control_stream(sd, STREAM_START); + state->capture.ready = 1; + + return 0; +} + +static int isx012_start_capture(struct v4l2_subdev *sd) +{ + struct isx012_state *state = to_state(sd); + int err = -ENODEV, count; + u32 val = 0; + u32 night_delay; + + cam_info("start_capture\n"); + + if (!state->capture.ready) { + err = isx012_set_capture(sd); + CHECK_ERR(err); + + err = isx012_is_cm_changed(sd); + CHECK_ERR(err); + + isx012_control_stream(sd, STREAM_START); + night_delay = 500; + } else + night_delay = 700; /* for completely skipping 1 frame. */ #ifdef CONFIG_DEBUG_NO_FRAME isx012_start_frame_checker(sd); #endif - if (state->focus.preflash == PREFLASH_ON) { - msleep_debug(210, true); + if (state->flash.on && (state->wb.mode == WHITE_BALANCE_AUTO)) { + msleep_debug(state->flash.awb_delay, true); + for (count = 0; count < ISX012_CNT_CAPTURE_AWB; count++) { isx012_readb(sd, REG_AWBSTS, &val); - if ((val & 0x06) != 0) { - cam_trace("AWB stable. cnt=%d\n", count); + if ((val & 0x06) != 0) break; - } + msleep_debug(30, false); } + + if (unlikely(count >= ISX012_CNT_CAPTURE_AWB)) + cam_warn("start_capture: fail to check awb\n"); } state->runmode = RUNMODE_CAPTURING; + if (state->capture.lowlux_night) + msleep_debug(night_delay, true); + /* Get EXIF */ isx012_get_exif(sd); @@ -2872,12 +3121,13 @@ static int isx012_s_mbus_fmt(struct v4l2_subdev *sd, state->format_mode = V4L2_PIX_FMT_MODE_CAPTURE; if (state->format_mode != V4L2_PIX_FMT_MODE_CAPTURE) { - previous_index = state->preview ? state->preview->index : -1; + previous_index = state->preview.frmsize ? + state->preview.frmsize->index : -1; isx012_set_framesize(sd, isx012_preview_frmsizes, ARRAY_SIZE(isx012_preview_frmsizes), true); - if (previous_index != state->preview->index) - state->update_frmsize = 1; + if (previous_index != state->preview.frmsize->index) + state->preview.update_frmsize = 1; } else { /* * In case of image capture mode, @@ -2888,8 +3138,8 @@ static int isx012_s_mbus_fmt(struct v4l2_subdev *sd, /* for maket app. * Samsung camera app does not use unmatched ratio.*/ - if (unlikely(FRM_RATIO(state->preview) - != FRM_RATIO(state->capture))) { + if (unlikely(FRM_RATIO(state->preview.frmsize) + != FRM_RATIO(state->capture.frmsize))) { cam_warn("%s: warning, capture ratio " \ "is different with preview ratio\n", __func__); @@ -2926,7 +3176,7 @@ static int isx012_try_mbus_fmt(struct v4l2_subdev *sd, for (i = 0; i < num_entries; i++) { if (capture_fmts[i].code == fmt->code && capture_fmts[i].colorspace == fmt->colorspace) { - cam_dbg("%s: match found, returning 0\n", __func__); + cam_info("%s: match found, returning 0\n", __func__); return 0; } } @@ -2948,23 +3198,23 @@ static int isx012_enum_framesizes(struct v4l2_subdev *sd, * this returns the default camera resolution (VGA) */ if (state->format_mode != V4L2_PIX_FMT_MODE_CAPTURE) { - if (unlikely(state->preview == NULL)) { + if (unlikely(state->preview.frmsize == NULL)) { cam_err("%s: error\n", __func__); return -EFAULT; } fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; - fsize->discrete.width = state->preview->width; - fsize->discrete.height = state->preview->height; + fsize->discrete.width = state->preview.frmsize->width; + fsize->discrete.height = state->preview.frmsize->height; } else { - if (unlikely(state->capture == NULL)) { + if (unlikely(state->capture.frmsize == NULL)) { cam_err("%s: error\n", __func__); return -EFAULT; } fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; - fsize->discrete.width = state->capture->width; - fsize->discrete.height = state->capture->height; + fsize->discrete.width = state->capture.frmsize->width; + fsize->discrete.height = state->capture.frmsize->height; } return 0; @@ -3082,7 +3332,7 @@ static int isx012_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) static int isx012_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { struct isx012_state *state = to_state(sd); - int err = -ENOIOCTLCMD; + int err = 0; if (!state->initialized && ctrl->id != V4L2_CID_CAMERA_SENSOR_MODE) { cam_warn("%s: WARNING, camera not initialized. ID = %d(0x%X)\n", @@ -3188,11 +3438,20 @@ static int isx012_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) err = isx012_set_iso(sd, ctrl->value); break; + case V4L2_CID_CAMERA_CAPTURE_MODE: + if (RUNMODE_RUNNING == state->runmode) + state->capture.pre_req = ctrl->value; + + break; + + case V4L2_CID_CAMERA_ANTI_BANDING: + break; + case V4L2_CID_CAMERA_FRAME_RATE: default: cam_err("%s: WARNING, unknown Ctrl-ID 0x%x\n", __func__, ctrl->id); - err = 0; /* we return no error. */ + /* we return no error. */ break; } @@ -3263,14 +3522,14 @@ static int isx012_s_stream(struct v4l2_subdev *sd, int enable) case STREAM_MODE_MOVIE_ON: cam_info("movie on"); state->recording = 1; - if (state->flash_mode != FLASH_MODE_OFF) + if (state->flash.mode != FLASH_MODE_OFF) isx012_flash_torch(sd, ISX012_FLASH_ON); break; case STREAM_MODE_MOVIE_OFF: cam_info("movie off"); state->recording = 0; - if (state->flash_on) + if (state->flash.on) isx012_flash_torch(sd, ISX012_FLASH_OFF); break; @@ -3457,7 +3716,7 @@ static int isx012_post_poweron(struct v4l2_subdev *sd) isx012_Sensor_Calibration(sd); cam_dbg("calibration complete!\n"); - cam_dbg("POWER ON END\n\n"); + cam_info("POWER ON END\n\n"); return 0; } @@ -3473,7 +3732,7 @@ static void isx012_init_parameter(struct v4l2_subdev *sd) state->light_level = LUX_LEVEL_MAX; /* Set update_frmsize to 1 for case of power reset */ - state->update_frmsize = 1; + state->preview.update_frmsize = 1; /* Initialize focus field for case of init after power reset. */ memset(&state->focus, 0, sizeof(state->focus)); @@ -3482,6 +3741,17 @@ static void isx012_init_parameter(struct v4l2_subdev *sd) state->frame_check = false; #endif state->lux_level_flash = LUX_LEVEL_FLASH_ON; + state->shutter_level_flash = 0x0; + +#ifdef CONFIG_LOAD_FILE + state->flash.ae_offset.ae_ofsetval = + isx012_define_read("AE_OFSETVAL", 4); + state->flash.ae_offset.ae_maxdiff = + isx012_define_read("AE_MAXDIFF", 4); +#else + state->flash.ae_offset.ae_ofsetval = AE_OFSETVAL; + state->flash.ae_offset.ae_maxdiff = AE_MAXDIFF; +#endif } static int isx012_init(struct v4l2_subdev *sd, u32 val) @@ -3489,10 +3759,11 @@ static int isx012_init(struct v4l2_subdev *sd, u32 val) struct isx012_state *state = to_state(sd); int err = -EINVAL; - cam_dbg("%s: start\n", __func__); + cam_info("init: start v08(%s)\n", __DATE__); #ifdef CONFIG_LOAD_FILE err = isx012_regs_table_init(); + CHECK_ERR_MSG(err, "loading setfile fail!\n"); #endif err = isx012_post_poweron(sd); CHECK_ERR_MSG(err, "power-on fail!\n"); @@ -3558,22 +3829,22 @@ static int isx012_s_config(struct v4l2_subdev *sd, else state->freq = state->pdata->freq; - state->preview = state->capture = NULL; + state->preview.frmsize = state->capture.frmsize = NULL; state->sensor_mode = SENSOR_CAMERA; state->format_mode = V4L2_PIX_FMT_MODE_PREVIEW; state->fps = 0; state->req_fps = -1; /* Initialize the independant HW module like flash here */ - state->flash_mode = FLASH_MODE_OFF; - state->flash_on = 0; + state->flash.mode = FLASH_MODE_OFF; + state->flash.on = 0; for (i = 0; i < ARRAY_SIZE(isx012_ctrls); i++) isx012_ctrls[i].value = isx012_ctrls[i].default_value; #ifdef ISX012_SUPPORT_FLASH if (isx012_is_hwflash_on(sd)) - state->ignore_flash = 1; + state->flash.ignore_flash = 1; #endif state->regs = ®_datas; @@ -3672,7 +3943,7 @@ static int isx012_remove(struct i2c_client *client) * to preventing Market App from controlling improperly flash. * It isn't necessary in case that you power flash down * in power routine to turn camera off.*/ - if (unlikely(state->flash_on && !state->ignore_flash)) + if (unlikely(state->flash.on && !state->flash.ignore_flash)) isx012_flash_torch(sd, ISX012_FLASH_OFF); v4l2_device_unregister_subdev(sd); @@ -3685,6 +3956,83 @@ static int isx012_remove(struct i2c_client *client) return 0; } +static int is_sysdev(struct device *dev, void *str) +{ + return !strcmp(dev_name(dev), (char *)str) ? 1 : 0; +} + +ssize_t cam_loglevel_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + char temp_buf[60] = {0,}; + + sprintf(buf, "Log Level: "); + if (dbg_level & CAMDBG_LEVEL_TRACE) { + sprintf(temp_buf, "trace "); + strcat(buf, temp_buf); + } + + if (dbg_level & CAMDBG_LEVEL_DEBUG) { + sprintf(temp_buf, "debug "); + strcat(buf, temp_buf); + } + + if (dbg_level & CAMDBG_LEVEL_INFO) { + sprintf(temp_buf, "info "); + strcat(buf, temp_buf); + } + + sprintf(temp_buf, "\n - warn and error level is always on\n\n"); + strcat(buf, temp_buf); + + return strlen(buf); +} + +ssize_t cam_loglevel_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + printk(KERN_DEBUG "CAM buf=%s, count=%d\n", buf, count); + + if (strstr(buf, "trace")) + dbg_level |= CAMDBG_LEVEL_TRACE; + else + dbg_level &= ~CAMDBG_LEVEL_TRACE; + + if (strstr(buf, "debug")) + dbg_level |= CAMDBG_LEVEL_DEBUG; + else + dbg_level &= ~CAMDBG_LEVEL_DEBUG; + + if (strstr(buf, "info")) + dbg_level |= CAMDBG_LEVEL_INFO; + + return count; +} + +static DEVICE_ATTR(loglevel, 0664, cam_loglevel_show, cam_loglevel_store); + +static int isx012_create_dbglogfile(struct class *cls) +{ + struct device *dev; + int err; + + dbg_level |= CAMDBG_LEVEL_DEFAULT; + + dev = class_find_device(cls, NULL, "rear", is_sysdev); + if (unlikely(!dev)) { + pr_info("[ISX012] can not find rear device\n"); + return 0; + } + + err = device_create_file(dev, &dev_attr_loglevel); + if (unlikely(err < 0)) { + pr_err("cam_init: failed to create device file, %s\n", + dev_attr_loglevel.attr.name); + } + + return 0; +} + static const struct i2c_device_id isx012_id[] = { { ISX012_DRIVER_NAME, 0 }, {} @@ -3703,6 +4051,7 @@ static int __init v4l2_i2c_drv_init(void) { pr_info("%s: %s called\n", __func__, ISX012_DRIVER_NAME); /* dslim*/ isx012_create_file(camera_class); + isx012_create_dbglogfile(camera_class); return i2c_add_driver(&v4l2_i2c_driver); } |