fixing LM3648 flash driver (v4l2) after testing LM3643EVM
[mlp-open-source/kernel.git] / drivers / media / i2c / lm3648.c
index 8beaa79af21ac867f52f17deb1d6314b1e5278eb..773e14e0aedd5ee5cc48554e0d85d44596da388e 100644 (file)
 #include <media/v4l2-device.h>
 
 /* registers definitions */
-#define REG_ENABLE             0x0c
-#define REG_TORCH_BR   0x05
+#define REG_ENABLE             0x01
 #define REG_FLASH_BR   0x03
+#define REG_TORCH_BR   0x05
 #define REG_FLASH_TOUT 0x08
 #define REG_FLAG1              0x0a
 #define REG_FLAG2              0x0b
 #define REG_STROBE_SRC 0x01
 
-#define MASK_ENABLE            0x03
+#define MASK_ENABLE            0x0c
 #define MASK_TORCH_BR  0x7f
 #define MASK_FLASH_BR  0x3f
 #define MASK_FLASH_TOUT        0x0f
@@ -76,6 +76,7 @@ struct lm3648_flash {
 
        struct v4l2_ctrl_handler ctrls_led;
        struct v4l2_subdev subdev_led;
+struct v4l2_device v4l2_dev;
 
        u8 mode_reg;
 };
@@ -150,7 +151,6 @@ static int lm3648_set_ctrl(struct v4l2_ctrl *ctrl)
 
        switch (ctrl->id) {
        case V4L2_CID_FLASH_LED_MODE:
-
                if (ctrl->val != V4L2_FLASH_LED_MODE_FLASH)
                        return lm3648_mode_ctrl(flash, ctrl->val);
                /* switch to SHDN mode before flash strobe on */
@@ -162,7 +162,6 @@ static int lm3648_set_ctrl(struct v4l2_ctrl *ctrl)
                                          (ctrl->val) << 5);
 
        case V4L2_CID_FLASH_STROBE:
-
                /* read and check current mode of chip to start flash */
                rval = regmap_read(flash->regmap, REG_ENABLE, &reg_val);
                if (rval < 0 || ((reg_val & MASK_ENABLE) != MODE_SHDN))
@@ -171,7 +170,6 @@ static int lm3648_set_ctrl(struct v4l2_ctrl *ctrl)
                return lm3648_mode_ctrl(flash, V4L2_FLASH_LED_MODE_FLASH);
 
        case V4L2_CID_FLASH_STROBE_STOP:
-
                /*
                 * flash mode will be turned automatically
                 * from FLASH mode to SHDN mode after flash duration timeout
@@ -221,7 +219,7 @@ static int lm3648_init_controls(struct lm3648_flash *flash)
        v4l2_ctrl_handler_init(hdl, 8);
        /* flash mode */
        v4l2_ctrl_new_std_menu(hdl, ops, V4L2_CID_FLASH_LED_MODE,
-                              V4L2_FLASH_LED_MODE_TORCH, ~0x7,
+                              V4L2_FLASH_LED_MODE_IR, ~0x7,
                               V4L2_FLASH_LED_MODE_NONE);
 
        /* flash source */
@@ -237,7 +235,8 @@ static int lm3648_init_controls(struct lm3648_flash *flash)
        v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_TIMEOUT,
                          LM3648_FLASH_TOUT_MIN,
                          LM3648_FLASH_TOUT_MAX,
-                         LM3648_FLASH_TOUT_LOW_STEP, flash->pdata->flash_timeout);
+                         LM3648_FLASH_TOUT_LOW_STEP,
+                         LM3648_FLASH_TOUT_MAX);
 
        /* max flash current */
        v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_INTENSITY,
@@ -255,10 +254,14 @@ static int lm3648_init_controls(struct lm3648_flash *flash)
 
        /* fault */
        fault = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_FAULT, 0,
-                                 V4L2_FLASH_FAULT_OVER_VOLTAGE
-                                 | V4L2_FLASH_FAULT_OVER_TEMPERATURE
+                                 V4L2_FLASH_FAULT_TIMEOUT
                                  | V4L2_FLASH_FAULT_SHORT_CIRCUIT
-                                 | V4L2_FLASH_FAULT_TIMEOUT, 0, 0);
+                                 | V4L2_FLASH_FAULT_UNDER_VOLTAGE
+                                 | V4L2_FLASH_FAULT_INPUT_VOLTAGE
+                                 | V4L2_FLASH_FAULT_OVER_CURRENT
+                                 | V4L2_FLASH_FAULT_OVER_TEMPERATURE
+                                 | V4L2_FLASH_FAULT_LED_OVER_TEMPERATURE
+                                 | V4L2_FLASH_FAULT_OVER_VOLTAGE, 0, 0);
        if (fault != NULL)
                fault->flags |= V4L2_CTRL_FLAG_VOLATILE;
 
@@ -285,6 +288,7 @@ static int lm3648_subdev_init(struct lm3648_flash *flash)
        struct i2c_client *client = to_i2c_client(flash->dev);
        int rval;
 
+rval = v4l2_device_register(&client->dev, &flash->v4l2_dev);
        v4l2_i2c_subdev_init(&flash->subdev_led, client, &lm3648_ops);
        flash->subdev_led.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
        strcpy(flash->subdev_led.name, LM3648_NAME);
@@ -295,6 +299,8 @@ static int lm3648_subdev_init(struct lm3648_flash *flash)
        if (rval < 0)
                goto err_out;
        flash->subdev_led.entity.type = MEDIA_ENT_T_V4L2_SUBDEV_FLASH;
+rval = v4l2_device_register_subdev(&flash->v4l2_dev, &flash->subdev_led);
+rval = v4l2_device_register_subdev_nodes(&flash->v4l2_dev);
        return rval;
 
 err_out:
@@ -307,11 +313,17 @@ static int lm3648_init_device(struct lm3648_flash *flash)
        unsigned int reg_val;
        int rval;
 
+       /* LED Enable - on */
+       rval = regmap_update_bits(flash->regmap, REG_ENABLE, 0x03, 0x03);
+       rval |= regmap_update_bits(flash->regmap, REG_FLASH_BR, 0xc0, 0x80);
+       rval |= regmap_update_bits(flash->regmap, REG_TORCH_BR, 0x80, 0x80);
+       if (rval < 0)
+               return rval;
        /* read the value of mode register to reduce redundant i2c accesses */
        rval = regmap_read(flash->regmap, REG_ENABLE, &reg_val);
        if (rval < 0)
                return rval;
-       flash->mode_reg = reg_val & 0xfc;
+       flash->mode_reg = reg_val & 0xf3;
 
        /* output disable */
        rval = lm3648_mode_ctrl(flash, V4L2_FLASH_LED_MODE_NONE);