Merge branch 'for-linus' into next
Sync up to bring in wacom_w8001 changes to avoid merge conflicts later.
这个提交包含在:
@@ -178,7 +178,6 @@ static int arizona_haptics_probe(struct platform_device *pdev)
|
||||
input_set_drvdata(haptics->input_dev, haptics);
|
||||
|
||||
haptics->input_dev->name = "arizona:haptics";
|
||||
haptics->input_dev->dev.parent = pdev->dev.parent;
|
||||
haptics->input_dev->close = arizona_haptics_close;
|
||||
__set_bit(FF_RUMBLE, haptics->input_dev->ffbit);
|
||||
|
||||
|
@@ -255,12 +255,14 @@ static int max8997_haptic_probe(struct platform_device *pdev)
|
||||
struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
|
||||
const struct max8997_platform_data *pdata =
|
||||
dev_get_platdata(iodev->dev);
|
||||
const struct max8997_haptic_platform_data *haptic_pdata =
|
||||
pdata->haptic_pdata;
|
||||
const struct max8997_haptic_platform_data *haptic_pdata = NULL;
|
||||
struct max8997_haptic *chip;
|
||||
struct input_dev *input_dev;
|
||||
int error;
|
||||
|
||||
if (pdata)
|
||||
haptic_pdata = pdata->haptic_pdata;
|
||||
|
||||
if (!haptic_pdata) {
|
||||
dev_err(&pdev->dev, "no haptic platform data\n");
|
||||
return -EINVAL;
|
||||
|
@@ -353,7 +353,8 @@ static int pmic8xxx_pwrkey_probe(struct platform_device *pdev)
|
||||
if (of_property_read_u32(pdev->dev.of_node, "debounce", &kpd_delay))
|
||||
kpd_delay = 15625;
|
||||
|
||||
if (kpd_delay > 62500 || kpd_delay == 0) {
|
||||
/* Valid range of pwr key trigger delay is 1/64 sec to 2 seconds. */
|
||||
if (kpd_delay > USEC_PER_SEC * 2 || kpd_delay < USEC_PER_SEC / 64) {
|
||||
dev_err(&pdev->dev, "invalid power key trigger delay\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -385,8 +386,8 @@ static int pmic8xxx_pwrkey_probe(struct platform_device *pdev)
|
||||
pwr->name = "pmic8xxx_pwrkey";
|
||||
pwr->phys = "pmic8xxx_pwrkey/input0";
|
||||
|
||||
delay = (kpd_delay << 10) / USEC_PER_SEC;
|
||||
delay = 1 + ilog2(delay);
|
||||
delay = (kpd_delay << 6) / USEC_PER_SEC;
|
||||
delay = ilog2(delay);
|
||||
|
||||
err = regmap_read(regmap, PON_CNTL_1, &pon_cntl);
|
||||
if (err < 0) {
|
||||
|
@@ -20,21 +20,40 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pwm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
struct pwm_beeper {
|
||||
struct input_dev *input;
|
||||
struct pwm_device *pwm;
|
||||
struct work_struct work;
|
||||
unsigned long period;
|
||||
};
|
||||
|
||||
#define HZ_TO_NANOSECONDS(x) (1000000000UL/(x))
|
||||
|
||||
static void __pwm_beeper_set(struct pwm_beeper *beeper)
|
||||
{
|
||||
unsigned long period = beeper->period;
|
||||
|
||||
if (period) {
|
||||
pwm_config(beeper->pwm, period / 2, period);
|
||||
pwm_enable(beeper->pwm);
|
||||
} else
|
||||
pwm_disable(beeper->pwm);
|
||||
}
|
||||
|
||||
static void pwm_beeper_work(struct work_struct *work)
|
||||
{
|
||||
struct pwm_beeper *beeper =
|
||||
container_of(work, struct pwm_beeper, work);
|
||||
|
||||
__pwm_beeper_set(beeper);
|
||||
}
|
||||
|
||||
static int pwm_beeper_event(struct input_dev *input,
|
||||
unsigned int type, unsigned int code, int value)
|
||||
{
|
||||
int ret = 0;
|
||||
struct pwm_beeper *beeper = input_get_drvdata(input);
|
||||
unsigned long period;
|
||||
|
||||
if (type != EV_SND || value < 0)
|
||||
return -EINVAL;
|
||||
@@ -49,22 +68,31 @@ static int pwm_beeper_event(struct input_dev *input,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (value == 0) {
|
||||
pwm_disable(beeper->pwm);
|
||||
} else {
|
||||
period = HZ_TO_NANOSECONDS(value);
|
||||
ret = pwm_config(beeper->pwm, period / 2, period);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = pwm_enable(beeper->pwm);
|
||||
if (ret)
|
||||
return ret;
|
||||
beeper->period = period;
|
||||
}
|
||||
if (value == 0)
|
||||
beeper->period = 0;
|
||||
else
|
||||
beeper->period = HZ_TO_NANOSECONDS(value);
|
||||
|
||||
schedule_work(&beeper->work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pwm_beeper_stop(struct pwm_beeper *beeper)
|
||||
{
|
||||
cancel_work_sync(&beeper->work);
|
||||
|
||||
if (beeper->period)
|
||||
pwm_disable(beeper->pwm);
|
||||
}
|
||||
|
||||
static void pwm_beeper_close(struct input_dev *input)
|
||||
{
|
||||
struct pwm_beeper *beeper = input_get_drvdata(input);
|
||||
|
||||
pwm_beeper_stop(beeper);
|
||||
}
|
||||
|
||||
static int pwm_beeper_probe(struct platform_device *pdev)
|
||||
{
|
||||
unsigned long pwm_id = (unsigned long)dev_get_platdata(&pdev->dev);
|
||||
@@ -87,6 +115,8 @@ static int pwm_beeper_probe(struct platform_device *pdev)
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
INIT_WORK(&beeper->work, pwm_beeper_work);
|
||||
|
||||
beeper->input = input_allocate_device();
|
||||
if (!beeper->input) {
|
||||
dev_err(&pdev->dev, "Failed to allocate input device\n");
|
||||
@@ -106,6 +136,7 @@ static int pwm_beeper_probe(struct platform_device *pdev)
|
||||
beeper->input->sndbit[0] = BIT(SND_TONE) | BIT(SND_BELL);
|
||||
|
||||
beeper->input->event = pwm_beeper_event;
|
||||
beeper->input->close = pwm_beeper_close;
|
||||
|
||||
input_set_drvdata(beeper->input, beeper);
|
||||
|
||||
@@ -135,7 +166,6 @@ static int pwm_beeper_remove(struct platform_device *pdev)
|
||||
|
||||
input_unregister_device(beeper->input);
|
||||
|
||||
pwm_disable(beeper->pwm);
|
||||
pwm_free(beeper->pwm);
|
||||
|
||||
kfree(beeper);
|
||||
@@ -147,8 +177,7 @@ static int __maybe_unused pwm_beeper_suspend(struct device *dev)
|
||||
{
|
||||
struct pwm_beeper *beeper = dev_get_drvdata(dev);
|
||||
|
||||
if (beeper->period)
|
||||
pwm_disable(beeper->pwm);
|
||||
pwm_beeper_stop(beeper);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -157,10 +186,8 @@ static int __maybe_unused pwm_beeper_resume(struct device *dev)
|
||||
{
|
||||
struct pwm_beeper *beeper = dev_get_drvdata(dev);
|
||||
|
||||
if (beeper->period) {
|
||||
pwm_config(beeper->pwm, beeper->period / 2, beeper->period);
|
||||
pwm_enable(beeper->pwm);
|
||||
}
|
||||
if (beeper->period)
|
||||
__pwm_beeper_set(beeper);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -222,7 +222,6 @@ static int twl4030_vibra_probe(struct platform_device *pdev)
|
||||
|
||||
info->input_dev->name = "twl4030:vibrator";
|
||||
info->input_dev->id.version = 1;
|
||||
info->input_dev->dev.parent = pdev->dev.parent;
|
||||
info->input_dev->close = twl4030_vibra_close;
|
||||
__set_bit(FF_RUMBLE, info->input_dev->ffbit);
|
||||
|
||||
|
@@ -45,7 +45,6 @@
|
||||
struct vibra_info {
|
||||
struct device *dev;
|
||||
struct input_dev *input_dev;
|
||||
struct workqueue_struct *workqueue;
|
||||
struct work_struct play_work;
|
||||
|
||||
int irq;
|
||||
@@ -182,6 +181,14 @@ static void vibra_play_work(struct work_struct *work)
|
||||
{
|
||||
struct vibra_info *info = container_of(work,
|
||||
struct vibra_info, play_work);
|
||||
int ret;
|
||||
|
||||
/* Do not allow effect, while the routing is set to use audio */
|
||||
ret = twl6040_get_vibralr_status(info->twl6040);
|
||||
if (ret & TWL6040_VIBSEL) {
|
||||
dev_info(info->dev, "Vibra is configured for audio\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (info->weak_speed || info->strong_speed) {
|
||||
if (!info->enabled)
|
||||
@@ -197,24 +204,12 @@ static int vibra_play(struct input_dev *input, void *data,
|
||||
struct ff_effect *effect)
|
||||
{
|
||||
struct vibra_info *info = input_get_drvdata(input);
|
||||
int ret;
|
||||
|
||||
/* Do not allow effect, while the routing is set to use audio */
|
||||
ret = twl6040_get_vibralr_status(info->twl6040);
|
||||
if (ret & TWL6040_VIBSEL) {
|
||||
dev_info(&input->dev, "Vibra is configured for audio\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
info->weak_speed = effect->u.rumble.weak_magnitude;
|
||||
info->strong_speed = effect->u.rumble.strong_magnitude;
|
||||
info->direction = effect->direction < EFFECT_DIR_180_DEG ? 1 : -1;
|
||||
|
||||
ret = queue_work(info->workqueue, &info->play_work);
|
||||
if (!ret) {
|
||||
dev_info(&input->dev, "work is already on queue\n");
|
||||
return ret;
|
||||
}
|
||||
schedule_work(&info->play_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -253,6 +248,7 @@ static int twl6040_vibra_probe(struct platform_device *pdev)
|
||||
int vddvibr_uV = 0;
|
||||
int error;
|
||||
|
||||
of_node_get(twl6040_core_dev->of_node);
|
||||
twl6040_core_node = of_find_node_by_name(twl6040_core_dev->of_node,
|
||||
"vibra");
|
||||
if (!twl6040_core_node) {
|
||||
@@ -351,7 +347,6 @@ static int twl6040_vibra_probe(struct platform_device *pdev)
|
||||
|
||||
info->input_dev->name = "twl6040:vibrator";
|
||||
info->input_dev->id.version = 1;
|
||||
info->input_dev->dev.parent = pdev->dev.parent;
|
||||
info->input_dev->close = twl6040_vibra_close;
|
||||
__set_bit(FF_RUMBLE, info->input_dev->ffbit);
|
||||
|
||||
|
@@ -664,7 +664,7 @@ struct uinput_ff_upload_compat {
|
||||
static int uinput_ff_upload_to_user(char __user *buffer,
|
||||
const struct uinput_ff_upload *ff_up)
|
||||
{
|
||||
if (INPUT_COMPAT_TEST) {
|
||||
if (in_compat_syscall()) {
|
||||
struct uinput_ff_upload_compat ff_up_compat;
|
||||
|
||||
ff_up_compat.request_id = ff_up->request_id;
|
||||
@@ -695,7 +695,7 @@ static int uinput_ff_upload_to_user(char __user *buffer,
|
||||
static int uinput_ff_upload_from_user(const char __user *buffer,
|
||||
struct uinput_ff_upload *ff_up)
|
||||
{
|
||||
if (INPUT_COMPAT_TEST) {
|
||||
if (in_compat_syscall()) {
|
||||
struct uinput_ff_upload_compat ff_up_compat;
|
||||
|
||||
if (copy_from_user(&ff_up_compat, buffer,
|
||||
@@ -981,9 +981,15 @@ static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
|
||||
#define UI_SET_PHYS_COMPAT _IOW(UINPUT_IOCTL_BASE, 108, compat_uptr_t)
|
||||
|
||||
static long uinput_compat_ioctl(struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
if (cmd == UI_SET_PHYS_COMPAT)
|
||||
cmd = UI_SET_PHYS;
|
||||
|
||||
return uinput_ioctl_handler(file, cmd, arg, compat_ptr(arg));
|
||||
}
|
||||
#endif
|
||||
|
在新工单中引用
屏蔽一个用户