root/drivers/input/touchscreen/ipaq-micro-ts.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. micro_ts_receive
  2. micro_ts_toggle_receive
  3. micro_ts_open
  4. micro_ts_close
  5. micro_ts_probe
  6. micro_ts_suspend
  7. micro_ts_resume

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  *
   4  * h3600 atmel micro companion support, touchscreen subdevice
   5  * Author : Alessandro Gardich <gremlin@gremlin.it>
   6  * Author : Dmitry Artamonow <mad_soft@inbox.ru>
   7  * Author : Linus Walleij <linus.walleij@linaro.org>
   8  */
   9 
  10 #include <asm/byteorder.h>
  11 #include <linux/module.h>
  12 #include <linux/init.h>
  13 #include <linux/interrupt.h>
  14 #include <linux/pm.h>
  15 #include <linux/delay.h>
  16 #include <linux/device.h>
  17 #include <linux/input.h>
  18 #include <linux/platform_device.h>
  19 #include <linux/slab.h>
  20 #include <linux/mfd/ipaq-micro.h>
  21 
  22 struct touchscreen_data {
  23         struct input_dev *input;
  24         struct ipaq_micro *micro;
  25 };
  26 
  27 static void micro_ts_receive(void *data, int len, unsigned char *msg)
  28 {
  29         struct touchscreen_data *ts = data;
  30 
  31         if (len == 4) {
  32                 input_report_abs(ts->input, ABS_X,
  33                                  be16_to_cpup((__be16 *) &msg[2]));
  34                 input_report_abs(ts->input, ABS_Y,
  35                                  be16_to_cpup((__be16 *) &msg[0]));
  36                 input_report_key(ts->input, BTN_TOUCH, 1);
  37                 input_sync(ts->input);
  38         } else if (len == 0) {
  39                 input_report_abs(ts->input, ABS_X, 0);
  40                 input_report_abs(ts->input, ABS_Y, 0);
  41                 input_report_key(ts->input, BTN_TOUCH, 0);
  42                 input_sync(ts->input);
  43         }
  44 }
  45 
  46 static void micro_ts_toggle_receive(struct touchscreen_data *ts, bool enable)
  47 {
  48         struct ipaq_micro *micro = ts->micro;
  49 
  50         spin_lock_irq(&micro->lock);
  51 
  52         if (enable) {
  53                 micro->ts = micro_ts_receive;
  54                 micro->ts_data = ts;
  55         } else {
  56                 micro->ts = NULL;
  57                 micro->ts_data = NULL;
  58         }
  59 
  60         spin_unlock_irq(&ts->micro->lock);
  61 }
  62 
  63 static int micro_ts_open(struct input_dev *input)
  64 {
  65         struct touchscreen_data *ts = input_get_drvdata(input);
  66 
  67         micro_ts_toggle_receive(ts, true);
  68 
  69         return 0;
  70 }
  71 
  72 static void micro_ts_close(struct input_dev *input)
  73 {
  74         struct touchscreen_data *ts = input_get_drvdata(input);
  75 
  76         micro_ts_toggle_receive(ts, false);
  77 }
  78 
  79 static int micro_ts_probe(struct platform_device *pdev)
  80 {
  81         struct ipaq_micro *micro = dev_get_drvdata(pdev->dev.parent);
  82         struct touchscreen_data *ts;
  83         int error;
  84 
  85         ts = devm_kzalloc(&pdev->dev, sizeof(*ts), GFP_KERNEL);
  86         if (!ts)
  87                 return -ENOMEM;
  88 
  89         ts->micro = micro;
  90 
  91         ts->input = devm_input_allocate_device(&pdev->dev);
  92         if (!ts->input) {
  93                 dev_err(&pdev->dev, "failed to allocate input device\n");
  94                 return -ENOMEM;
  95         }
  96 
  97         ts->input->name = "ipaq micro ts";
  98         ts->input->open = micro_ts_open;
  99         ts->input->close = micro_ts_close;
 100 
 101         input_set_drvdata(ts->input, ts);
 102 
 103         input_set_capability(ts->input, EV_KEY, BTN_TOUCH);
 104         input_set_capability(ts->input, EV_ABS, ABS_X);
 105         input_set_capability(ts->input, EV_ABS, ABS_Y);
 106         input_set_abs_params(ts->input, ABS_X, 0, 1023, 0, 0);
 107         input_set_abs_params(ts->input, ABS_Y, 0, 1023, 0, 0);
 108 
 109         error = input_register_device(ts->input);
 110         if (error) {
 111                 dev_err(&pdev->dev, "error registering touch input\n");
 112                 return error;
 113         }
 114 
 115         platform_set_drvdata(pdev, ts);
 116 
 117         dev_info(&pdev->dev, "iPAQ micro touchscreen\n");
 118 
 119         return 0;
 120 }
 121 
 122 static int __maybe_unused micro_ts_suspend(struct device *dev)
 123 {
 124         struct touchscreen_data *ts = dev_get_drvdata(dev);
 125 
 126         micro_ts_toggle_receive(ts, false);
 127 
 128         return 0;
 129 }
 130 
 131 static int __maybe_unused micro_ts_resume(struct device *dev)
 132 {
 133         struct touchscreen_data *ts = dev_get_drvdata(dev);
 134         struct input_dev *input = ts->input;
 135 
 136         mutex_lock(&input->mutex);
 137 
 138         if (input->users)
 139                 micro_ts_toggle_receive(ts, true);
 140 
 141         mutex_unlock(&input->mutex);
 142 
 143         return 0;
 144 }
 145 
 146 static const struct dev_pm_ops micro_ts_dev_pm_ops = {
 147         SET_SYSTEM_SLEEP_PM_OPS(micro_ts_suspend, micro_ts_resume)
 148 };
 149 
 150 static struct platform_driver micro_ts_device_driver = {
 151         .driver = {
 152                 .name   = "ipaq-micro-ts",
 153                 .pm     = &micro_ts_dev_pm_ops,
 154         },
 155         .probe  = micro_ts_probe,
 156 };
 157 module_platform_driver(micro_ts_device_driver);
 158 
 159 MODULE_LICENSE("GPL");
 160 MODULE_DESCRIPTION("driver for iPAQ Atmel micro touchscreen");
 161 MODULE_ALIAS("platform:ipaq-micro-ts");

/* [<][>][^][v][top][bottom][index][help] */