1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
|
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2016 Golden Delicious Comp. GmbH&Co. KG
* Nikolaus Schaller <hns@goldelico.com>
*/
#include <linux/i2c.h>
#include <linux/iio/iio.h>
#include "tsc2007.h"
struct tsc2007_iio {
struct tsc2007 *ts;
};
#define TSC2007_CHAN_IIO(_chan, _name, _type, _chan_info) \
{ \
.datasheet_name = _name, \
.type = _type, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(_chan_info), \
.indexed = 1, \
.channel = _chan, \
}
static const struct iio_chan_spec tsc2007_iio_channel[] = {
TSC2007_CHAN_IIO(0, "x", IIO_VOLTAGE, IIO_CHAN_INFO_RAW),
TSC2007_CHAN_IIO(1, "y", IIO_VOLTAGE, IIO_CHAN_INFO_RAW),
TSC2007_CHAN_IIO(2, "z1", IIO_VOLTAGE, IIO_CHAN_INFO_RAW),
TSC2007_CHAN_IIO(3, "z2", IIO_VOLTAGE, IIO_CHAN_INFO_RAW),
TSC2007_CHAN_IIO(4, "adc", IIO_VOLTAGE, IIO_CHAN_INFO_RAW),
TSC2007_CHAN_IIO(5, "rt", IIO_VOLTAGE, IIO_CHAN_INFO_RAW), /* Ohms? */
TSC2007_CHAN_IIO(6, "pen", IIO_PRESSURE, IIO_CHAN_INFO_RAW),
TSC2007_CHAN_IIO(7, "temp0", IIO_TEMP, IIO_CHAN_INFO_RAW),
TSC2007_CHAN_IIO(8, "temp1", IIO_TEMP, IIO_CHAN_INFO_RAW),
};
static int tsc2007_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct tsc2007_iio *iio = iio_priv(indio_dev);
struct tsc2007 *tsc = iio->ts;
int adc_chan = chan->channel;
int ret = 0;
if (adc_chan >= ARRAY_SIZE(tsc2007_iio_channel))
return -EINVAL;
if (mask != IIO_CHAN_INFO_RAW)
return -EINVAL;
mutex_lock(&tsc->mlock);
switch (chan->channel) {
case 0:
*val = tsc2007_xfer(tsc, READ_X);
break;
case 1:
*val = tsc2007_xfer(tsc, READ_Y);
break;
case 2:
*val = tsc2007_xfer(tsc, READ_Z1);
break;
case 3:
*val = tsc2007_xfer(tsc, READ_Z2);
break;
case 4:
*val = tsc2007_xfer(tsc, (ADC_ON_12BIT | TSC2007_MEASURE_AUX));
break;
case 5: {
struct ts_event tc;
tc.x = tsc2007_xfer(tsc, READ_X);
tc.z1 = tsc2007_xfer(tsc, READ_Z1);
tc.z2 = tsc2007_xfer(tsc, READ_Z2);
*val = tsc2007_calculate_resistance(tsc, &tc);
break;
}
case 6:
*val = tsc2007_is_pen_down(tsc);
break;
case 7:
*val = tsc2007_xfer(tsc,
(ADC_ON_12BIT | TSC2007_MEASURE_TEMP0));
break;
case 8:
*val = tsc2007_xfer(tsc,
(ADC_ON_12BIT | TSC2007_MEASURE_TEMP1));
break;
}
/* Prepare for next touch reading - power down ADC, enable PENIRQ */
tsc2007_xfer(tsc, PWRDOWN);
mutex_unlock(&tsc->mlock);
ret = IIO_VAL_INT;
return ret;
}
static const struct iio_info tsc2007_iio_info = {
.read_raw = tsc2007_read_raw,
};
int tsc2007_iio_configure(struct tsc2007 *ts)
{
struct iio_dev *indio_dev;
struct tsc2007_iio *iio;
int error;
indio_dev = devm_iio_device_alloc(&ts->client->dev, sizeof(*iio));
if (!indio_dev) {
dev_err(&ts->client->dev, "iio_device_alloc failed\n");
return -ENOMEM;
}
iio = iio_priv(indio_dev);
iio->ts = ts;
indio_dev->name = "tsc2007";
indio_dev->info = &tsc2007_iio_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = tsc2007_iio_channel;
indio_dev->num_channels = ARRAY_SIZE(tsc2007_iio_channel);
error = devm_iio_device_register(&ts->client->dev, indio_dev);
if (error) {
dev_err(&ts->client->dev,
"iio_device_register() failed: %d\n", error);
return error;
}
return 0;
}
|