diff options
Diffstat (limited to 'drivers/platform/chrome/cros_ec_lightbar.c')
| -rw-r--r-- | drivers/platform/chrome/cros_ec_lightbar.c | 47 |
1 files changed, 30 insertions, 17 deletions
diff --git a/drivers/platform/chrome/cros_ec_lightbar.c b/drivers/platform/chrome/cros_ec_lightbar.c index 469dfc7a4a03..8352e9732791 100644 --- a/drivers/platform/chrome/cros_ec_lightbar.c +++ b/drivers/platform/chrome/cros_ec_lightbar.c @@ -8,6 +8,8 @@ #include <linux/device.h> #include <linux/fs.h> #include <linux/kobject.h> +#include <linux/kstrtox.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> #include <linux/platform_data/cros_ec_commands.h> #include <linux/platform_data/cros_ec_proto.h> @@ -28,12 +30,19 @@ static unsigned long lb_interval_jiffies = 50 * HZ / 1000; */ static bool userspace_control; +/* + * Whether or not the lightbar supports the manual suspend commands. + * The Pixel 2013 (Link) does not while all other devices with a + * lightbar do. + */ +static bool has_manual_suspend; + static ssize_t interval_msec_show(struct device *dev, struct device_attribute *attr, char *buf) { unsigned long msec = lb_interval_jiffies * 1000 / HZ; - return scnprintf(buf, PAGE_SIZE, "%lu\n", msec); + return sysfs_emit(buf, "%lu\n", msec); } static ssize_t interval_msec_store(struct device *dev, @@ -168,7 +177,7 @@ static ssize_t version_show(struct device *dev, if (!get_lightbar_version(ec, &version, &flags)) return -EIO; - return scnprintf(buf, PAGE_SIZE, "%d %d\n", version, flags); + return sysfs_emit(buf, "%d %d\n", version, flags); } static ssize_t brightness_store(struct device *dev, @@ -301,17 +310,15 @@ static ssize_t sequence_show(struct device *dev, ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); if (ret < 0) { - ret = scnprintf(buf, PAGE_SIZE, "XFER / EC ERROR %d / %d\n", - ret, msg->result); + ret = sysfs_emit(buf, "XFER / EC ERROR %d / %d\n", ret, msg->result); goto exit; } resp = (struct ec_response_lightbar *)msg->data; if (resp->get_seq.num >= ARRAY_SIZE(seqname)) - ret = scnprintf(buf, PAGE_SIZE, "%d\n", resp->get_seq.num); + ret = sysfs_emit(buf, "%d\n", resp->get_seq.num); else - ret = scnprintf(buf, PAGE_SIZE, "%s\n", - seqname[resp->get_seq.num]); + ret = sysfs_emit(buf, "%s\n", seqname[resp->get_seq.num]); exit: kfree(msg); @@ -482,7 +489,7 @@ static ssize_t userspace_control_show(struct device *dev, struct device_attribute *attr, char *buf) { - return scnprintf(buf, PAGE_SIZE, "%d\n", userspace_control); + return sysfs_emit(buf, "%d\n", userspace_control); } static ssize_t userspace_control_store(struct device *dev, @@ -493,7 +500,7 @@ static ssize_t userspace_control_store(struct device *dev, bool enable; int ret; - ret = strtobool(buf, &enable); + ret = kstrtobool(buf, &enable); if (ret < 0) return ret; @@ -550,7 +557,7 @@ static int cros_ec_lightbar_probe(struct platform_device *pd) return -ENODEV; /* Take control of the lightbar from the EC. */ - lb_manual_suspend_ctrl(ec_dev, 1); + has_manual_suspend = (lb_manual_suspend_ctrl(ec_dev, 1) != -EINVAL); ret = sysfs_create_group(&ec_dev->class_dev.kobj, &cros_ec_lightbar_attr_group); @@ -561,7 +568,7 @@ static int cros_ec_lightbar_probe(struct platform_device *pd) return ret; } -static int cros_ec_lightbar_remove(struct platform_device *pd) +static void cros_ec_lightbar_remove(struct platform_device *pd) { struct cros_ec_dev *ec_dev = dev_get_drvdata(pd->dev.parent); @@ -569,16 +576,15 @@ static int cros_ec_lightbar_remove(struct platform_device *pd) &cros_ec_lightbar_attr_group); /* Let the EC take over the lightbar again. */ - lb_manual_suspend_ctrl(ec_dev, 0); - - return 0; + if (has_manual_suspend) + lb_manual_suspend_ctrl(ec_dev, 0); } static int __maybe_unused cros_ec_lightbar_resume(struct device *dev) { struct cros_ec_dev *ec_dev = dev_get_drvdata(dev->parent); - if (userspace_control) + if (userspace_control || !has_manual_suspend) return 0; return lb_send_empty_cmd(ec_dev, LIGHTBAR_CMD_RESUME); @@ -588,7 +594,7 @@ static int __maybe_unused cros_ec_lightbar_suspend(struct device *dev) { struct cros_ec_dev *ec_dev = dev_get_drvdata(dev->parent); - if (userspace_control) + if (userspace_control || !has_manual_suspend) return 0; return lb_send_empty_cmd(ec_dev, LIGHTBAR_CMD_SUSPEND); @@ -597,17 +603,24 @@ static int __maybe_unused cros_ec_lightbar_suspend(struct device *dev) static SIMPLE_DEV_PM_OPS(cros_ec_lightbar_pm_ops, cros_ec_lightbar_suspend, cros_ec_lightbar_resume); +static const struct platform_device_id cros_ec_lightbar_id[] = { + { DRV_NAME, 0 }, + {} +}; +MODULE_DEVICE_TABLE(platform, cros_ec_lightbar_id); + static struct platform_driver cros_ec_lightbar_driver = { .driver = { .name = DRV_NAME, .pm = &cros_ec_lightbar_pm_ops, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, .probe = cros_ec_lightbar_probe, .remove = cros_ec_lightbar_remove, + .id_table = cros_ec_lightbar_id, }; module_platform_driver(cros_ec_lightbar_driver); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Expose the Chromebook Pixel's lightbar to userspace"); -MODULE_ALIAS("platform:" DRV_NAME); |
