Re: [PATCH 3/3] adp1653: Add driver for LED flash controller

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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.ailus@xxxxxxxxxxxxxxxxxxxxxxxxxx>
> Signed-off-by: Tuukka Toivonen <tuukkat76@xxxxxxxxx>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx>
> Signed-off-by: David Cohen <dacohen@xxxxxxxxx>

[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 majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux