Input: rpi_ft5406 - add enable sysfs attribute
authorKwangCheol Lee <kclee@dignsys.com>
Mon, 11 Sep 2017 05:09:08 +0000 (14:09 +0900)
committerJunghoon Kim <jhoon20.kim@samsung.com>
Thu, 2 Apr 2020 04:08:59 +0000 (13:08 +0900)
Add enable sysfs attribute for disable/enable the touchscreen input.
This feature is required to turn the touch screen display on or off.

Change-Id: I4d5250c32cc2118f0f19a8a3cfb76ea8574f6937
Signed-off-by: KwangCheol Lee <kclee@dignsys.com>
drivers/input/touchscreen/rpi-ft5406.c

index 719ab01..7f38fbd 100644 (file)
@@ -53,6 +53,8 @@ struct ft5406 {
        void __iomem            *ts_base;
        dma_addr_t              bus_addr;
        struct task_struct      *thread;
+       bool                     enable;
+       struct mutex             sysfs_mutex;
 
        uint16_t        max_x;
        uint16_t        max_y;
@@ -160,6 +162,62 @@ static int ft5406_thread(void *arg)
        return 0;
 }
 
+static ssize_t enable_show(struct device *dev, struct device_attribute *attr,
+                         char *buf)
+{
+       struct ft5406 *ts = (struct ft5406 *)dev_get_drvdata(dev);
+
+       return sprintf(buf, "%d\n", ts->enable);
+}
+
+static ssize_t enable_store(struct device *dev, struct device_attribute *attr,
+                          const char *buf, size_t count)
+{
+       struct ft5406 *ts = (struct ft5406 *)dev_get_drvdata(dev);
+       unsigned int val;
+       int error;
+
+       error = kstrtouint(buf, 0, &val);
+       if (error)
+               return error;
+
+       mutex_lock(&ts->sysfs_mutex);
+
+       if (ts->enable == !!val)
+               goto out;
+
+       if (val) {
+               ts->thread = kthread_run(ft5406_thread, ts, "ft5406");
+               if (IS_ERR(ts->thread)) {
+                       dev_err(dev, "Failed to create kernel thread");
+                       goto out;
+               }
+       } else {
+               error = kthread_stop(ts->thread);
+               if (unlikely(error)) {
+                       dev_err(dev, "Failed to stop kernel thread");
+                       goto out;
+               }
+       }
+       ts->enable = !!val;
+
+out:
+       mutex_unlock(&ts->sysfs_mutex);
+
+       return count;
+}
+
+static DEVICE_ATTR_RW(enable);
+
+static struct attribute *rpi_ft5406_attrs[] = {
+       &dev_attr_enable.attr,
+       NULL
+};
+
+static const struct attribute_group rpi_ft5406_attr_group = {
+       .attrs = rpi_ft5406_attrs,
+};
+
 static int ft5406_probe(struct platform_device *pdev)
 {
        int err = 0;
@@ -296,16 +354,28 @@ static int ft5406_probe(struct platform_device *pdev)
                goto out;
        }
 
+       ts->enable = true;
+       mutex_init(&ts->sysfs_mutex);
+
+       err = sysfs_create_group(&dev->kobj, &rpi_ft5406_attr_group);
+       if (err) {
+               dev_err(dev, "failed to create sysfs group: %d\n", err);
+               goto out;
+       }
+
        /* create thread that polls the touch events */
        ts->thread = kthread_run(ft5406_thread, ts, "ft5406");
-       if (ts->thread == NULL) {
+       if (IS_ERR(ts->thread))
+       {
                dev_err(dev, "Failed to create kernel thread");
                err = -ENOMEM;
-               goto out;
+               goto out_sysfs;
        }
 
        return 0;
 
+out_sysfs:
+       sysfs_remove_group(&dev->kobj, &rpi_ft5406_attr_group);
 out:
        if (ts->bus_addr) {
                dma_free_coherent(dev, PAGE_SIZE, ts->ts_base, ts->bus_addr);
@@ -329,7 +399,10 @@ static int ft5406_remove(struct platform_device *pdev)
 
        dev_info(dev, "Removing rpi-ft5406\n");
 
-       kthread_stop(ts->thread);
+       sysfs_remove_group(&dev->kobj, &rpi_ft5406_attr_group);
+
+       if (ts->enable)
+               kthread_stop(ts->thread);
 
        if (ts->bus_addr)
                dma_free_coherent(dev, PAGE_SIZE, ts->ts_base, ts->bus_addr);