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_get_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; ctrl->cur.val = 0; if (flash->fault & ADP1653_REG_FAULT_FLT_SCP) ctrl->cur.val |= V4L2_FLASH_FAULT_SHORT_CIRCUIT; if (flash->fault & ADP1653_REG_FAULT_FLT_OT) ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_TEMPERATURE; if (flash->fault & ADP1653_REG_FAULT_FLT_TMR) ctrl->cur.val |= V4L2_FLASH_FAULT_TIMEOUT; if (flash->fault & ADP1653_REG_FAULT_FLT_OV) ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_VOLTAGE; flash->fault = 0; 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_ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc) { struct adp1653_flash *flash = s->priv; switch (vc->id) { case V4L2_CID_FLASH_TIMEOUT: vc->value = flash->flash_timeout; break; case V4L2_CID_FLASH_INTENSITY: vc->value = flash->flash_intensity; break; case V4L2_CID_TORCH_INTENSITY: vc->value = flash->torch_intensity; break; case V4L2_CID_INDICATOR_INTENSITY: vc->value = flash->indicator_intensity; break; case V4L2_CID_FLASH_ADP1653_FAULT_SCP: vc->value = (adp1653_get_fault(s) & ADP1653_REG_FAULT_FLT_SCP) != 0; break; case V4L2_CID_FLASH_ADP1653_FAULT_OT: vc->value = (adp1653_get_fault(s) & ADP1653_REG_FAULT_FLT_OT) != 0; break; case V4L2_CID_FLASH_ADP1653_FAULT_TMR: vc->value = (adp1653_get_fault(s) & ADP1653_REG_FAULT_FLT_TMR) != 0; break; case V4L2_CID_FLASH_ADP1653_FAULT_OV: vc->value = (adp1653_get_fault(s) & ADP1653_REG_FAULT_FLT_OV) != 0; break; default: return -EINVAL; } return 0; }