staticbool da7280_volatile_register(struct device *dev, unsignedint reg)
{ switch (reg) { case DA7280_IRQ_EVENT1: case DA7280_IRQ_EVENT_WARNING_DIAG: case DA7280_IRQ_EVENT_SEQ_DIAG: case DA7280_IRQ_STATUS1: case DA7280_TOP_CTL1: returntrue; default: returnfalse;
}
}
staticint da7280_haptic_mem_update(struct da7280_haptic *haptics)
{ unsignedint val; int error;
/* The patterns should be updated when haptic is not working */
error = regmap_read(haptics->regmap, DA7280_IRQ_STATUS1, &val); if (error) return error; if (val & DA7280_STA_WARNING_MASK) {
dev_warn(haptics->dev, "Warning! Please check HAPTIC status.\n"); return -EBUSY;
}
/* Patterns are not updated if the lock bit is enabled */
val = 0;
error = regmap_read(haptics->regmap, DA7280_MEM_CTL2, &val); if (error) return error; if (~val & DA7280_WAV_MEM_LOCK_MASK) {
dev_warn(haptics->dev, "Please unlock the bit first\n"); return -EACCES;
}
/* Set to Inactive mode to make sure safety */
error = regmap_update_bits(haptics->regmap,
DA7280_TOP_CTL1,
DA7280_OPERATION_MODE_MASK, 0); if (error) return error;
error = regmap_read(haptics->regmap, DA7280_MEM_CTL1, &val); if (error) return error;
return regmap_bulk_write(haptics->regmap, val, haptics->snp_mem,
DA7280_SNP_MEM_MAX - val + 1);
}
error = pwm_apply_might_sleep(haptics->pwm_dev, &state); if (error)
dev_err(haptics->dev, "Failed to apply pwm state: %d\n", error);
return error;
}
staticvoid da7280_haptic_activate(struct da7280_haptic *haptics)
{ int error;
if (haptics->active) return;
switch (haptics->op_mode) { case DA7280_DRO_MODE: /* the valid range check when acc_en is enabled */ if (haptics->acc_en && haptics->level > 0x7F)
haptics->level = 0x7F; elseif (haptics->level > 0xFF)
haptics->level = 0xFF;
/* Set level as a % of ACTUATOR_NOMMAX (nommax) */
error = regmap_write(haptics->regmap, DA7280_TOP_CTL2,
haptics->level); if (error) {
dev_err(haptics->dev, "Failed to set level to %d: %d\n",
haptics->level, error); return;
} break;
case DA7280_PWM_MODE: if (da7280_haptic_set_pwm(haptics, true)) return; break;
case DA7280_RTWM_MODE: /* *ThepatternwillbeplayedbythePS_SEQ_IDandthe *PS_SEQ_LOOP
*/ break;
case DA7280_ETWM_MODE: /* *ThepatternwillbeplayedbytheGPI[N]state, *GPI(N)_SEQUENCE_IDandthePS_SEQ_LOOP.Seethe *datasheetforthedetails.
*/ break;
default:
dev_err(haptics->dev, "Invalid op mode %d\n", haptics->op_mode); return;
}
error = regmap_update_bits(haptics->regmap,
DA7280_TOP_CTL1,
DA7280_OPERATION_MODE_MASK,
haptics->op_mode); if (error) {
dev_err(haptics->dev, "Failed to set operation mode: %d", error); return;
}
if (haptics->op_mode == DA7280_PWM_MODE ||
haptics->op_mode == DA7280_RTWM_MODE) {
error = regmap_update_bits(haptics->regmap,
DA7280_TOP_CTL1,
DA7280_SEQ_START_MASK,
DA7280_SEQ_START_MASK); if (error) {
dev_err(haptics->dev, "Failed to start sequence: %d\n", error); return;
}
}
haptics->active = true;
}
staticvoid da7280_haptic_deactivate(struct da7280_haptic *haptics)
{ int error;
if (!haptics->active) return;
/* Set to Inactive mode */
error = regmap_update_bits(haptics->regmap,
DA7280_TOP_CTL1,
DA7280_OPERATION_MODE_MASK, 0); if (error) {
dev_err(haptics->dev, "Failed to clear operation mode: %d", error); return;
}
switch (haptics->op_mode) { case DA7280_DRO_MODE:
error = regmap_write(haptics->regmap,
DA7280_TOP_CTL2, 0); if (error) {
dev_err(haptics->dev, "Failed to disable DRO mode: %d\n", error); return;
} break;
case DA7280_PWM_MODE: if (da7280_haptic_set_pwm(haptics, false)) return; break;
case DA7280_RTWM_MODE: case DA7280_ETWM_MODE:
error = regmap_update_bits(haptics->regmap,
DA7280_TOP_CTL1,
DA7280_SEQ_START_MASK, 0); if (error) {
dev_err(haptics->dev, "Failed to disable RTWM/ETWM mode: %d\n",
error); return;
} break;
default:
dev_err(haptics->dev, "Invalid op mode %d\n", haptics->op_mode); return;
}
haptics->active = false;
}
staticvoid da7280_haptic_work(struct work_struct *work)
{ struct da7280_haptic *haptics =
container_of(work, struct da7280_haptic, work); int val = haptics->val;
if (val)
da7280_haptic_activate(haptics); else
da7280_haptic_deactivate(haptics);
}
staticint da7280_haptics_upload_effect(struct input_dev *dev, struct ff_effect *effect, struct ff_effect *old)
{ struct da7280_haptic *haptics = input_get_drvdata(dev);
s16 data[DA7280_SNP_MEM_SIZE] = { 0 }; unsignedint val; int tmp, i, num; int error;
/* The effect should be uploaded when haptic is not working */ if (haptics->active) return -EBUSY;
switch (effect->type) { /* DRO/PWM modes support this type */ case FF_CONSTANT:
haptics->op_mode = haptics->const_op_mode; if (haptics->op_mode == DA7280_DRO_MODE) {
tmp = effect->u.constant.level * 254;
haptics->level = tmp / 0x7FFF; break;
}
/* RTWM/ETWM modes support this type */ case FF_PERIODIC: if (effect->u.periodic.waveform != FF_CUSTOM) {
dev_err(haptics->dev, "Device can only accept FF_CUSTOM waveform\n"); return -EINVAL;
}
/* If no property, set to zero as default is to do nothing. */
haptics->ps_seq_id = 0;
error = device_property_read_u32(dev, "dlg,ps-seq-id", &val); if (!error && val <= DA7280_SEQ_ID_MAX)
haptics->ps_seq_id = val;
haptics->ps_seq_loop = 0;
error = device_property_read_u32(dev, "dlg,ps-seq-loop", &val); if (!error && val <= DA7280_SEQ_LOOP_MAX)
haptics->ps_seq_loop = val;
/* GPI0~2 Control */ for (i = 0; i <= DA7280_GPI_SEQ_ID_MAX; i++) {
gpi_str1[7] = '0' + i;
haptics->gpi_ctl[i].seq_id = DA7280_GPI_SEQ_ID_DFT + i;
error = device_property_read_u32 (dev, gpi_str1, &val); if (!error && val <= DA7280_SEQ_ID_MAX)
haptics->gpi_ctl[i].seq_id = val;
if (events[0] & DA7280_E_SEQ_FAULT_MASK) { /* *Stopfirstifhapticisactive,otherwise,thefaultmay *happencontinuallyeventhoughthebitiscleared.
*/
error = regmap_update_bits(haptics->regmap, DA7280_TOP_CTL1,
DA7280_OPERATION_MODE_MASK, 0); if (error)
dev_err(dev, "failed to clear op mode on fault: %d\n",
error);
}
if (events[0] & DA7280_E_SEQ_DONE_MASK)
haptics->active = false;
if (events[0] & DA7280_E_WARNING_MASK) { if (events[1] & DA7280_E_LIM_DRIVE_MASK ||
events[1] & DA7280_E_LIM_DRIVE_ACC_MASK)
dev_warn(dev, "Please reduce the driver level\n"); if (events[1] & DA7280_E_MEM_TYPE_MASK)
dev_warn(dev, "Please check the mem data format\n"); if (events[1] & DA7280_E_OVERTEMP_WARN_MASK)
dev_warn(dev, "Over-temperature warning\n");
}
if (events[0] & DA7280_E_SEQ_FAULT_MASK) { if (events[2] & DA7280_E_SEQ_ID_FAULT_MASK)
dev_info(dev, "Please reload PS_SEQ_ID & mem data\n"); if (events[2] & DA7280_E_MEM_FAULT_MASK)
dev_info(dev, "Please reload the mem data\n"); if (events[2] & DA7280_E_PWM_FAULT_MASK)
dev_info(dev, "Please restart PWM interface\n");
}
out: return IRQ_HANDLED;
}
staticint da7280_init(struct da7280_haptic *haptics)
{ unsignedint val = 0;
u32 v2i_factor; int error, i;
u8 mask = 0;
/* *IfdevicetypeisDA7280_DEV_MAXthensimplyusecurrently *programmedmode.
*/ if (haptics->dev_type == DA7280_DEV_MAX) {
error = regmap_read(haptics->regmap, DA7280_TOP_CFG1, &val); if (error) goto out_err;
haptics->dev_type = val & DA7280_ACTUATOR_TYPE_MASK ?
DA7280_ERM_COIN : DA7280_LRA;
}
/* Apply user settings */ if (haptics->dev_type == DA7280_LRA &&
haptics->resonant_freq_l != DA7280_SKIP_INIT) {
error = regmap_write(haptics->regmap, DA7280_FRQ_LRA_PER_H,
haptics->resonant_freq_h); if (error) goto out_err;
error = regmap_write(haptics->regmap, DA7280_FRQ_LRA_PER_L,
haptics->resonant_freq_l); if (error) goto out_err;
} elseif (haptics->dev_type == DA7280_ERM_COIN) {
error = regmap_update_bits(haptics->regmap, DA7280_TOP_INT_CFG1,
DA7280_BEMF_FAULT_LIM_MASK, 0); if (error) goto out_err;
mask = DA7280_TST_CALIB_IMPEDANCE_DIS_MASK |
DA7280_V2I_FACTOR_FREEZE_MASK;
val = DA7280_TST_CALIB_IMPEDANCE_DIS_MASK |
DA7280_V2I_FACTOR_FREEZE_MASK;
error = regmap_update_bits(haptics->regmap, DA7280_TOP_CFG4,
mask, val); if (error) goto out_err;
if (!client->irq) {
dev_err(dev, "No IRQ configured\n"); return -EINVAL;
}
haptics = devm_kzalloc(dev, sizeof(*haptics), GFP_KERNEL); if (!haptics) return -ENOMEM;
haptics->dev = dev;
da7280_parse_properties(dev, haptics);
if (haptics->const_op_mode == DA7280_PWM_MODE) {
haptics->pwm_dev = devm_pwm_get(dev, NULL);
error = PTR_ERR_OR_ZERO(haptics->pwm_dev); if (error) { if (error != -EPROBE_DEFER)
dev_err(dev, "Unable to request PWM: %d\n",
error); return error;
}
/* Sync up PWM state and ensure it is off. */
pwm_init_state(haptics->pwm_dev, &state);
state.enabled = false;
error = pwm_apply_might_sleep(haptics->pwm_dev, &state); if (error) {
dev_err(dev, "Failed to apply PWM state: %d\n", error); return error;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.