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