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; }
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; }
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; }
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, ¤t_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; }
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; }
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; }
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); }
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); }
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); }
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); }
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); }
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); }
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); }