static void qpnp_vib_enable(struct timed_output_dev *dev, int value) { struct qpnp_vib *vib = container_of(dev, struct qpnp_vib, timed_dev); unsigned long flags; retry: spin_lock_irqsave(&vib->lock, flags); if (hrtimer_try_to_cancel(&vib->vib_timer) < 0) { spin_unlock_irqrestore(&vib->lock, flags); cpu_relax(); goto retry; } printk(KERN_INFO "[VIB] enable=%d.\n", value); if (value == 0) vib->state = 0; else { value = (value > vib->timeout ? vib->timeout : value); vib->state = 1; hrtimer_start(&vib->vib_timer, ktime_set(value / 1000, (value % 1000) * 1000000), HRTIMER_MODE_REL); } qpnp_vib_set(vib, vib->state); spin_unlock_irqrestore(&vib->lock, flags); }
static int qpnp_vibrator_suspend(struct device *dev) { struct qpnp_vib *vib = dev_get_drvdata(dev); hrtimer_cancel(&vib->vib_timer); cancel_work_sync(&vib->work); /* turn-off vibrator */ qpnp_vib_set(vib, 0); return 0; }
static enum hrtimer_restart qpnp_vib_timer_func(struct hrtimer *timer) { struct qpnp_vib *vib = container_of(timer, struct qpnp_vib, vib_timer); unsigned long flags; spin_lock_irqsave(&vib->lock, flags); vib->state = 0; qpnp_vib_set(vib, vib->state); spin_unlock_irqrestore(&vib->lock, flags); return HRTIMER_NORESTART; }
static ssize_t qpnp_vib_attrs_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int tmp_vtg_level; unsigned long value; int ret = -EINVAL; struct qpnp_vib *vib = container_of(dev, struct qpnp_vib, sysfs_dev); if (kstrtoul(buf, 0, &value)) { dev_err(dev, "%s: Invalid value\n", __func__); goto err_out; } value /= QPNP_VIB_UV_PER_MV; if (value) { if (value < QPNP_VIB_MIN_LEVEL || value > QPNP_VIB_MAX_LEVEL) { dev_err(dev, "Invalid voltage level\n"); goto err_out; } } else { dev_err(dev, "Voltage level not specified\n"); goto err_out; } tmp_vtg_level = vib->vtg_level; vib->vtg_level = value; ret = qpnp_vib_set(vib, vib->state); if (ret) { dev_err(dev, "%s: qpnp_vib_set failed %d\n", __func__, ret); vib->vtg_level = tmp_vtg_level; goto err_out; } return count; err_out: return ret; }
static void qpnp_vib_update(struct work_struct *work) { struct qpnp_vib *vib = container_of(work, struct qpnp_vib, work); qpnp_vib_set(vib, vib->state); }