static void vibra_play_work(struct work_struct *work) { struct vibra_info *info = container_of(work, struct vibra_info, play_work); int dir; int pwm; u8 reg; dir = info->direction; pwm = info->speed; twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, ®, TWL4030_REG_VIBRA_CTL); if (pwm && (!info->coexist || !(reg & TWL4030_VIBRA_SEL))) { if (!info->enabled) vibra_enable(info); /* set vibra rotation direction */ twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, ®, TWL4030_REG_VIBRA_CTL); reg = (dir) ? (reg | TWL4030_VIBRA_DIR) : (reg & ~TWL4030_VIBRA_DIR); twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, reg, TWL4030_REG_VIBRA_CTL); /* set PWM, 1 = max, 255 = min */ twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, 256 - pwm, TWL4030_REG_VIBRA_SET); } else { if (info->enabled) vibra_disable(info); } }
static void vibra_play_work(struct work_struct *work) { struct vibra_info *info = container_of(work, struct vibra_info, play_work); int dir; int pwm; u8 reg; dir = info->direction; pwm = info->speed; #ifdef VDEBUG printk(KERN_INFO "entered vibra_play_work: dir = 0x%x, speed = %d\n", dir, pwm); #endif twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, ®, TWL4030_REG_VIBRA_CTL); if (pwm && (!info->coexist || !(reg & TWL4030_VIBRA_SEL))) { #ifdef VDEBUG printk(KERN_INFO "about to set direction and speed.\n"); #endif if (!info->enabled) vibra_enable(info); /* set vibra rotation direction */ twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, ®, TWL4030_REG_VIBRA_CTL); #ifdef VDEBUG printk(KERN_INFO "reg value = %x", reg); #endif reg = (dir) ? (reg | TWL4030_VIBRA_DIR) : (reg & ~TWL4030_VIBRA_DIR); #ifdef VDEBUG int tmp = 0; twl_i2c_read_u8(TWL4030_MODULE_LED, &tmp, 0); printk(KERN_INFO "LEDEN = %x\n", tmp); tmp = 0; twl_i2c_write_u8(TWL4030_MODULE_LED, &tmp, 0); twl_i2c_read_u8(TWL4030_MODULE_LED, &tmp, 0); printk(KERN_INFO "LEDEN updated = %x\n", tmp); printk(KERN_INFO "reg = %x\n", reg); //reg = 1; #endif twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, reg, TWL4030_REG_VIBRA_CTL); #ifdef VDEBUG pwm = 255; #endif /* set PWM, 1 = max, 255 = min */ twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, 256 - pwm, TWL4030_REG_VIBRA_SET); } else { if (info->enabled) vibra_disable(info); } }
static void twl4030_vibra_close(struct input_dev *input) { struct vibra_info *info = input_get_drvdata(input); cancel_work_sync(&info->play_work); if (info->enabled) vibra_disable(info); }
/*** Module ***/ static int __maybe_unused twl4030_vibra_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct vibra_info *info = platform_get_drvdata(pdev); if (info->enabled) vibra_disable(info); return 0; }
static void twl4030_vibra_close(struct input_dev *input) { struct vibra_info *info = input_get_drvdata(input); cancel_work_sync(&info->play_work); INIT_WORK(&info->play_work, vibra_play_work); /* cleanup */ destroy_workqueue(info->workqueue); info->workqueue = NULL; if (info->enabled) vibra_disable(info); }
static ssize_t vibra_set_vibrator(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { long vibrator_enable; struct vibra_info *info = dev_get_drvdata(dev); if (kstrtol(buf, 0, &vibrator_enable)) return -EINVAL; if (vibrator_enable == info->enabled) return len; else if (vibrator_enable == 0) vibra_disable(info); else if (vibrator_enable == 1) vibra_enable(info); else return -EINVAL; return len; }