예제 #1
0
static int lm3556_s_flash_mode(struct v4l2_subdev *sd, u32 val)
{
	int ret;
	enum atomisp_flash_mode new_mode = (enum atomisp_flash_mode)val;
	struct lm3556_priv *p_lm3556_priv = to_lm3556_priv(sd);

	pr_debug("%s %d", __func__, val);

	switch (new_mode) {
	case ATOMISP_FLASH_MODE_OFF:
		/* FIXME: controller isn't setting flash mode for flash
		ret = set_reg_field(sd, &enable, LM3556_MODE_SHUTDOWN);
		break;
		*/
	case ATOMISP_FLASH_MODE_FLASH:
		ret = set_reg_field(sd, &enable, LM3556_MODE_FLASH);
		break;
	case ATOMISP_FLASH_MODE_INDICATOR:
		ret = set_reg_field(sd, &enable, LM3556_MODE_INDICATOR);
		break;
	case ATOMISP_FLASH_MODE_TORCH:
		ret = set_reg_field(sd, &enable, LM3556_MODE_TORCH);
		break;
	default:
		ret = -EINVAL;
	}
	if (ret == 0)
		p_lm3556_priv->mode = new_mode;
	return ret;
}
예제 #2
0
static int lm3554_s_flash_mode(struct v4l2_subdev *sd, u32 val)
{
	int ret;
	enum atomisp_flash_mode new_mode = (enum atomisp_flash_mode)val;
	struct lm3554_priv *p_lm3554_priv = to_lm3554_priv(sd);

	switch (new_mode) {
	case ATOMISP_FLASH_MODE_OFF:
		if (p_lm3554_priv->mode == ATOMISP_FLASH_MODE_FLASH) {
			ret = set_reg_field(sd, &flash_mode,
					    LM3554_MODE_SHUTDOWN);
		} else {
			ret = set_reg_field(sd, &torch_mode,
					    LM3554_MODE_SHUTDOWN);
		}
		break;
	case ATOMISP_FLASH_MODE_FLASH:
		ret = set_reg_field(sd, &flash_mode, LM3554_MODE_FLASH);
		break;
	case ATOMISP_FLASH_MODE_INDICATOR:
		ret = set_reg_field(sd, &flash_mode, LM3554_MODE_INDICATOR);
		break;
	case ATOMISP_FLASH_MODE_TORCH:
		ret = set_reg_field(sd, &torch_mode, LM3554_MODE_TORCH);
		break;
	default:
		ret = -EINVAL;
	}
	if (ret == 0)
		p_lm3554_priv->mode = new_mode;
	return ret;
}
예제 #3
0
static int lm3554_s_flash_strobe(struct v4l2_subdev *sd, u32 val)
{
	int ret, timer_pending;
	struct i2c_client *client = v4l2_get_subdevdata(sd);
	struct lm3554_priv *p_lm3554_priv = to_lm3554_priv(sd);
	struct camera_flash_platform_data *pdata = p_lm3554_priv->platform_data;

	/*
	 * An abnormal high flash current is observed when strobe off the
	 * flash. Workaround here is firstly set flash current to lower level,
	 * wait a short moment, and then strobe off the flash.
	 */

	timer_pending = del_timer_sync(&p_lm3554_priv->flash_off_delay);

	/* Flash off */
	if (!val) {
		/* set current to 70mA and wait a while */
		ret = set_reg_field(sd, &flash_current, 0);
		if (ret < 0)
			goto err;
		mod_timer(&p_lm3554_priv->flash_off_delay,
			  jiffies + msecs_to_jiffies(LM3554_TIMER_DELAY));
		return 0;
	}

	/* Flash on */

	/*
	 * If timer is killed before run, flash is not strobe off,
	 * so must strobe off here
	 */
	if (timer_pending != 0) {
		ret = set_gpio_output(pdata->gpio_strobe, "flash", 0);
		if (ret < 0)
			goto err;
	}

	/* Restore flash current settings */
	ret = set_reg_field(sd, &flash_current,
			    (u8)p_lm3554_priv->intensity);
	if (ret < 0)
		goto err;

	/* Strobe on Flash */
	ret = set_gpio_output(pdata->gpio_strobe, "flash", val);
	if (ret < 0)
		goto err;

	return 0;
err:
	dev_err(&client->dev, "failed to generate flash strobe (%d)\n",
		ret);
	return ret;
}
예제 #4
0
static int lm3554_detect(struct i2c_client *client)
{
	s32 status;
	struct i2c_adapter *adapter = client->adapter;
	struct v4l2_subdev *sd = i2c_get_clientdata(client);
	struct lm3554_priv *p_lm3554_priv = to_lm3554_priv(sd);
	struct camera_flash_platform_data *pdata = p_lm3554_priv->platform_data;
	int ret;

	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
		dev_err(&client->dev, "lm3554_detect i2c error\n");
		return -ENODEV;
	}

	lm3554_hw_reset(client);

	ret = set_gpio_output(pdata->gpio_strobe, "flash", 0);
	if (ret < 0)
		goto fail;

	ret = set_gpio_output(pdata->gpio_torch, "torch", 0);
	if (ret < 0)
		goto fail;

	/* Set to TX2 mode, then ENVM/TX2 pin is a power
	 * amplifier sync input:
	 * ENVM/TX pin asserted, flash forced into torch;
	 * ENVM/TX pin desserted, flash set back;
	 */
	ret = set_reg_field(sd, &envm_tx2, 1);
	if (ret < 0)
		goto fail;

	ret = set_reg_field(sd, &tx2_polarity, 0);
	if (ret < 0)
		goto fail;

	/* set peak current limit to be 1000mA */
	ret = set_reg_field(sd, &current_limit, 0);
	if (ret < 0)
		goto fail;

	/* clear the flags register */
	ret = lm3554_g_flash_status(sd, &status);
	if (ret < 0)
		goto fail;

	dev_dbg(&client->dev, "Successfully detected lm3554 LED flash\n");
	return 0;

fail:
	dev_err(&client->dev, "gpio request/direction_output fail");
	return ret;
}
예제 #5
0
static int lm3556_detect(struct i2c_client *client)
{
	u32 status;
	struct i2c_adapter *adapter = client->adapter;
	struct v4l2_subdev *sd = i2c_get_clientdata(client);
	int ret;

	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
		dev_err(&client->dev, "lm3556_detect i2c error\n");
		return -ENODEV;
	}

	lm3556_hw_reset(client);

	ret = gpio_direction_output(GP_LM3556_FLASH_STROBE, 0);
	if (ret < 0)
		goto fail;

	ret = set_reg_field(sd, &configure, 0xF8);
	if (ret < 0)
		goto fail;

	/* clear the flags register */
	ret = lm3556_g_flash_status(sd, &status);
	if (ret < 0)
		goto fail;

	dev_dbg(&client->dev, "Successfully detected lm3556 LED flash\n");
	return 0;

fail:
	dev_err(&client->dev, "lm3556_detect fail........");
	return ret;
}
예제 #6
0
static int lm3556_s_flash_strobe(struct v4l2_subdev *sd, u32 val)
{
	int ret;
	struct i2c_client *client = v4l2_get_subdevdata(sd);
	struct lm3556_priv *p_lm3556_priv = to_lm3556_priv(sd);

	pr_debug("%s %d", __func__, val);

	ret = gpio_direction_output(GP_LM3556_FLASH_STROBE, val);
	if (ret < 0) {
		dev_err(&client->dev, "failed to generate flash strobe (%d)\n",
			ret);
		return ret;
	}

	if (val == 0 && p_lm3556_priv->mode == ATOMISP_FLASH_MODE_OFF) {
		/* Driver requires mode bits to get reset after flash event */
		usleep_range(5000, 5000);
		ret =  set_reg_field(sd, &enable, LM3556_MODE_FLASH);
		if (ret < 0) {
			dev_err(&client->dev, "failed to reset flash mode"
					"(%d)\n", ret);
			return ret;
		}
	}

	return 0;
}
예제 #7
0
static int lm3554_s_indicator_intensity(struct v4l2_subdev *sd, u32 intensity)
{
	intensity = LM3554_CLAMP_PERCENTAGE(intensity);
	intensity = LM3554_PERCENT_TO_VALUE(intensity, LM3554_INDICATOR_STEP);

	return set_reg_field(sd, &indicator_current, (u8)intensity);
}
예제 #8
0
static int lm3554_s_torch_intensity(struct v4l2_subdev *sd, u32 intensity)
{
	intensity = LM3554_CLAMP_PERCENTAGE(intensity);
	intensity = LM3554_PERCENT_TO_VALUE(intensity, LM3554_TORCH_STEP);

	return set_reg_field(sd, &torch_current, (u8)intensity);
}
예제 #9
0
static int lm3556_s_indicator_intensity(struct v4l2_subdev *sd, u32 intensity)
{
	pr_debug("%s %d\n", __func__, intensity);

	intensity = LM3556_CLAMP_PERCENTAGE(intensity);
	intensity = LM3556_PERCENT_TO_VALUE(intensity, LM3556_INDICATOR_STEP);

	return set_reg_field(sd, &indicator_current, (u8)intensity);
}
예제 #10
0
static int lm3554_s_flash_timeout(struct v4l2_subdev *sd, u32 val)
{
	struct lm3554_priv *p_lm3554 = to_lm3554_priv(sd);

	val = clamp(val, LM3554_MIN_TIMEOUT, LM3554_MAX_TIMEOUT);
	p_lm3554->timeout = val;

	val = val / LM3554_TIMEOUT_STEPSIZE - 1;
	return set_reg_field(sd, &flash_timeout, (u8)val);
}
예제 #11
0
static int lm3554_s_flash_intensity(struct v4l2_subdev *sd, u32 intensity)
{
	struct lm3554_priv *p_lm3554_priv = to_lm3554_priv(sd);

	intensity = LM3554_CLAMP_PERCENTAGE(intensity);
	intensity = LM3554_PERCENT_TO_VALUE(intensity, LM3554_FLASH_STEP);

	p_lm3554_priv->intensity = intensity;

	return set_reg_field(sd, &flash_current, (u8)intensity);
}
예제 #12
0
static int lm3556_s_flash_intensity(struct v4l2_subdev *sd, u32 intensity)
{
	pr_debug("%s %d\n", __func__, intensity);

	intensity = LM3556_CLAMP_PERCENTAGE(intensity);
	intensity = LM3556_PERCENT_TO_VALUE(intensity, LM3556_FLASH_STEP);

	if (intensity > LM3556_FLASH_MAX_LVL)
		intensity = LM3556_FLASH_MAX_LVL;

	return set_reg_field(sd, &flash_current, (u8)intensity);
}
예제 #13
0
static int lm3556_s_flash_timeout(struct v4l2_subdev *sd, u32 val)
{
	struct lm3556_priv *p_lm3556 = to_lm3556_priv(sd);

	pr_debug("%s %d\n", __func__, val);

	val = clamp(val, LM3556_MIN_TIMEOUT, LM3556_MAX_TIMEOUT);
	p_lm3556->timeout = val;

	val = val / LM3556_TIMEOUT_STEPSIZE - 1;
	return set_reg_field(sd, &flash_timeout, (u8)val);
}