diff options
Diffstat (limited to 'drivers/media/video/m5mols')
-rw-r--r-- | drivers/media/video/m5mols/m5mols.h | 48 | ||||
-rw-r--r-- | drivers/media/video/m5mols/m5mols_capture.c | 83 | ||||
-rw-r--r-- | drivers/media/video/m5mols/m5mols_core.c | 310 | ||||
-rw-r--r-- | drivers/media/video/m5mols/m5mols_reg.h | 247 |
4 files changed, 323 insertions, 365 deletions
diff --git a/drivers/media/video/m5mols/m5mols.h b/drivers/media/video/m5mols/m5mols.h index 89d09a8914f..4b021e1ee5f 100644 --- a/drivers/media/video/m5mols/m5mols.h +++ b/drivers/media/video/m5mols/m5mols.h @@ -162,9 +162,7 @@ struct m5mols_version { * @pad: media pad * @ffmt: current fmt according to resolution type * @res_type: current resolution type - * @code: current code * @irq_waitq: waitqueue for the capture - * @work_irq: workqueue for the IRQ * @flags: state variable for the interrupt handler * @handle: control handler * @autoexposure: Auto Exposure control @@ -176,14 +174,12 @@ struct m5mols_version { * @ver: information of the version * @cap: the capture mode attributes * @power: current sensor's power status - * @ctrl_sync: true means all controls of the sensor are initialized - * @int_capture: true means the capture interrupt is issued once + * @isp_ready: 1 when the ISP controller has completed booting + * @ctrl_sync: 1 when the control handler state is restored in H/W * @lock_ae: true means the Auto Exposure is locked * @lock_awb: true means the Aut WhiteBalance is locked * @resolution: register value for current resolution - * @interrupt: register value for current interrupt status * @mode: register value for current operation mode - * @mode_save: register value for current operation mode for saving * @set_power: optional power callback to the board code */ struct m5mols_info { @@ -192,17 +188,16 @@ struct m5mols_info { struct media_pad pad; struct v4l2_mbus_framefmt ffmt[M5MOLS_RESTYPE_MAX]; int res_type; - enum v4l2_mbus_pixelcode code; + wait_queue_head_t irq_waitq; - struct work_struct work_irq; - unsigned long flags; + atomic_t irq_done; struct v4l2_ctrl_handler handle; + /* Autoexposure/exposure control cluster */ - struct { - struct v4l2_ctrl *autoexposure; - struct v4l2_ctrl *exposure; - }; + struct v4l2_ctrl *autoexposure; + struct v4l2_ctrl *exposure; + struct v4l2_ctrl *autowb; struct v4l2_ctrl *colorfx; struct v4l2_ctrl *saturation; @@ -210,21 +205,19 @@ struct m5mols_info { struct m5mols_version ver; struct m5mols_capture cap; - bool power; - bool ctrl_sync; + + unsigned int isp_ready:1; + unsigned int power:1; + unsigned int ctrl_sync:1; + bool lock_ae; bool lock_awb; u8 resolution; - u8 interrupt; u8 mode; - u8 mode_save; + int (*set_power)(struct device *dev, int on); }; -#define ST_CAPT_IRQ 0 - -#define is_powered(__info) (__info->power) -#define is_ctrl_synced(__info) (__info->ctrl_sync) #define is_available_af(__info) (__info->ver.af) #define is_code(__code, __type) (__code == m5mols_default_ffmt[__type].code) #define is_manufacturer(__info, __manufacturer) \ @@ -259,7 +252,15 @@ int m5mols_read_u8(struct v4l2_subdev *sd, u32 reg_comb, u8 *val); int m5mols_read_u16(struct v4l2_subdev *sd, u32 reg_comb, u16 *val); int m5mols_read_u32(struct v4l2_subdev *sd, u32 reg_comb, u32 *val); int m5mols_write(struct v4l2_subdev *sd, u32 reg_comb, u32 val); -int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u8 value); + +int m5mols_busy_wait(struct v4l2_subdev *sd, u32 reg, u32 value, u32 mask, + int timeout); + +/* Mask value for busy waiting until M-5MOLS I2C interface is initialized */ +#define M5MOLS_I2C_RDY_WAIT_FL (1 << 16) +/* ISP state transition timeout, in ms */ +#define M5MOLS_MODE_CHANGE_TIMEOUT 200 +#define M5MOLS_BUSY_WAIT_DEF_TIMEOUT 250 /* * Mode operation of the M-5MOLS @@ -284,7 +285,8 @@ int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u8 value); int m5mols_mode(struct m5mols_info *info, u8 mode); int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg); -int m5mols_sync_controls(struct m5mols_info *info); +int m5mols_wait_interrupt(struct v4l2_subdev *sd, u8 condition, u32 timeout); +int m5mols_restore_controls(struct m5mols_info *info); int m5mols_start_capture(struct m5mols_info *info); int m5mols_do_scenemode(struct m5mols_info *info, u8 mode); int m5mols_lock_3a(struct m5mols_info *info, bool lock); diff --git a/drivers/media/video/m5mols/m5mols_capture.c b/drivers/media/video/m5mols/m5mols_capture.c index 3248ac80571..ba25e8e2ba4 100644 --- a/drivers/media/video/m5mols/m5mols_capture.c +++ b/drivers/media/video/m5mols/m5mols_capture.c @@ -1,3 +1,4 @@ + /* * The Capture code for Fujitsu M-5MOLS ISP * @@ -25,26 +26,11 @@ #include <media/v4l2-device.h> #include <media/v4l2-subdev.h> #include <media/m5mols.h> +#include <media/s5p_fimc.h> #include "m5mols.h" #include "m5mols_reg.h" -static int m5mols_capture_error_handler(struct m5mols_info *info, - int timeout) -{ - int ret; - - /* Disable all interrupts and clear relevant interrupt staus bits */ - ret = m5mols_write(&info->sd, SYSTEM_INT_ENABLE, - info->interrupt & ~(REG_INT_CAPTURE)); - if (ret) - return ret; - - if (timeout == 0) - return -ETIMEDOUT; - - return 0; -} /** * m5mols_read_rational - I2C read of a rational number * @@ -121,69 +107,54 @@ int m5mols_start_capture(struct m5mols_info *info) { struct v4l2_subdev *sd = &info->sd; u8 resolution = info->resolution; - int timeout; int ret; /* - * Preparing capture. Setting control & interrupt before entering - * capture mode - * - * 1) change to MONITOR mode for operating control & interrupt - * 2) set controls (considering v4l2_control value & lock 3A) - * 3) set interrupt - * 4) change to CAPTURE mode + * Synchronize the controls, set the capture frame resolution and color + * format. The frame capture is initiated during switching from Monitor + * to Capture mode. */ ret = m5mols_mode(info, REG_MONITOR); if (!ret) - ret = m5mols_sync_controls(info); + ret = m5mols_restore_controls(info); if (!ret) - ret = m5mols_lock_3a(info, true); + ret = m5mols_write(sd, CAPP_YUVOUT_MAIN, REG_JPEG); + if (!ret) + ret = m5mols_write(sd, CAPP_MAIN_IMAGE_SIZE, resolution); if (!ret) - ret = m5mols_enable_interrupt(sd, REG_INT_CAPTURE); + ret = m5mols_lock_3a(info, true); if (!ret) ret = m5mols_mode(info, REG_CAPTURE); - if (!ret) { - /* Wait for capture interrupt, after changing capture mode */ - timeout = wait_event_interruptible_timeout(info->irq_waitq, - test_bit(ST_CAPT_IRQ, &info->flags), - msecs_to_jiffies(2000)); - if (test_and_clear_bit(ST_CAPT_IRQ, &info->flags)) - ret = m5mols_capture_error_handler(info, timeout); - } + if (!ret) + /* Wait until a frame is captured to ISP internal memory */ + ret = m5mols_wait_interrupt(sd, REG_INT_CAPTURE, 2000); if (!ret) ret = m5mols_lock_3a(info, false); if (ret) return ret; + /* - * Starting capture. Setting capture frame count and resolution and - * the format(available format: JPEG, Bayer RAW, YUV). - * - * 1) select single or multi(enable to 25), format, size - * 2) set interrupt - * 3) start capture(for main image, now) - * 4) get information - * 5) notify file size to v4l2 device(e.g, to s5p-fimc v4l2 device) + * Initiate the captured data transfer to a MIPI-CSI receiver. */ ret = m5mols_write(sd, CAPC_SEL_FRAME, 1); if (!ret) - ret = m5mols_write(sd, CAPP_YUVOUT_MAIN, REG_JPEG); - if (!ret) - ret = m5mols_write(sd, CAPP_MAIN_IMAGE_SIZE, resolution); - if (!ret) - ret = m5mols_enable_interrupt(sd, REG_INT_CAPTURE); - if (!ret) ret = m5mols_write(sd, CAPC_START, REG_CAP_START_MAIN); if (!ret) { + bool captured = false; + unsigned int size; + /* Wait for the capture completion interrupt */ - timeout = wait_event_interruptible_timeout(info->irq_waitq, - test_bit(ST_CAPT_IRQ, &info->flags), - msecs_to_jiffies(2000)); - if (test_and_clear_bit(ST_CAPT_IRQ, &info->flags)) { + ret = m5mols_wait_interrupt(sd, REG_INT_CAPTURE, 2000); + if (!ret) { + captured = true; ret = m5mols_capture_info(info); - if (!ret) - v4l2_subdev_notify(sd, 0, &info->cap.total); } + size = captured ? info->cap.main : 0; + v4l2_dbg(1, m5mols_debug, sd, "%s: size: %d, thumb.: %d B\n", + __func__, size, info->cap.thumb); + + v4l2_subdev_notify(sd, S5P_FIMC_TX_END_NOTIFY, &size); } - return m5mols_capture_error_handler(info, timeout); + return ret; } diff --git a/drivers/media/video/m5mols/m5mols_core.c b/drivers/media/video/m5mols/m5mols_core.c index 05ab3700647..93d768db9f3 100644 --- a/drivers/media/video/m5mols/m5mols_core.c +++ b/drivers/media/video/m5mols/m5mols_core.c @@ -135,10 +135,13 @@ static u32 m5mols_swap_byte(u8 *data, u8 length) * @reg: combination of size, category and command for the I2C packet * @size: desired size of I2C packet * @val: read value + * + * Returns 0 on success, or else negative errno. */ static int m5mols_read(struct v4l2_subdev *sd, u32 size, u32 reg, u32 *val) { struct i2c_client *client = v4l2_get_subdevdata(sd); + struct m5mols_info *info = to_m5mols(sd); u8 rbuf[M5MOLS_I2C_MAX_SIZE + 1]; u8 category = I2C_CATEGORY(reg); u8 cmd = I2C_COMMAND(reg); @@ -168,15 +171,17 @@ static int m5mols_read(struct v4l2_subdev *sd, u32 size, u32 reg, u32 *val) usleep_range(200, 200); ret = i2c_transfer(client->adapter, msg, 2); - if (ret < 0) { - v4l2_err(sd, "read failed: size:%d cat:%02x cmd:%02x. %d\n", - size, category, cmd, ret); - return ret; + + if (ret == 2) { + *val = m5mols_swap_byte(&rbuf[1], size); + return 0; } - *val = m5mols_swap_byte(&rbuf[1], size); + if (info->isp_ready) + v4l2_err(sd, "read failed: size:%d cat:%02x cmd:%02x. %d\n", + size, category, cmd, ret); - return 0; + return ret < 0 ? ret : -EIO; } int m5mols_read_u8(struct v4l2_subdev *sd, u32 reg, u8 *val) @@ -229,10 +234,13 @@ int m5mols_read_u32(struct v4l2_subdev *sd, u32 reg, u32 *val) * m5mols_write - I2C command write function * @reg: combination of size, category and command for the I2C packet * @val: value to write + * + * Returns 0 on success, or else negative errno. */ int m5mols_write(struct v4l2_subdev *sd, u32 reg, u32 val) { struct i2c_client *client = v4l2_get_subdevdata(sd); + struct m5mols_info *info = to_m5mols(sd); u8 wbuf[M5MOLS_I2C_MAX_SIZE + 4]; u8 category = I2C_CATEGORY(reg); u8 cmd = I2C_COMMAND(reg); @@ -263,28 +271,45 @@ int m5mols_write(struct v4l2_subdev *sd, u32 reg, u32 val) usleep_range(200, 200); ret = i2c_transfer(client->adapter, msg, 1); - if (ret < 0) { - v4l2_err(sd, "write failed: size:%d cat:%02x cmd:%02x. %d\n", - size, category, cmd, ret); - return ret; - } + if (ret == 1) + return 0; - return 0; + if (info->isp_ready) + v4l2_err(sd, "write failed: cat:%02x cmd:%02x ret:%d\n", + category, cmd, ret); + + return ret < 0 ? ret : -EIO; } -int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u8 mask) +/** + * m5mols_busy_wait - Busy waiting with I2C register polling + * @reg: the I2C_REG() address of an 8-bit status register to check + * @value: expected status register value + * @mask: bit mask for the read status register value + * @timeout: timeout in miliseconds, or -1 for default timeout + * + * The @reg register value is ORed with @mask before comparing with @value. + * + * Return: 0 if the requested condition became true within less than + * @timeout ms, or else negative errno. + */ +int m5mols_busy_wait(struct v4l2_subdev *sd, u32 reg, u32 value, u32 mask, + int timeout) { - u8 busy; - int i; - int ret; + int ms = timeout < 0 ? M5MOLS_BUSY_WAIT_DEF_TIMEOUT : timeout; + unsigned long end = jiffies + msecs_to_jiffies(ms); + u8 status; - for (i = 0; i < M5MOLS_I2C_CHECK_RETRY; i++) { - ret = m5mols_read_u8(sd, I2C_REG(category, cmd, 1), &busy); - if (ret < 0) + do { + int ret = m5mols_read_u8(sd, reg, &status); + + if (ret < 0 && !(mask & M5MOLS_I2C_RDY_WAIT_FL)) return ret; - if ((busy & mask) == mask) + if (!ret && (status & mask & 0xff) == (value & 0xff)) return 0; - } + usleep_range(100, 250); + } while (ms > 0 && time_is_after_jiffies(end)); + return -EBUSY; } @@ -307,6 +332,20 @@ int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg) return ret; } +int m5mols_wait_interrupt(struct v4l2_subdev *sd, u8 irq_mask, u32 timeout) +{ + struct m5mols_info *info = to_m5mols(sd); + + int ret = wait_event_interruptible_timeout(info->irq_waitq, + atomic_add_unless(&info->irq_done, -1, 0), + msecs_to_jiffies(timeout)); + if (ret <= 0) + return ret ? ret : -ETIMEDOUT; + + return m5mols_busy_wait(sd, SYSTEM_INT_FACTOR, irq_mask, + M5MOLS_I2C_RDY_WAIT_FL | irq_mask, -1); +} + /** * m5mols_reg_mode - Write the mode and check busy status * @@ -316,8 +355,10 @@ int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg) static int m5mols_reg_mode(struct v4l2_subdev *sd, u8 mode) { int ret = m5mols_write(sd, SYSTEM_SYSMODE, mode); - - return ret ? ret : m5mols_busy(sd, CAT_SYSTEM, CAT0_SYSMODE, mode); + if (ret < 0) + return ret; + return m5mols_busy_wait(sd, SYSTEM_SYSMODE, mode, 0xff, + M5MOLS_MODE_CHANGE_TIMEOUT); } /** @@ -334,17 +375,17 @@ int m5mols_mode(struct m5mols_info *info, u8 mode) int ret = -EINVAL; u8 reg; - if (mode < REG_PARAMETER && mode > REG_CAPTURE) + if (mode < REG_PARAMETER || mode > REG_CAPTURE) return ret; ret = m5mols_read_u8(sd, SYSTEM_SYSMODE, ®); - if ((!ret && reg == mode) || ret) + if (ret || reg == mode) return ret; switch (reg) { case REG_PARAMETER: ret = m5mols_reg_mode(sd, REG_MONITOR); - if (!ret && mode == REG_MONITOR) + if (mode == REG_MONITOR) break; if (!ret) ret = m5mols_reg_mode(sd, REG_CAPTURE); @@ -361,7 +402,7 @@ int m5mols_mode(struct m5mols_info *info, u8 mode) case REG_CAPTURE: ret = m5mols_reg_mode(sd, REG_MONITOR); - if (!ret && mode == REG_MONITOR) + if (mode == REG_MONITOR) break; if (!ret) ret = m5mols_reg_mode(sd, REG_PARAMETER); @@ -511,9 +552,6 @@ static int m5mols_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, struct m5mols_info *info = to_m5mols(sd); struct v4l2_mbus_framefmt *format; - if (fmt->pad != 0) - return -EINVAL; - format = __find_format(info, fh, fmt->which, info->res_type); if (!format) return -EINVAL; @@ -532,9 +570,6 @@ static int m5mols_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, u32 resolution = 0; int ret; - if (fmt->pad != 0) - return -EINVAL; - ret = __find_resolution(sd, format, &type, &resolution); if (ret < 0) return ret; @@ -543,13 +578,14 @@ static int m5mols_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, if (!sfmt) return 0; - *sfmt = m5mols_default_ffmt[type]; - sfmt->width = format->width; - sfmt->height = format->height; + + format->code = m5mols_default_ffmt[type].code; + format->colorspace = V4L2_COLORSPACE_JPEG; + format->field = V4L2_FIELD_NONE; if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { + *sfmt = *format; info->resolution = resolution; - info->code = format->code; info->res_type = type; } @@ -575,26 +611,25 @@ static struct v4l2_subdev_pad_ops m5mols_pad_ops = { }; /** - * m5mols_sync_controls - Apply default scene mode and the current controls + * m5mols_restore_controls - Apply current control values to the registers * - * This is used only streaming for syncing between v4l2_ctrl framework and - * m5mols's controls. First, do the scenemode to the sensor, then call - * v4l2_ctrl_handler_setup. It can be same between some commands and - * the scenemode's in the default v4l2_ctrls. But, such commands of control - * should be prior to the scenemode's one. + * m5mols_do_scenemode() handles all parameters for which there is yet no + * individual control. It should be replaced at some point by setting each + * control individually, in required register set up order. */ -int m5mols_sync_controls(struct m5mols_info *info) +int m5mols_restore_controls(struct m5mols_info *info) { - int ret = -EINVAL; + int ret; - if (!is_ctrl_synced(info)) { - ret = m5mols_do_scenemode(info, REG_SCENE_NORMAL); - if (ret) - return ret; + if (info->ctrl_sync) + return 0; - v4l2_ctrl_handler_setup(&info->handle); - info->ctrl_sync = true; - } + ret = m5mols_do_scenemode(info, REG_SCENE_NORMAL); + if (ret) + return ret; + + ret = v4l2_ctrl_handler_setup(&info->handle); + info->ctrl_sync = !ret; return ret; } @@ -618,7 +653,7 @@ static int m5mols_start_monitor(struct m5mols_info *info) if (!ret) ret = m5mols_mode(info, REG_MONITOR); if (!ret) - ret = m5mols_sync_controls(info); + ret = m5mols_restore_controls(info); return ret; } @@ -626,13 +661,14 @@ static int m5mols_start_monitor(struct m5mols_info *info) static int m5mols_s_stream(struct v4l2_subdev *sd, int enable) { struct m5mols_info *info = to_m5mols(sd); + u32 code = info->ffmt[info->res_type].code; if (enable) { int ret = -EINVAL; - if (is_code(info->code, M5MOLS_RESTYPE_MONITOR)) + if (is_code(code, M5MOLS_RESTYPE_MONITOR)) ret = m5mols_start_monitor(info); - if (is_code(info->code, M5MOLS_RESTYPE_CAPTURE)) + if (is_code(code, M5MOLS_RESTYPE_CAPTURE)) ret = m5mols_start_capture(info); return ret; @@ -649,17 +685,25 @@ static int m5mols_s_ctrl(struct v4l2_ctrl *ctrl) { struct v4l2_subdev *sd = to_sd(ctrl); struct m5mols_info *info = to_m5mols(sd); + int ispstate = info->mode; int ret; - info->mode_save = info->mode; + /* + * If needed, defer restoring the controls until + * the device is fully initialized. + */ + if (!info->isp_ready) { + info->ctrl_sync = 0; + return 0; + } ret = m5mols_mode(info, REG_PARAMETER); - if (!ret) - ret = m5mols_set_ctrl(ctrl); - if (!ret) - ret = m5mols_mode(info, info->mode_save); - - return ret; + if (ret < 0) + return ret; + ret = m5mols_set_ctrl(ctrl); + if (ret < 0) + return ret; + return m5mols_mode(info, ispstate); } static const struct v4l2_ctrl_ops m5mols_ctrl_ops = { @@ -673,10 +717,10 @@ static int m5mols_sensor_power(struct m5mols_info *info, bool enable) const struct m5mols_platform_data *pdata = info->pdata; int ret; - if (enable) { - if (is_powered(info)) - return 0; + if (info->power == enable) + return 0; + if (enable) { if (info->set_power) { ret = info->set_power(&client->dev, 1); if (ret) @@ -690,15 +734,11 @@ static int m5mols_sensor_power(struct m5mols_info *info, bool enable) } gpio_set_value(pdata->gpio_reset, !pdata->reset_polarity); - usleep_range(1000, 1000); - info->power = true; + info->power = 1; return ret; } - if (!is_powered(info)) - return 0; - ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies); if (ret) return ret; @@ -707,8 +747,9 @@ static int m5mols_sensor_power(struct m5mols_info *info, bool enable) info->set_power(&client->dev, 0); gpio_set_value(pdata->gpio_reset, pdata->reset_polarity); - usleep_range(1000, 1000); - info->power = false; + + info->isp_ready = 0; + info->power = 0; return ret; } @@ -721,21 +762,29 @@ int __attribute__ ((weak)) m5mols_update_fw(struct v4l2_subdev *sd, } /** - * m5mols_sensor_armboot - Booting M-5MOLS internal ARM core. + * m5mols_fw_start - M-5MOLS internal ARM controller initialization * - * Booting internal ARM core makes the M-5MOLS is ready for getting commands - * with I2C. It's the first thing to be done after it powered up. It must wait - * at least 520ms recommended by M-5MOLS datasheet, after executing arm booting. + * Execute the M-5MOLS internal ARM controller initialization sequence. + * This function should be called after the supply voltage has been + * applied and before any requests to the device are made. */ -static int m5mols_sensor_armboot(struct v4l2_subdev *sd) +static int m5mols_fw_start(struct v4l2_subdev *sd) { + struct m5mols_info *info = to_m5mols(sd); int ret; - ret = m5mols_write(sd, FLASH_CAM_START, REG_START_ARM_BOOT); + atomic_set(&info->irq_done, 0); + /* Wait until I2C slave is initialized in Flash Writer mode */ + ret = m5mols_busy_wait(sd, FLASH_CAM_START, REG_IN_FLASH_MODE, + M5MOLS_I2C_RDY_WAIT_FL | 0xff, -1); + if (!ret) + ret = m5mols_write(sd, FLASH_CAM_START, REG_START_ARM_BOOT); + if (!ret) + ret = m5mols_wait_interrupt(sd, REG_INT_MODE, 2000); if (ret < 0) return ret; - msleep(520); + info->isp_ready = 1; ret = m5mols_get_version(sd); if (!ret) @@ -747,7 +796,8 @@ static int m5mols_sensor_armboot(struct v4l2_subdev *sd) ret = m5mols_write(sd, PARM_INTERFACE, REG_INTERFACE_MIPI); if (!ret) - ret = m5mols_enable_interrupt(sd, REG_INT_AF); + ret = m5mols_enable_interrupt(sd, + REG_INT_AF | REG_INT_CAPTURE); return ret; } @@ -784,7 +834,7 @@ static int m5mols_init_controls(struct m5mols_info *info) 4, (1 << V4L2_COLORFX_BW), V4L2_COLORFX_NONE); info->autoexposure = v4l2_ctrl_new_std_menu(&info->handle, &m5mols_ctrl_ops, V4L2_CID_EXPOSURE_AUTO, - 1, 0, V4L2_EXPOSURE_MANUAL); + 1, 0, V4L2_EXPOSURE_AUTO); sd->ctrl_handler = &info->handle; if (info->handle.error) { @@ -813,16 +863,7 @@ static int m5mols_s_power(struct v4l2_subdev *sd, int on) if (on) { ret = m5mols_sensor_power(info, true); if (!ret) - ret = m5mols_sensor_armboot(sd); - if (!ret) - ret = m5mols_init_controls(info); - if (ret) - return ret; - - info->ffmt[M5MOLS_RESTYPE_MONITOR] = - m5mols_default_ffmt[M5MOLS_RESTYPE_MONITOR]; - info->ffmt[M5MOLS_RESTYPE_CAPTURE] = - m5mols_default_ffmt[M5MOLS_RESTYPE_CAPTURE]; + ret = m5mols_fw_start(sd); return ret; } @@ -833,17 +874,14 @@ static int m5mols_s_power(struct v4l2_subdev *sd, int on) if (!ret) ret = m5mols_write(sd, AF_MODE, REG_AF_POWEROFF); if (!ret) - ret = m5mols_busy(sd, CAT_SYSTEM, CAT0_STATUS, - REG_AF_IDLE); - if (!ret) - v4l2_info(sd, "Success soft-landing lens\n"); + ret = m5mols_busy_wait(sd, SYSTEM_STATUS, REG_AF_IDLE, + 0xff, -1); + if (ret < 0) + v4l2_warn(sd, "Soft landing lens failed\n"); } ret = m5mols_sensor_power(info, false); - if (!ret) { - v4l2_ctrl_handler_free(&info->handle); - info->ctrl_sync = false; - } + info->ctrl_sync = 0; return ret; } @@ -869,52 +907,33 @@ static const struct v4l2_subdev_core_ops m5mols_core_ops = { .log_status = m5mols_log_status, }; +/* + * V4L2 subdev internal operations + */ +static int m5mols_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(fh, 0); + + *format = m5mols_default_ffmt[0]; + return 0; +} + +static const struct v4l2_subdev_internal_ops m5mols_subdev_internal_ops = { + .open = m5mols_open, +}; + static const struct v4l2_subdev_ops m5mols_ops = { .core = &m5mols_core_ops, .pad = &m5mols_pad_ops, .video = &m5mols_video_ops, }; -static void m5mols_irq_work(struct work_struct *work) -{ - struct m5mols_info *info = - container_of(work, struct m5mols_info, work_irq); - struct v4l2_subdev *sd = &info->sd; - u8 reg; - int ret; - - if (!is_powered(info) || - m5mols_read_u8(sd, SYSTEM_INT_FACTOR, &info->interrupt)) - return; - - switch (info->interrupt & REG_INT_MASK) { - case REG_INT_AF: - if (!is_available_af(info)) - break; - ret = m5mols_read_u8(sd, AF_STATUS, ®); - v4l2_dbg(2, m5mols_debug, sd, "AF %s\n", - reg == REG_AF_FAIL ? "Failed" : - reg == REG_AF_SUCCESS ? "Success" : - reg == REG_AF_IDLE ? "Idle" : "Busy"); - break; - case REG_INT_CAPTURE: - if (!test_and_set_bit(ST_CAPT_IRQ, &info->flags)) - wake_up_interruptible(&info->irq_waitq); - - v4l2_dbg(2, m5mols_debug, sd, "CAPTURE\n"); - break; - default: - v4l2_dbg(2, m5mols_debug, sd, "Undefined: %02x\n", reg); - break; - }; -} - static irqreturn_t m5mols_irq_handler(int irq, void *data) { - struct v4l2_subdev *sd = data; - struct m5mols_info *info = to_m5mols(sd); + struct m5mols_info *info = to_m5mols(data); - schedule_work(&info->work_irq); + atomic_set(&info->irq_done, 1); + wake_up_interruptible(&info->irq_waitq); return IRQ_HANDLED; } @@ -965,7 +984,9 @@ static int __devinit m5mols_probe(struct i2c_client *client, sd = &info->sd; strlcpy(sd->name, MODULE_NAME, sizeof(sd->name)); v4l2_i2c_subdev_init(sd, client, &m5mols_ops); + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + sd->internal_ops = &m5mols_subdev_internal_ops; info->pad.flags = MEDIA_PAD_FL_SOURCE; ret = media_entity_init(&sd->entity, 1, &info->pad, 0); if (ret < 0) @@ -973,7 +994,6 @@ static int __devinit m5mols_probe(struct i2c_client *client, sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR; init_waitqueue_head(&info->irq_waitq); - INIT_WORK(&info->work_irq, m5mols_irq_work); ret = request_irq(client->irq, m5mols_irq_handler, IRQF_TRIGGER_RISING, MODULE_NAME, sd); if (ret) { @@ -981,7 +1001,20 @@ static int __devinit m5mols_probe(struct i2c_client *client, goto out_me; } info->res_type = M5MOLS_RESTYPE_MONITOR; - return 0; + info->ffmt[0] = m5mols_default_ffmt[0]; + info->ffmt[1] = m5mols_default_ffmt[1]; + + ret = m5mols_sensor_power(info, true); + if (ret) + goto out_me; + + ret = m5mols_fw_start(sd); + if (!ret) + ret = m5mols_init_controls(info); + + m5mols_sensor_power(info, false); + if (!ret) + return 0; out_me: media_entity_cleanup(&sd->entity); out_reg: @@ -999,6 +1032,7 @@ static int __devexit m5mols_remove(struct i2c_client *client) struct m5mols_info *info = to_m5mols(sd); v4l2_device_unregister_subdev(sd); + v4l2_ctrl_handler_free(sd->ctrl_handler); free_irq(client->irq, sd); regulator_bulk_free(ARRAY_SIZE(supplies), supplies); diff --git a/drivers/media/video/m5mols/m5mols_reg.h b/drivers/media/video/m5mols/m5mols_reg.h index c755bd6edfe..ae4aced0f9b 100644 --- a/drivers/media/video/m5mols/m5mols_reg.h +++ b/drivers/media/video/m5mols/m5mols_reg.h @@ -55,39 +55,31 @@ * There is many registers between customer version address and awb one. For * more specific contents, see definition if file m5mols.h. */ -#define CAT0_VER_CUSTOMER 0x00 /* customer version */ -#define CAT0_VER_PROJECT 0x01 /* project version */ -#define CAT0_VER_FIRMWARE 0x02 /* Firmware version */ -#define CAT0_VER_HARDWARE 0x04 /* Hardware version */ -#define CAT0_VER_PARAMETER 0x06 /* Parameter version */ -#define CAT0_VER_AWB 0x08 /* Auto WB version */ -#define CAT0_VER_STRING 0x0a /* string including M-5MOLS */ -#define CAT0_SYSMODE 0x0b /* SYSTEM mode register */ -#define CAT0_STATUS 0x0c /* SYSTEM mode status register */ -#define CAT0_INT_FACTOR 0x10 /* interrupt pending register */ -#define CAT0_INT_ENABLE 0x11 /* interrupt enable register */ - -#define SYSTEM_VER_CUSTOMER I2C_REG(CAT_SYSTEM, CAT0_VER_CUSTOMER, 1) -#define SYSTEM_VER_PROJECT I2C_REG(CAT_SYSTEM, CAT0_VER_PROJECT, 1) -#define SYSTEM_VER_FIRMWARE I2C_REG(CAT_SYSTEM, CAT0_VER_FIRMWARE, 2) -#define SYSTEM_VER_HARDWARE I2C_REG(CAT_SYSTEM, CAT0_VER_HARDWARE, 2) -#define SYSTEM_VER_PARAMETER I2C_REG(CAT_SYSTEM, CAT0_VER_PARAMETER, 2) -#define SYSTEM_VER_AWB I2C_REG(CAT_SYSTEM, CAT0_VER_AWB, 2) - -#define SYSTEM_SYSMODE I2C_REG(CAT_SYSTEM, CAT0_SYSMODE, 1) +#define SYSTEM_VER_CUSTOMER I2C_REG(CAT_SYSTEM, 0x00, 1) +#define SYSTEM_VER_PROJECT I2C_REG(CAT_SYSTEM, 0x01, 1) +#define SYSTEM_VER_FIRMWARE I2C_REG(CAT_SYSTEM, 0x02, 2) +#define SYSTEM_VER_HARDWARE I2C_REG(CAT_SYSTEM, 0x04, 2) +#define SYSTEM_VER_PARAMETER I2C_REG(CAT_SYSTEM, 0x06, 2) +#define SYSTEM_VER_AWB I2C_REG(CAT_SYSTEM, 0x08, 2) + +#define SYSTEM_SYSMODE I2C_REG(CAT_SYSTEM, 0x0b, 1) #define REG_SYSINIT 0x00 /* SYSTEM mode */ #define REG_PARAMETER 0x01 /* PARAMETER mode */ #define REG_MONITOR 0x02 /* MONITOR mode */ #define REG_CAPTURE 0x03 /* CAPTURE mode */ #define SYSTEM_CMD(__cmd) I2C_REG(CAT_SYSTEM, cmd, 1) -#define SYSTEM_VER_STRING I2C_REG(CAT_SYSTEM, CAT0_VER_STRING, 1) +#define SYSTEM_VER_STRING I2C_REG(CAT_SYSTEM, 0x0a, 1) #define REG_SAMSUNG_ELECTRO "SE" /* Samsung Electro-Mechanics */ #define REG_SAMSUNG_OPTICS "OP" /* Samsung Fiber-Optics */ #define REG_SAMSUNG_TECHWIN "TB" /* Samsung Techwin */ +/* SYSTEM mode status */ +#define SYSTEM_STATUS I2C_REG(CAT_SYSTEM, 0x0c, 1) -#define SYSTEM_INT_FACTOR I2C_REG(CAT_SYSTEM, CAT0_INT_FACTOR, 1) -#define SYSTEM_INT_ENABLE I2C_REG(CAT_SYSTEM, CAT0_INT_ENABLE, 1) +/* Interrupt pending register */ +#define SYSTEM_INT_FACTOR I2C_REG(CAT_SYSTEM, 0x10, 1) +/* interrupt enable register */ +#define SYSTEM_INT_ENABLE I2C_REG(CAT_SYSTEM, 0x11, 1) #define REG_INT_MODE (1 << 0) #define REG_INT_AF (1 << 1) #define REG_INT_ZOOM (1 << 2) @@ -105,20 +97,20 @@ * can handle with preview(MONITOR) resolution size/frame per second/interface * between the sensor and the Application Processor/even the image effect. */ -#define CAT1_DATA_INTERFACE 0x00 /* interface between sensor and AP */ -#define CAT1_MONITOR_SIZE 0x01 /* resolution at the MONITOR mode */ -#define CAT1_MONITOR_FPS 0x02 /* frame per second at this mode */ -#define CAT1_EFFECT 0x0b /* image effects */ -#define PARM_MON_SIZE I2C_REG(CAT_PARAM, CAT1_MONITOR_SIZE, 1) +/* Resolution in the MONITOR mode */ +#define PARM_MON_SIZE I2C_REG(CAT_PARAM, 0x01, 1) -#define PARM_MON_FPS I2C_REG(CAT_PARAM, CAT1_MONITOR_FPS, 1) +/* Frame rate */ +#define PARM_MON_FPS I2C_REG(CAT_PARAM, 0x02, 1) #define REG_FPS_30 0x02 -#define PARM_INTERFACE I2C_REG(CAT_PARAM, CAT1_DATA_INTERFACE, 1) +/* Video bus between the sensor and a host processor */ +#define PARM_INTERFACE I2C_REG(CAT_PARAM, 0x00, 1) #define REG_INTERFACE_MIPI 0x02 -#define PARM_EFFECT I2C_REG(CAT_PARAM, CAT1_EFFECT, 1) +/* Image effects */ +#define PARM_EFFECT I2C_REG(CAT_PARAM, 0x0b, 1) #define REG_EFFECT_OFF 0x00 #define REG_EFFECT_NEGA 0x01 #define REG_EFFECT_EMBOSS 0x06 @@ -135,39 +127,37 @@ * another options like zoom/color effect(different with effect in PARAMETER * mode)/anti hand shaking algorithm. */ -#define CAT2_ZOOM 0x01 /* set the zoom position & execute */ -#define CAT2_ZOOM_STEP 0x03 /* set the zoom step */ -#define CAT2_CFIXB 0x09 /* CB value for color effect */ -#define CAT2_CFIXR 0x0a /* CR value for color effect */ -#define CAT2_COLOR_EFFECT 0x0b /* set on/off of color effect */ -#define CAT2_CHROMA_LVL 0x0f /* set chroma level */ -#define CAT2_CHROMA_EN 0x10 /* set on/off of choroma */ -#define CAT2_EDGE_LVL 0x11 /* set sharpness level */ -#define CAT2_EDGE_EN 0x12 /* set on/off sharpness */ -#define CAT2_TONE_CTL 0x25 /* set tone color(contrast) */ - -#define MON_ZOOM I2C_REG(CAT_MONITOR, CAT2_ZOOM, 1) - -#define MON_CFIXR I2C_REG(CAT_MONITOR, CAT2_CFIXR, 1) -#define MON_CFIXB I2C_REG(CAT_MONITOR, CAT2_CFIXB, 1) + +/* Target digital zoom position */ +#define MON_ZOOM I2C_REG(CAT_MONITOR, 0x01, 1) + +/* CR value for color effect */ +#define MON_CFIXR I2C_REG(CAT_MONITOR, 0x0a, 1) +/* CB value for color effect */ +#define MON_CFIXB I2C_REG(CAT_MONITOR, 0x09, 1) #define REG_CFIXB_SEPIA 0xd8 #define REG_CFIXR_SEPIA 0x18 -#define MON_EFFECT I2C_REG(CAT_MONITOR, CAT2_COLOR_EFFECT, 1) +#define MON_EFFECT I2C_REG(CAT_MONITOR, 0x0b, 1) #define REG_COLOR_EFFECT_OFF 0x00 #define REG_COLOR_EFFECT_ON 0x01 -#define MON_CHROMA_EN I2C_REG(CAT_MONITOR, CAT2_CHROMA_EN, 1) -#define MON_CHROMA_LVL I2C_REG(CAT_MONITOR, CAT2_CHROMA_LVL, 1) +/* Chroma enable */ +#define MON_CHROMA_EN I2C_REG(CAT_MONITOR, 0x10, 1) +/* Chroma level */ +#define MON_CHROMA_LVL I2C_REG(CAT_MONITOR, 0x0f, 1) #define REG_CHROMA_OFF 0x00 #define REG_CHROMA_ON 0x01 -#define MON_EDGE_EN I2C_REG(CAT_MONITOR, CAT2_EDGE_EN, 1) -#define MON_EDGE_LVL I2C_REG(CAT_MONITOR, CAT2_EDGE_LVL, 1) +/* Sharpness on/off */ +#define MON_EDGE_EN I2C_REG(CAT_MONITOR, 0x12, 1) +/* Sharpness level */ +#define MON_EDGE_LVL I2C_REG(CAT_MONITOR, 0x11, 1) #define REG_EDGE_OFF 0x00 #define REG_EDGE_ON 0x01 -#define MON_TONE_CTL I2C_REG(CAT_MONITOR, CAT2_TONE_CTL, 1) +/* Set color tone (contrast) */ +#define MON_TONE_CTL I2C_REG(CAT_MONITOR, 0x25, 1) /* * Category 3 - Auto Exposure @@ -179,27 +169,20 @@ * different. So, this category also provide getting the max/min values. And, * each MONITOR and CAPTURE mode has each gain/shutter/max exposure values. */ -#define CAT3_AE_LOCK 0x00 /* locking Auto exposure */ -#define CAT3_AE_MODE 0x01 /* set AE mode, mode means range */ -#define CAT3_ISO 0x05 /* set ISO */ -#define CAT3_EV_PRESET_MONITOR 0x0a /* EV(scenemode) preset for MONITOR */ -#define CAT3_EV_PRESET_CAPTURE 0x0b /* EV(scenemode) preset for CAPTURE */ -#define CAT3_MANUAL_GAIN_MON 0x12 /* meteoring value for the MONITOR */ -#define CAT3_MAX_GAIN_MON 0x1a /* max gain value for the MONITOR */ -#define CAT3_MANUAL_GAIN_CAP 0x26 /* meteoring value for the CAPTURE */ -#define CAT3_AE_INDEX 0x38 /* AE index */ - -#define AE_LOCK I2C_REG(CAT_AE, CAT3_AE_LOCK, 1) + +/* Auto Exposure locking */ +#define AE_LOCK I2C_REG(CAT_AE, 0x00, 1) #define REG_AE_UNLOCK 0x00 #define REG_AE_LOCK 0x01 -#define AE_MODE I2C_REG(CAT_AE, CAT3_AE_MODE, 1) +/* Auto Exposure algorithm mode */ +#define AE_MODE I2C_REG(CAT_AE, 0x01, 1) #define REG_AE_OFF 0x00 /* AE off */ #define REG_AE_ALL 0x01 /* calc AE in all block integral */ #define REG_AE_CENTER 0x03 /* calc AE in center weighted */ #define REG_AE_SPOT 0x06 /* calc AE in specific spot */ -#define AE_ISO I2C_REG(CAT_AE, CAT3_ISO, 1) +#define AE_ISO I2C_REG(CAT_AE, 0x05, 1) #define REG_ISO_AUTO 0x00 #define REG_ISO_50 0x01 #define REG_ISO_100 0x02 @@ -207,8 +190,10 @@ #define REG_ISO_400 0x04 #define REG_ISO_800 0x05 -#define AE_EV_PRESET_MONITOR I2C_REG(CAT_AE, CAT3_EV_PRESET_MONITOR, 1) -#define AE_EV_PRESET_CAPTURE I2C_REG(CAT_AE, CAT3_EV_PRESET_CAPTURE, 1) +/* EV (scenemode) preset for MONITOR */ +#define AE_EV_PRESET_MONITOR I2C_REG(CAT_AE, 0x0a, 1) +/* EV (scenemode) preset for CAPTURE */ +#define AE_EV_PRESET_CAPTURE I2C_REG(CAT_AE, 0x0b, 1) #define REG_SCENE_NORMAL 0x00 #define REG_SCENE_PORTRAIT 0x01 #define REG_SCENE_LANDSCAPE 0x02 @@ -224,11 +209,14 @@ #define REG_SCENE_TEXT 0x0c #define REG_SCENE_CANDLE 0x0d -#define AE_MAN_GAIN_MON I2C_REG(CAT_AE, CAT3_MANUAL_GAIN_MON, 2) -#define AE_MAX_GAIN_MON I2C_REG(CAT_AE, CAT3_MAX_GAIN_MON, 2) -#define AE_MAN_GAIN_CAP I2C_REG(CAT_AE, CAT3_MANUAL_GAIN_CAP, 2) +/* Manual gain in MONITOR mode */ +#define AE_MAN_GAIN_MON I2C_REG(CAT_AE, 0x12, 2) +/* Maximum gain in MONITOR mode */ +#define AE_MAX_GAIN_MON I2C_REG(CAT_AE, 0x1a, 2) +/* Manual gain in CAPTURE mode */ +#define AE_MAN_GAIN_CAP I2C_REG(CAT_AE, 0x26, 2) -#define AE_INDEX I2C_REG(CAT_AE, CAT3_AE_INDEX, 1) +#define AE_INDEX I2C_REG(CAT_AE, 0x38, 1) #define REG_AE_INDEX_20_NEG 0x00 #define REG_AE_INDEX_15_NEG 0x01 #define REG_AE_INDEX_10_NEG 0x02 @@ -241,22 +229,19 @@ /* * Category 6 - White Balance - * - * This category provide AWB locking/mode/preset/speed/gain bias, etc. */ -#define CAT6_AWB_LOCK 0x00 /* locking Auto Whitebalance */ -#define CAT6_AWB_MODE 0x02 /* set Auto or Manual */ -#define CAT6_AWB_MANUAL 0x03 /* set Manual(preset) value */ -#define AWB_LOCK I2C_REG(CAT_WB, CAT6_AWB_LOCK, 1) +/* Auto Whitebalance locking */ +#define AWB_LOCK I2C_REG(CAT_WB, 0x00, 1) #define REG_AWB_UNLOCK 0x00 #define REG_AWB_LOCK 0x01 -#define AWB_MODE I2C_REG(CAT_WB, CAT6_AWB_MODE, 1) +#define AWB_MODE I2C_REG(CAT_WB, 0x02, 1) #define REG_AWB_AUTO 0x01 /* AWB off */ #define REG_AWB_PRESET 0x02 /* AWB preset */ -#define AWB_MANUAL I2C_REG(CAT_WB, CAT6_AWB_MANUAL, 1) +/* Manual WB (preset) */ +#define AWB_MANUAL I2C_REG(CAT_WB, 0x03, 1) #define REG_AWB_INCANDESCENT 0x01 #define REG_AWB_FLUORESCENT_1 0x02 #define REG_AWB_FLUORESCENT_2 0x03 @@ -269,42 +254,25 @@ /* * Category 7 - EXIF information */ -#define CAT7_INFO_EXPTIME_NU 0x00 -#define CAT7_INFO_EXPTIME_DE 0x04 -#define CAT7_INFO_TV_NU 0x08 -#define CAT7_INFO_TV_DE 0x0c -#define CAT7_INFO_AV_NU 0x10 -#define CAT7_INFO_AV_DE 0x14 -#define CAT7_INFO_BV_NU 0x18 -#define CAT7_INFO_BV_DE 0x1c -#define CAT7_INFO_EBV_NU 0x20 -#define CAT7_INFO_EBV_DE 0x24 -#define CAT7_INFO_ISO 0x28 -#define CAT7_INFO_FLASH 0x2a -#define CAT7_INFO_SDR 0x2c -#define CAT7_INFO_QVAL 0x2e - -#define EXIF_INFO_EXPTIME_NU I2C_REG(CAT_EXIF, CAT7_INFO_EXPTIME_NU, 4) -#define EXIF_INFO_EXPTIME_DE I2C_REG(CAT_EXIF, CAT7_INFO_EXPTIME_DE, 4) -#define EXIF_INFO_TV_NU I2C_REG(CAT_EXIF, CAT7_INFO_TV_NU, 4) -#define EXIF_INFO_TV_DE I2C_REG(CAT_EXIF, CAT7_INFO_TV_DE, 4) -#define EXIF_INFO_AV_NU I2C_REG(CAT_EXIF, CAT7_INFO_AV_NU, 4) -#define EXIF_INFO_AV_DE I2C_REG(CAT_EXIF, CAT7_INFO_AV_DE, 4) -#define EXIF_INFO_BV_NU I2C_REG(CAT_EXIF, CAT7_INFO_BV_NU, 4) -#define EXIF_INFO_BV_DE I2C_REG(CAT_EXIF, CAT7_INFO_BV_DE, 4) -#define EXIF_INFO_EBV_NU I2C_REG(CAT_EXIF, CAT7_INFO_EBV_NU, 4) -#define EXIF_INFO_EBV_DE I2C_REG(CAT_EXIF, CAT7_INFO_EBV_DE, 4) -#define EXIF_INFO_ISO I2C_REG(CAT_EXIF, CAT7_INFO_ISO, 2) -#define EXIF_INFO_FLASH I2C_REG(CAT_EXIF, CAT7_INFO_FLASH, 2) -#define EXIF_INFO_SDR I2C_REG(CAT_EXIF, CAT7_INFO_SDR, 2) -#define EXIF_INFO_QVAL I2C_REG(CAT_EXIF, CAT7_INFO_QVAL, 2) +#define EXIF_INFO_EXPTIME_NU I2C_REG(CAT_EXIF, 0x00, 4) +#define EXIF_INFO_EXPTIME_DE I2C_REG(CAT_EXIF, 0x04, 4) +#define EXIF_INFO_TV_NU I2C_REG(CAT_EXIF, 0x08, 4) +#define EXIF_INFO_TV_DE I2C_REG(CAT_EXIF, 0x0c, 4) +#define EXIF_INFO_AV_NU I2C_REG(CAT_EXIF, 0x10, 4) +#define EXIF_INFO_AV_DE I2C_REG(CAT_EXIF, 0x14, 4) +#define EXIF_INFO_BV_NU I2C_REG(CAT_EXIF, 0x18, 4) +#define EXIF_INFO_BV_DE I2C_REG(CAT_EXIF, 0x1c, 4) +#define EXIF_INFO_EBV_NU I2C_REG(CAT_EXIF, 0x20, 4) +#define EXIF_INFO_EBV_DE I2C_REG(CAT_EXIF, 0x24, 4) +#define EXIF_INFO_ISO I2C_REG(CAT_EXIF, 0x28, 2) +#define EXIF_INFO_FLASH I2C_REG(CAT_EXIF, 0x2a, 2) +#define EXIF_INFO_SDR I2C_REG(CAT_EXIF, 0x2c, 2) +#define EXIF_INFO_QVAL I2C_REG(CAT_EXIF, 0x2e, 2) /* * Category 9 - Face Detection */ -#define CAT9_FD_CTL 0x00 - -#define FD_CTL I2C_REG(CAT_FD, CAT9_FD_CTL, 1) +#define FD_CTL I2C_REG(CAT_FD, 0x00, 1) #define BIT_FD_EN 0 #define BIT_FD_DRAW_FACE_FRAME 4 #define BIT_FD_DRAW_SMILE_LVL 6 @@ -314,62 +282,50 @@ /* * Category A - Lens Parameter */ -#define CATA_AF_MODE 0x01 -#define CATA_AF_EXECUTE 0x02 -#define CATA_AF_STATUS 0x03 -#define CATA_AF_VERSION 0x0a - -#define AF_MODE I2C_REG(CAT_LENS, CATA_AF_MODE, 1) +#define AF_MODE I2C_REG(CAT_LENS, 0x01, 1) #define REG_AF_NORMAL 0x00 /* Normal AF, one time */ #define REG_AF_MACRO 0x01 /* Macro AF, one time */ #define REG_AF_POWEROFF 0x07 -#define AF_EXECUTE I2C_REG(CAT_LENS, CATA_AF_EXECUTE, 1) +#define AF_EXECUTE I2C_REG(CAT_LENS, 0x02, 1) #define REG_AF_STOP 0x00 #define REG_AF_EXE_AUTO 0x01 #define REG_AF_EXE_CAF 0x02 -#define AF_STATUS I2C_REG(CAT_LENS, CATA_AF_STATUS, 1) +#define AF_STATUS I2C_REG(CAT_LENS, 0x03, 1) #define REG_AF_FAIL 0x00 #define REG_AF_SUCCESS 0x02 #define REG_AF_IDLE 0x04 #define REG_AF_BUSY 0x05 -#define AF_VERSION I2C_REG(CAT_LENS, CATA_AF_VERSION, 1) +#define AF_VERSION I2C_REG(CAT_LENS, 0x0a, 1) /* * Category B - CAPTURE Parameter */ -#define CATB_YUVOUT_MAIN 0x00 -#define CATB_MAIN_IMAGE_SIZE 0x01 -#define CATB_MCC_MODE 0x1d -#define CATB_WDR_EN 0x2c -#define CATB_LIGHT_CTRL 0x40 -#define CATB_FLASH_CTRL 0x41 - -#define CAPP_YUVOUT_MAIN I2C_REG(CAT_CAPT_PARM, CATB_YUVOUT_MAIN, 1) +#define CAPP_YUVOUT_MAIN I2C_REG(CAT_CAPT_PARM, 0x00, 1) #define REG_YUV422 0x00 #define REG_BAYER10 0x05 #define REG_BAYER8 0x06 #define REG_JPEG 0x10 -#define CAPP_MAIN_IMAGE_SIZE I2C_REG(CAT_CAPT_PARM, CATB_MAIN_IMAGE_SIZE, 1) +#define CAPP_MAIN_IMAGE_SIZE I2C_REG(CAT_CAPT_PARM, 0x01, 1) -#define CAPP_MCC_MODE I2C_REG(CAT_CAPT_PARM, CATB_MCC_MODE, 1) +#define CAPP_MCC_MODE I2C_REG(CAT_CAPT_PARM, 0x1d, 1) #define REG_MCC_OFF 0x00 #define REG_MCC_NORMAL 0x01 -#define CAPP_WDR_EN I2C_REG(CAT_CAPT_PARM, CATB_WDR_EN, 1) +#define CAPP_WDR_EN I2C_REG(CAT_CAPT_PARM, 0x2c, 1) #define REG_WDR_OFF 0x00 #define REG_WDR_ON 0x01 #define REG_WDR_AUTO 0x02 -#define CAPP_LIGHT_CTRL I2C_REG(CAT_CAPT_PARM, CATB_LIGHT_CTRL, 1) +#define CAPP_LIGHT_CTRL I2C_REG(CAT_CAPT_PARM, 0x40, 1) #define REG_LIGHT_OFF 0x00 #define REG_LIGHT_ON 0x01 #define REG_LIGHT_AUTO 0x02 -#define CAPP_FLASH_CTRL I2C_REG(CAT_CAPT_PARM, CATB_FLASH_CTRL, 1) +#define CAPP_FLASH_CTRL I2C_REG(CAT_CAPT_PARM, 0x41, 1) #define REG_FLASH_OFF 0x00 #define REG_FLASH_ON 0x01 #define REG_FLASH_AUTO 0x02 @@ -377,34 +333,29 @@ /* * Category C - CAPTURE Control */ -#define CATC_CAP_MODE 0x00 -#define CATC_CAP_SEL_FRAME 0x06 /* It determines Single or Multi */ -#define CATC_CAP_START 0x09 -#define CATC_CAP_IMAGE_SIZE 0x0d -#define CATC_CAP_THUMB_SIZE 0x11 - -#define CAPC_MODE I2C_REG(CAT_CAPT_CTRL, CATC_CAP_MODE, 1) +#define CAPC_MODE I2C_REG(CAT_CAPT_CTRL, 0x00, 1) #define REG_CAP_NONE 0x00 #define REG_CAP_ANTI_SHAKE 0x02 -#define CAPC_SEL_FRAME I2C_REG(CAT_CAPT_CTRL, CATC_CAP_SEL_FRAME, 1) +/* Select single- or multi-shot capture */ +#define CAPC_SEL_FRAME I2C_REG(CAT_CAPT_CTRL, 0x06, 1) -#define CAPC_START I2C_REG(CAT_CAPT_CTRL, CATC_CAP_START, 1) +#define CAPC_START I2C_REG(CAT_CAPT_CTRL, 0x09, 1) #define REG_CAP_START_MAIN 0x01 #define REG_CAP_START_THUMB 0x03 -#define CAPC_IMAGE_SIZE I2C_REG(CAT_CAPT_CTRL, CATC_CAP_IMAGE_SIZE, 4) -#define CAPC_THUMB_SIZE I2C_REG(CAT_CAPT_CTRL, CATC_CAP_THUMB_SIZE, 4) +#define CAPC_IMAGE_SIZE I2C_REG(CAT_CAPT_CTRL, 0x0d, 4) +#define CAPC_THUMB_SIZE I2C_REG(CAT_CAPT_CTRL, 0x11, 4) /* * Category F - Flash * * This mode provides functions about internal flash stuff and system startup. */ -#define CATF_CAM_START 0x12 /* It starts internal ARM core booting - * after power-up */ -#define FLASH_CAM_START I2C_REG(CAT_FLASH, CATF_CAM_START, 1) -#define REG_START_ARM_BOOT 0x01 +/* Starts internal ARM core booting after power-up */ +#define FLASH_CAM_START I2C_REG(CAT_FLASH, 0x12, 1) +#define REG_START_ARM_BOOT 0x01 /* write value */ +#define REG_IN_FLASH_MODE 0x00 /* read value */ #endif /* M5MOLS_REG_H */ |