static int adp1653_get_fault(struct adp1653_flash *flash) { 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; flash->fault |= fault; if (!flash->fault) return 0; /* Clear faults. */ rval = i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL, 0); if (IS_ERR_VALUE(rval)) return rval; flash->led_mode->val = V4L2_FLASH_LED_MODE_NONE; rval = adp1653_update_hw(flash); if (IS_ERR_VALUE(rval)) return rval; return flash->fault; }
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; } mutex_lock(&flash->ctrls.lock); /* Reset faults before reading new ones. */ flash->fault = 0; rval = adp1653_get_fault(flash); mutex_unlock(&flash->ctrls.lock); if (rval > 0) { dev_err(&client->dev, "faults detected: 0x%1.1x\n", rval); 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; }
static int adp1653_set_ctrl(struct v4l2_ctrl *ctrl) { struct adp1653_flash *flash = container_of(ctrl->handler, struct adp1653_flash, ctrls); int rval; rval = adp1653_get_fault(flash); if (IS_ERR_VALUE(rval)) return rval; if ((rval & (ADP1653_REG_FAULT_FLT_SCP | ADP1653_REG_FAULT_FLT_OT | ADP1653_REG_FAULT_FLT_OV)) && (ctrl->id == V4L2_CID_FLASH_STROBE || ctrl->id == V4L2_CID_FLASH_TORCH_INTENSITY || ctrl->id == V4L2_CID_FLASH_LED_MODE)) return -EBUSY; switch (ctrl->id) { case V4L2_CID_FLASH_STROBE: return adp1653_strobe(flash, 1); case V4L2_CID_FLASH_STROBE_STOP: return adp1653_strobe(flash, 0); } return adp1653_update_hw(flash); }
static int adp1653_strobe(struct v4l2_int_device *s) { struct adp1653_flash *flash = s->priv; int rval; if (flash->torch_intensity > 0) { /* Disabling torch enables flash in update_hw() */ flash->torch_intensity = 0; rval = adp1653_update_hw(s); if (rval) return rval; } if (flash->platform_data->strobe) { /* Hardware-specific strobe using I/O pin */ return flash->platform_data->strobe(s); } else { /* Software strobe using i2c */ rval = i2c_smbus_write_byte_data(flash->i2c_client, ADP1653_REG_SW_STROBE, ADP1653_REG_SW_STROBE_SW_STROBE); if (rval) return rval; rval = i2c_smbus_write_byte_data(flash->i2c_client, ADP1653_REG_SW_STROBE, 0); return rval; } }
static int adp1653_ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc) { struct adp1653_flash *flash = s->priv; int ctrl; int *value; switch (vc->id) { case V4L2_CID_FLASH_STROBE: return adp1653_strobe(s); case V4L2_CID_FLASH_TIMEOUT: ctrl = CTRL_CAMERA_FLASH_TIMEOUT; value = &flash->flash_timeout; break; case V4L2_CID_FLASH_INTENSITY: ctrl = CTRL_CAMERA_FLASH_INTENSITY; value = &flash->flash_intensity; break; case V4L2_CID_TORCH_INTENSITY: ctrl = CTRL_CAMERA_FLASH_TORCH_INTENSITY; value = &flash->torch_intensity; break; case V4L2_CID_INDICATOR_INTENSITY: ctrl = CTRL_CAMERA_FLASH_INDICATOR_INTENSITY; value = &flash->indicator_intensity; break; default: return -EINVAL; } if (vc->value < adp1653_ctrls[ctrl].minimum) vc->value = adp1653_ctrls[ctrl].minimum; if (vc->value > adp1653_ctrls[ctrl].maximum) vc->value = adp1653_ctrls[ctrl].maximum; vc->value = (vc->value - adp1653_ctrls[ctrl].minimum + (adp1653_ctrls[ctrl].step >> 1)) / adp1653_ctrls[ctrl].step; vc->value = vc->value * adp1653_ctrls[ctrl].step + adp1653_ctrls[ctrl].minimum; *value = vc->value; return adp1653_update_hw(s); }
static int adp1653_init_device(struct v4l2_int_device *s) { struct adp1653_flash *flash = s->priv; int rval; /* Clear FAULT register by writing zero to OUT_SEL */ rval = i2c_smbus_write_byte_data(flash->i2c_client, ADP1653_REG_OUT_SEL, 0); if (rval < 0) { dev_err(&flash->i2c_client->dev, "failed writing fault register\n"); return -ENODEV; } /* Read FAULT register */ rval = i2c_smbus_read_byte_data(flash->i2c_client, ADP1653_REG_FAULT); if (rval < 0) { dev_err(&flash->i2c_client->dev, "failed reading fault register\n"); return -ENODEV; } if ((rval & 0x0f) != 0) { dev_err(&flash->i2c_client->dev, "device fault\n"); return -ENODEV; } rval = adp1653_update_hw(s); if (rval) { dev_err(&flash->i2c_client->dev, "adp1653_update_hw failed at adp1653_init_device\n"); return -ENODEV; } return 0; }