Hi Sakari,

Thanks for the patch.

On Monday 16 May 2011 15:00:39 Sakari Ailus wrote:
> This patch adds the driver for the adp1653 LED flash controller. This
> controller supports a high power led in flash and torch modes and an
> indicator light, sometimes also called privacy light.
> 
> The adp1653 is used on the Nokia N900.
> 
> Signed-off-by: Sakari Ailus <sakari.ai...@maxwell.research.nokia.com>
> Signed-off-by: Tuukka Toivonen <tuukka...@gmail.com>
> Signed-off-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
> Signed-off-by: David Cohen <daco...@gmail.com>

[snip]

> diff --git a/drivers/media/video/adp1653.c b/drivers/media/video/adp1653.c
> new file mode 100644
> index 0000000..92ea38b
> --- /dev/null
> +++ b/drivers/media/video/adp1653.c

[snip]

> +/* Write values into ADP1653 registers. */
> +static int adp1653_update_hw(struct adp1653_flash *flash)
> +{
> +     struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
> +     u8 out_sel;
> +     u8 config = 0;
> +     int rval;
> +
> +     out_sel = flash->indicator_intensity->val
> +             << ADP1653_REG_OUT_SEL_ILED_SHIFT;
> +
> +     switch (flash->led_mode->val) {
> +     case V4L2_FLASH_LED_MODE_NONE:
> +             break;
> +     case V4L2_FLASH_LED_MODE_FLASH:
> +             /* Flash mode, light on with strobe, duration from timer */
> +             config = ADP1653_REG_CONFIG_TMR_CFG;
> +             config |= TIMEOUT_US_TO_CODE(flash->flash_timeout->val)
> +                       << ADP1653_REG_CONFIG_TMR_SET_SHIFT;
> +             break;
> +     case V4L2_FLASH_LED_MODE_TORCH:
> +             /* Torch mode, light immediately on, duration indefinite */
> +             out_sel |= flash->torch_intensity->val
> +                        << ADP1653_REG_OUT_SEL_HPLED_SHIFT;
> +             break;
> +     }
> +
> +     rval = i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL, out_sel);

out_sel can be used uninitialized here.

> +     if (rval < 0)
> +             return rval;
> +
> +     rval = i2c_smbus_write_byte_data(client, ADP1653_REG_CONFIG, config);
> +     if (rval < 0)
> +             return rval;
> +
> +     return 0;
> +}

[snip]

> +static int adp1653_get_ctrl(struct v4l2_ctrl *ctrl)
> +{
> +     struct adp1653_flash *flash =
> +             container_of(ctrl->handler, struct adp1653_flash, ctrls);
> +     struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
> +     int fault;
> +     int rval;
> +
> +     fault = i2c_smbus_read_byte_data(client, ADP1653_REG_FAULT);
> +     if (IS_ERR_VALUE(fault))
> +             return fault;
> +
> +     /* Clear faults. */
> +     rval = i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL, 0);
> +     if (IS_ERR_VALUE(rval))
> +             return rval;

If several applications read controls, only one of them will be notified of 
faults. Shouldn't clearing the fault be handled explicitly by writing to a 
control ? I know this changes the API :-)

> +     /* Restore configuration. */
> +     rval = adp1653_update_hw(flash);
> +     if (IS_ERR_VALUE(rval))
> +             return rval;

Will that produce expected results ? For instance, if a fault was detected 
during flash strobe, won't it try to re-strobe the flash ? Shouldn't the user 
be required to explicitly re-strobe the flash or turn the torch (or indicator) 
on after a fault ? Once again this should be clarified in the API :-)

> +     ctrl->cur.val = 0;
> +
> +     if (fault & ADP1653_REG_FAULT_FLT_SCP)
> +             ctrl->cur.val |= V4L2_FLASH_FAULT_SHORT_CIRCUIT;
> +     if (fault & ADP1653_REG_FAULT_FLT_OT)
> +             ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_TEMPERATURE;
> +     if (fault & ADP1653_REG_FAULT_FLT_TMR)
> +             ctrl->cur.val |= V4L2_FLASH_FAULT_TIMEOUT;
> +     if (fault & ADP1653_REG_FAULT_FLT_OV)
> +             ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_VOLTAGE;
> +
> +     return 0;
> +}

[snip]

> +static int
> +adp1653_init_device(struct adp1653_flash *flash)
> +{
> +     struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
> +     int rval;
> +
> +     /* Clear FAULT register by writing zero to OUT_SEL */
> +     rval = i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL, 0);
> +     if (rval < 0) {
> +             dev_err(&client->dev, "failed writing fault register\n");
> +             return -EIO;
> +     }
> +
> +     /* Read FAULT register */
> +     rval = i2c_smbus_read_byte_data(client, ADP1653_REG_FAULT);
> +     if (rval < 0) {
> +             dev_err(&client->dev, "failed reading fault register\n");
> +             return -EIO;
> +     }
> +
> +     if ((rval & 0x0f) != 0) {
> +             dev_err(&client->dev, "device fault\n");

You could print the fault value, that could help debugging problems.

> +             return -EIO;
> +     }
> +
> +     mutex_lock(&flash->ctrls.lock);
> +     rval = adp1653_update_hw(flash);
> +     mutex_unlock(&flash->ctrls.lock);
> +     if (rval) {
> +             dev_err(&client->dev,
> +                     "adp1653_update_hw failed at %s\n", __func__);
> +             return -EIO;
> +     }
> +
> +     return 0;
> +}

[snip]

-- 
Regards,

Laurent Pinchart
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to