linux/drivers/input/touchscreen/of_touchscreen.c
<<
>>
Prefs
   1/*
   2 *  Generic DT helper functions for touchscreen devices
   3 *
   4 *  Copyright (c) 2014 Sebastian Reichel <sre@kernel.org>
   5 *
   6 *  This program is free software; you can redistribute it and/or modify
   7 *  it under the terms of the GNU General Public License version 2 as
   8 *  published by the Free Software Foundation.
   9 *
  10 */
  11
  12#include <linux/property.h>
  13#include <linux/input.h>
  14#include <linux/input/mt.h>
  15#include <linux/input/touchscreen.h>
  16
  17static bool touchscreen_get_prop_u32(struct device *dev,
  18                                     const char *property,
  19                                     unsigned int default_value,
  20                                     unsigned int *value)
  21{
  22        u32 val;
  23        int error;
  24
  25        error = device_property_read_u32(dev, property, &val);
  26        if (error) {
  27                *value = default_value;
  28                return false;
  29        }
  30
  31        *value = val;
  32        return true;
  33}
  34
  35static void touchscreen_set_params(struct input_dev *dev,
  36                                   unsigned long axis,
  37                                   int max, int fuzz)
  38{
  39        struct input_absinfo *absinfo;
  40
  41        if (!test_bit(axis, dev->absbit)) {
  42                dev_warn(&dev->dev,
  43                         "DT specifies parameters but the axis %lu is not set up\n",
  44                         axis);
  45                return;
  46        }
  47
  48        absinfo = &dev->absinfo[axis];
  49        absinfo->maximum = max;
  50        absinfo->fuzz = fuzz;
  51}
  52
  53/**
  54 * touchscreen_parse_properties - parse common touchscreen DT properties
  55 * @input: input device that should be parsed
  56 * @multitouch: specifies whether parsed properties should be applied to
  57 *      single-touch or multi-touch axes
  58 * @prop: pointer to a struct touchscreen_properties into which to store
  59 *      axis swap and invert info for use with touchscreen_report_x_y();
  60 *      or %NULL
  61 *
  62 * This function parses common DT properties for touchscreens and setups the
  63 * input device accordingly. The function keeps previously set up default
  64 * values if no value is specified via DT.
  65 */
  66void touchscreen_parse_properties(struct input_dev *input, bool multitouch,
  67                                  struct touchscreen_properties *prop)
  68{
  69        struct device *dev = input->dev.parent;
  70        unsigned int axis;
  71        unsigned int maximum, fuzz;
  72        bool data_present;
  73
  74        input_alloc_absinfo(input);
  75        if (!input->absinfo)
  76                return;
  77
  78        axis = multitouch ? ABS_MT_POSITION_X : ABS_X;
  79        data_present = touchscreen_get_prop_u32(dev, "touchscreen-size-x",
  80                                                input_abs_get_max(input,
  81                                                                  axis) + 1,
  82                                                &maximum) |
  83                       touchscreen_get_prop_u32(dev, "touchscreen-fuzz-x",
  84                                                input_abs_get_fuzz(input, axis),
  85                                                &fuzz);
  86        if (data_present)
  87                touchscreen_set_params(input, axis, maximum - 1, fuzz);
  88
  89        axis = multitouch ? ABS_MT_POSITION_Y : ABS_Y;
  90        data_present = touchscreen_get_prop_u32(dev, "touchscreen-size-y",
  91                                                input_abs_get_max(input,
  92                                                                  axis) + 1,
  93                                                &maximum) |
  94                       touchscreen_get_prop_u32(dev, "touchscreen-fuzz-y",
  95                                                input_abs_get_fuzz(input, axis),
  96                                                &fuzz);
  97        if (data_present)
  98                touchscreen_set_params(input, axis, maximum - 1, fuzz);
  99
 100        axis = multitouch ? ABS_MT_PRESSURE : ABS_PRESSURE;
 101        data_present = touchscreen_get_prop_u32(dev,
 102                                                "touchscreen-max-pressure",
 103                                                input_abs_get_max(input, axis),
 104                                                &maximum) |
 105                       touchscreen_get_prop_u32(dev,
 106                                                "touchscreen-fuzz-pressure",
 107                                                input_abs_get_fuzz(input, axis),
 108                                                &fuzz);
 109        if (data_present)
 110                touchscreen_set_params(input, axis, maximum, fuzz);
 111
 112        if (!prop)
 113                return;
 114
 115        axis = multitouch ? ABS_MT_POSITION_X : ABS_X;
 116
 117        prop->max_x = input_abs_get_max(input, axis);
 118        prop->max_y = input_abs_get_max(input, axis + 1);
 119        prop->invert_x =
 120                device_property_read_bool(dev, "touchscreen-inverted-x");
 121        prop->invert_y =
 122                device_property_read_bool(dev, "touchscreen-inverted-y");
 123        prop->swap_x_y =
 124                device_property_read_bool(dev, "touchscreen-swapped-x-y");
 125
 126        if (prop->swap_x_y)
 127                swap(input->absinfo[axis], input->absinfo[axis + 1]);
 128}
 129EXPORT_SYMBOL(touchscreen_parse_properties);
 130
 131static void
 132touchscreen_apply_prop_to_x_y(const struct touchscreen_properties *prop,
 133                              unsigned int *x, unsigned int *y)
 134{
 135        if (prop->invert_x)
 136                *x = prop->max_x - *x;
 137
 138        if (prop->invert_y)
 139                *y = prop->max_y - *y;
 140
 141        if (prop->swap_x_y)
 142                swap(*x, *y);
 143}
 144
 145/**
 146 * touchscreen_set_mt_pos - Set input_mt_pos coordinates
 147 * @pos: input_mt_pos to set coordinates of
 148 * @prop: pointer to a struct touchscreen_properties
 149 * @x: X coordinate to store in pos
 150 * @y: Y coordinate to store in pos
 151 *
 152 * Adjust the passed in x and y values applying any axis inversion and
 153 * swapping requested in the passed in touchscreen_properties and store
 154 * the result in a struct input_mt_pos.
 155 */
 156void touchscreen_set_mt_pos(struct input_mt_pos *pos,
 157                            const struct touchscreen_properties *prop,
 158                            unsigned int x, unsigned int y)
 159{
 160        touchscreen_apply_prop_to_x_y(prop, &x, &y);
 161        pos->x = x;
 162        pos->y = y;
 163}
 164EXPORT_SYMBOL(touchscreen_set_mt_pos);
 165
 166/**
 167 * touchscreen_report_pos - Report touchscreen coordinates
 168 * @input: input_device to report coordinates for
 169 * @prop: pointer to a struct touchscreen_properties
 170 * @x: X coordinate to report
 171 * @y: Y coordinate to report
 172 * @multitouch: Report coordinates on single-touch or multi-touch axes
 173 *
 174 * Adjust the passed in x and y values applying any axis inversion and
 175 * swapping requested in the passed in touchscreen_properties and then
 176 * report the resulting coordinates on the input_dev's x and y axis.
 177 */
 178void touchscreen_report_pos(struct input_dev *input,
 179                            const struct touchscreen_properties *prop,
 180                            unsigned int x, unsigned int y,
 181                            bool multitouch)
 182{
 183        touchscreen_apply_prop_to_x_y(prop, &x, &y);
 184        input_report_abs(input, multitouch ? ABS_MT_POSITION_X : ABS_X, x);
 185        input_report_abs(input, multitouch ? ABS_MT_POSITION_Y : ABS_Y, y);
 186}
 187EXPORT_SYMBOL(touchscreen_report_pos);
 188