From 899d90bdf4d4ef4c3ac0b33cd337c9b3e999ec2d Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Sun, 8 Sep 2013 16:20:00 +0100 Subject: iio: Add INT_TIME (integration time) channel info attribute Integration time is in seconds; it controls the measurement time and influences the gain of a sensor. There are two typical ways that scaling is implemented in a device: 1) input amplifier, 2) reference to the ADC is changed. These both result in the accuracy of the ADC varying (by applying its sampling over a more relevant range). Integration time is a way of dealing with noise inherent in the analog sensor itself. In the case of a light sensor, a mixture of photon noise and device specific noise. Photon noise is dealt with by either improving the efficiency of the sensor, (more photons actually captured) which is not easily varied dynamically, or by integrating the measurement over a longer time period. Note that this can also be thought of as an averaging of a number of individual samples and is infact sometimes implemented this way. Altering integration time implies that the duration of a measurement changes, a fact the device's user may be interested in. Hence it makes sense to distinguish between integration time and simple scale. In some devices both types of control are present and whilst they will have similar effects on the amplitude of the reading, their effect on the noise of the measurements will differ considerably. Used by adjd_s311, tsl4531, tcs3472 The following drivers have similar controls (and could be adapted): * tsl2563 (integration time is controlled via CALIBSCALE among other things) * tsl2583 (has integration_time device_attr, but driver doesn't use channels yet) * tsl2x7x (has integration_time attr) Signed-off-by: Peter Meerwald Cc: Jon Brenner Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'Documentation') diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 39c8de0e53d0..ab1047c20495 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -811,3 +811,14 @@ Description: Writing '1' stores the current device configuration into on-chip EEPROM. After power-up or chip reset the device will automatically load the saved configuration. + +What: /sys/.../iio:deviceX/in_intensity_red_integration_time +What: /sys/.../iio:deviceX/in_intensity_green_integration_time +What: /sys/.../iio:deviceX/in_intensity_blue_integration_time +What: /sys/.../iio:deviceX/in_intensity_clear_integration_time +What: /sys/.../iio:deviceX/in_illuminance_integration_time +KernelVersion: 3.12 +Contact: linux-iio@vger.kernel.org +Description: + This attribute is used to get/set the integration time in + seconds. -- cgit v1.2.3 From 02fa18958ce065ccc23ad59cff736031d62e9950 Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Wed, 21 Aug 2013 16:06:00 +0100 Subject: DT: Add documentation for gp2ap020a00f sensor This patch adds device tree binding documentation for the gp2ap020a00f proximity/als sensor. Signed-off-by: Jacek Anaszewski Signed-off-by: Kyungmin Park Acked-by: Stephen Warren Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/iio/light/gp2ap020a00f.txt | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/light/gp2ap020a00f.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/iio/light/gp2ap020a00f.txt b/Documentation/devicetree/bindings/iio/light/gp2ap020a00f.txt new file mode 100644 index 000000000000..9231c82317ad --- /dev/null +++ b/Documentation/devicetree/bindings/iio/light/gp2ap020a00f.txt @@ -0,0 +1,21 @@ +* Sharp GP2AP020A00F I2C Proximity/ALS sensor + +The proximity detector sensor requires power supply +for its built-in led. It is also defined by this binding. + +Required properties: + + - compatible : should be "sharp,gp2ap020a00f" + - reg : the I2C slave address of the light sensor + - interrupts : interrupt specifier for the sole interrupt generated + by the device + - vled-supply : VLED power supply, as covered in ../regulator/regulator.txt + +Example: + +gp2ap020a00f@39 { + compatible = "sharp,gp2ap020a00f"; + reg = <0x39>; + interrupts = <2 0>; + vled-supply = <...>; +}; -- cgit v1.2.3 From c2b2db71014696207b24a2bafb2d26867f82dbed Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 28 Sep 2013 10:31:00 +0100 Subject: iio: Update unit of the voltage scale in the documentation The documentation says that the result of raw * scale should be in microvolts, but in reallity all drivers actually report the scale so that the result is in millivolts. So update the documentation to match reallity. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index ab1047c20495..2d73620874b2 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -79,7 +79,7 @@ Description: correspond to externally available input one of the named versions may be used. The number must always be specified and unique to allow association with event codes. Units after - application of scale and offset are microvolts. + application of scale and offset are millivolts. What: /sys/bus/iio/devices/iio:deviceX/in_voltageY-voltageZ_raw KernelVersion: 2.6.35 @@ -90,7 +90,7 @@ Description: physically equivalent inputs when non differential readings are separately available. In differential only parts, then all that is required is a consistent labeling. Units after application - of scale and offset are microvolts. + of scale and offset are millivolts. What: /sys/bus/iio/devices/iio:deviceX/in_capacitanceY_raw KernelVersion: 3.2 -- cgit v1.2.3 From e9c88fb5cf05ae198323a3c992b41885397a0b48 Mon Sep 17 00:00:00 2001 From: Juergen Beisert Date: Mon, 23 Sep 2013 15:36:00 +0100 Subject: Staging/iio/adc/touchscreen/MXS: provide devicetree adaption MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is an RFC for the new touchscreen properties. Signed-off-by: Juergen Beisert Tested-by: Marek Vasut Acked-by: Marek Vasut Tested-by: Lothar Waßmann Signed-off-by: Jonathan Cameron CC: linux-arm-kernel@lists.infradead.org CC: linux-input@vger.kernel.org CC: devel@driverdev.osuosl.org CC: Marek Vasut CC: Fabio Estevam CC: devicetree@vger.kernel.org --- .../bindings/staging/iio/adc/mxs-lradc.txt | 36 ++++++++++++-- arch/arm/boot/dts/imx28-evk.dts | 4 ++ drivers/staging/iio/adc/mxs-lradc.c | 57 ++++++++++++++-------- 3 files changed, 71 insertions(+), 26 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt b/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt index 46882058b59b..ee05dc390694 100644 --- a/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt +++ b/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt @@ -1,7 +1,8 @@ * Freescale i.MX28 LRADC device driver Required properties: -- compatible: Should be "fsl,imx28-lradc" +- compatible: Should be "fsl,imx23-lradc" for i.MX23 SoC and "fsl,imx28-lradc" + for i.MX28 SoC - reg: Address and length of the register set for the device - interrupts: Should contain the LRADC interrupts @@ -9,13 +10,38 @@ Optional properties: - fsl,lradc-touchscreen-wires: Number of wires used to connect the touchscreen to LRADC. Valid value is either 4 or 5. If this property is not present, then the touchscreen is - disabled. + disabled. 5 wires is valid for i.MX28 SoC only. +- fsl,ave-ctrl: number of samples per direction to calculate an average value. + Allowed value is 1 ... 31, default is 4 +- fsl,ave-delay: delay between consecutive samples. Allowed value is + 1 ... 2047. It is used if 'fsl,ave-ctrl' > 1, counts at + 2 kHz and its default is 2 (= 1 ms) +- fsl,settling: delay between plate switch to next sample. Allowed value is + 1 ... 2047. It counts at 2 kHz and its default is + 10 (= 5 ms) -Examples: +Example for i.MX23 SoC: + + lradc@80050000 { + compatible = "fsl,imx23-lradc"; + reg = <0x80050000 0x2000>; + interrupts = <36 37 38 39 40 41 42 43 44>; + status = "okay"; + fsl,lradc-touchscreen-wires = <4>; + fsl,ave-ctrl = <4>; + fsl,ave-delay = <2>; + fsl,settling = <10>; + }; + +Example for i.MX28 SoC: lradc@80050000 { compatible = "fsl,imx28-lradc"; reg = <0x80050000 0x2000>; - interrupts = <10 14 15 16 17 18 19 - 20 21 22 23 24 25>; + interrupts = <10 14 15 16 17 18 19 20 21 22 23 24 25>; + status = "okay"; + fsl,lradc-touchscreen-wires = <5>; + fsl,ave-ctrl = <4>; + fsl,ave-delay = <2>; + fsl,settling = <10>; }; diff --git a/arch/arm/boot/dts/imx28-evk.dts b/arch/arm/boot/dts/imx28-evk.dts index 15715d921d14..aa33393903a8 100644 --- a/arch/arm/boot/dts/imx28-evk.dts +++ b/arch/arm/boot/dts/imx28-evk.dts @@ -183,6 +183,10 @@ lradc@80050000 { status = "okay"; + fsl,lradc-touchscreen-wires = <4>; + fsl,ave-ctrl = <4>; + fsl,ave-delay = <2>; + fsl,settling = <10>; }; i2c0: i2c@80058000 { diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c index 18510d1ea5c8..dfd1bc1cc56f 100644 --- a/drivers/staging/iio/adc/mxs-lradc.c +++ b/drivers/staging/iio/adc/mxs-lradc.c @@ -1224,10 +1224,45 @@ MODULE_DEVICE_TABLE(of, mxs_lradc_dt_ids); static int mxs_lradc_probe_touchscreen(struct mxs_lradc *lradc, struct device_node *lradc_node) { - /* TODO retrieve from device tree */ + int ret; + u32 ts_wires = 0, adapt; + + ret = of_property_read_u32(lradc_node, "fsl,lradc-touchscreen-wires", + &ts_wires); + if (ret) + return -ENODEV; /* touchscreen feature disabled */ + + switch (ts_wires) { + case 4: + lradc->use_touchscreen = MXS_LRADC_TOUCHSCREEN_4WIRE; + break; + case 5: + if (lradc->soc == IMX28_LRADC) { + lradc->use_touchscreen = MXS_LRADC_TOUCHSCREEN_5WIRE; + break; + } + /* fall through an error message for i.MX23 */ + default: + dev_err(lradc->dev, + "Unsupported number of touchscreen wires (%d)\n", + ts_wires); + return -EINVAL; + } + lradc->over_sample_cnt = 4; + ret = of_property_read_u32(lradc_node, "fsl,ave-ctrl", &adapt); + if (ret == 0) + lradc->over_sample_cnt = adapt; + lradc->over_sample_delay = 2; + ret = of_property_read_u32(lradc_node, "fsl,ave-delay", &adapt); + if (ret == 0) + lradc->over_sample_delay = adapt; + lradc->settling_delay = 10; + ret = of_property_read_u32(lradc_node, "fsl,settling", &adapt); + if (ret == 0) + lradc->settling_delay = adapt; return 0; } @@ -1243,7 +1278,6 @@ static int mxs_lradc_probe(struct platform_device *pdev) struct mxs_lradc *lradc; struct iio_dev *iio; struct resource *iores; - uint32_t ts_wires = 0; int ret = 0, touch_ret; int i; @@ -1277,25 +1311,6 @@ static int mxs_lradc_probe(struct platform_device *pdev) touch_ret = mxs_lradc_probe_touchscreen(lradc, node); - /* Check if touchscreen is enabled in DT. */ - ret = of_property_read_u32(node, "fsl,lradc-touchscreen-wires", - &ts_wires); - if (ret) - dev_info(dev, "Touchscreen not enabled.\n"); - else if (ts_wires == 4) - lradc->use_touchscreen = MXS_LRADC_TOUCHSCREEN_4WIRE; - else if (ts_wires == 5) - lradc->use_touchscreen = MXS_LRADC_TOUCHSCREEN_5WIRE; - else - dev_warn(dev, "Unsupported number of touchscreen wires (%d)\n", - ts_wires); - - if ((lradc->soc == IMX23_LRADC) && (ts_wires == 5)) { - dev_warn(dev, "No support for 5 wire touches on i.MX23\n"); - dev_warn(dev, "Falling back to 4 wire\n"); - ts_wires = 4; - } - /* Grab all IRQ sources */ for (i = 0; i < of_cfg->irq_count; i++) { lradc->irq[i] = platform_get_irq(pdev, i); -- cgit v1.2.3 From 2b6d598bc9043f51d2092d10392a6e3c161cdff7 Mon Sep 17 00:00:00 2001 From: Josh Wu Date: Tue, 8 Oct 2013 04:48:00 +0100 Subject: iio: at91: move the num_channels from DT to driver itself CC: devicetree@vger.kernel.org Signed-off-by: Josh Wu Acked-by: Ludovic Desroches Signed-off-by: Jonathan Cameron --- Documentation/devicetree/bindings/arm/atmel-adc.txt | 1 - drivers/iio/adc/at91_adc.c | 12 +++++------- 2 files changed, 5 insertions(+), 8 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/arm/atmel-adc.txt b/Documentation/devicetree/bindings/arm/atmel-adc.txt index 723c205cb10d..0e65e0137487 100644 --- a/Documentation/devicetree/bindings/arm/atmel-adc.txt +++ b/Documentation/devicetree/bindings/arm/atmel-adc.txt @@ -7,7 +7,6 @@ Required properties: - interrupts: Should contain the IRQ line for the ADC - atmel,adc-channels-used: Bitmask of the channels muxed and enable for this device - - atmel,adc-num-channels: Number of channels available in the ADC - atmel,adc-startup-time: Startup Time of the ADC in microseconds as defined in the datasheet - atmel,adc-vref: Reference voltage in millivolts for the conversions diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index abce01b9ff91..690a560e0dab 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -43,6 +43,7 @@ struct at91_adc_caps { /* startup time calculate function */ u32 (*calc_startup_ticks)(u8 startup_time, u32 adc_clk_khz); + u8 num_channels; struct at91_adc_reg_desc registers; }; @@ -496,13 +497,6 @@ static int at91_adc_probe_dt(struct at91_adc_state *st, } st->channels_mask = prop; - if (of_property_read_u32(node, "atmel,adc-num-channels", &prop)) { - dev_err(&idev->dev, "Missing adc-num-channels property in the DT.\n"); - ret = -EINVAL; - goto error_ret; - } - st->num_channels = prop; - st->sleep_mode = of_property_read_bool(node, "atmel,adc-sleep-mode"); if (of_property_read_u32(node, "atmel,adc-startup-time", &prop)) { @@ -528,6 +522,7 @@ static int at91_adc_probe_dt(struct at91_adc_state *st, goto error_ret; st->registers = &st->caps->registers; + st->num_channels = st->caps->num_channels; st->trigger_number = of_get_child_count(node); st->trigger_list = devm_kzalloc(&idev->dev, st->trigger_number * sizeof(struct at91_adc_trigger), @@ -773,6 +768,7 @@ static int at91_adc_remove(struct platform_device *pdev) #ifdef CONFIG_OF static struct at91_adc_caps at91sam9260_caps = { .calc_startup_ticks = calc_startup_ticks_9260, + .num_channels = 4, .registers = { .channel_base = AT91_ADC_CHR(0), .drdy_mask = AT91_ADC_DRDY, @@ -785,6 +781,7 @@ static struct at91_adc_caps at91sam9260_caps = { static struct at91_adc_caps at91sam9g45_caps = { .calc_startup_ticks = calc_startup_ticks_9260, /* same as 9260 */ + .num_channels = 8, .registers = { .channel_base = AT91_ADC_CHR(0), .drdy_mask = AT91_ADC_DRDY, @@ -797,6 +794,7 @@ static struct at91_adc_caps at91sam9g45_caps = { static struct at91_adc_caps at91sam9x5_caps = { .calc_startup_ticks = calc_startup_ticks_9x5, + .num_channels = 12, .registers = { .channel_base = AT91_ADC_CDR0_9X5, .drdy_mask = AT91_ADC_SR_DRDY_9X5, -- cgit v1.2.3 From ec6670ae53c13d767bdb7b3e37755ad661395380 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 7 Oct 2013 15:11:00 +0100 Subject: iio: Add a hysteresis event info attribute For some devices it is possible to configure a hysteresis for threshold (or similar) events. This patch adds a new hysteresis event info type which allows for easy creation and read/write handling of the sysfs attribute. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 56 +++++++++++++++++++++++++++++++++ drivers/iio/industrialio-event.c | 1 + include/linux/iio/types.h | 1 + 3 files changed, 58 insertions(+) (limited to 'Documentation') diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 2d73620874b2..b20e829d350f 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -537,6 +537,62 @@ Description: value is in raw device units or in processed units (as _raw and _input do on sysfs direct channel read attributes). +What: /sys/.../events/in_accel_x_thresh_rising_hysteresis +What: /sys/.../events/in_accel_x_thresh_falling_hysteresis +What: /sys/.../events/in_accel_x_thresh_either_hysteresis +What: /sys/.../events/in_accel_y_thresh_rising_hysteresis +What: /sys/.../events/in_accel_y_thresh_falling_hysteresis +What: /sys/.../events/in_accel_y_thresh_either_hysteresis +What: /sys/.../events/in_accel_z_thresh_rising_hysteresis +What: /sys/.../events/in_accel_z_thresh_falling_hysteresis +What: /sys/.../events/in_accel_z_thresh_either_hysteresis +What: /sys/.../events/in_anglvel_x_thresh_rising_hysteresis +What: /sys/.../events/in_anglvel_x_thresh_falling_hysteresis +What: /sys/.../events/in_anglvel_x_thresh_either_hysteresis +What: /sys/.../events/in_anglvel_y_thresh_rising_hysteresis +What: /sys/.../events/in_anglvel_y_thresh_falling_hysteresis +What: /sys/.../events/in_anglvel_y_thresh_either_hysteresis +What: /sys/.../events/in_anglvel_z_thresh_rising_hysteresis +What: /sys/.../events/in_anglvel_z_thresh_falling_hysteresis +What: /sys/.../events/in_anglvel_z_thresh_either_hysteresis +What: /sys/.../events/in_magn_x_thresh_rising_hysteresis +What: /sys/.../events/in_magn_x_thresh_falling_hysteresis +What: /sys/.../events/in_magn_x_thresh_either_hysteresis +What: /sys/.../events/in_magn_y_thresh_rising_hysteresis +What: /sys/.../events/in_magn_y_thresh_falling_hysteresis +What: /sys/.../events/in_magn_y_thresh_either_hysteresis +What: /sys/.../events/in_magn_z_thresh_rising_hysteresis +What: /sys/.../events/in_magn_z_thresh_falling_hysteresis +What: /sys/.../events/in_magn_z_thresh_either_hysteresis +What: /sys/.../events/in_voltageY_thresh_rising_hysteresis +What: /sys/.../events/in_voltageY_thresh_falling_hysteresis +What: /sys/.../events/in_voltageY_thresh_either_hysteresis +What: /sys/.../events/in_tempY_thresh_rising_hysteresis +What: /sys/.../events/in_tempY_thresh_falling_hysteresis +What: /sys/.../events/in_tempY_thresh_either_hysteresis +What: /sys/.../events/in_illuminance0_thresh_falling_hysteresis +what: /sys/.../events/in_illuminance0_thresh_rising_hysteresis +what: /sys/.../events/in_illuminance0_thresh_either_hysteresis +what: /sys/.../events/in_proximity0_thresh_falling_hysteresis +what: /sys/.../events/in_proximity0_thresh_rising_hysteresis +what: /sys/.../events/in_proximity0_thresh_either_hysteresis +KernelVersion: 3.13 +Contact: linux-iio@vger.kernel.org +Description: + Specifies the hysteresis of threshold that the device is comparing + against for the events enabled by + Y[_name]_thresh[_(rising|falling)]_hysteresis. + If separate attributes exist for the two directions, but + direction is not specified for this attribute, then a single + hysteresis value applies to both directions. + For falling events the hysteresis is added to the _value attribute for + this event to get the upper threshold for when the event goes back to + normal, for rising events the hysteresis is subtracted from the _value + attribute. E.g. if in_voltage0_raw_thresh_rising_value is set to 1200 + and in_voltage0_raw_thresh_rising_hysteresis is set to 50. The event + will get activated once in_voltage0_raw goes above 1200 and will become + deactived again once the value falls below 1150. + What: /sys/.../events/in_accel_x_raw_roc_rising_value What: /sys/.../events/in_accel_x_raw_roc_falling_value What: /sys/.../events/in_accel_y_raw_roc_rising_value diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c index b7a5d7cbed42..dac15b9f9df8 100644 --- a/drivers/iio/industrialio-event.c +++ b/drivers/iio/industrialio-event.c @@ -204,6 +204,7 @@ static const char * const iio_ev_dir_text[] = { static const char * const iio_ev_info_text[] = { [IIO_EV_INFO_ENABLE] = "en", [IIO_EV_INFO_VALUE] = "value", + [IIO_EV_INFO_HYSTERESIS] = "hysteresis", }; static enum iio_event_direction iio_ev_attr_dir(struct iio_dev_attr *attr) diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h index 18339ef4ff5d..4ac928ee31c5 100644 --- a/include/linux/iio/types.h +++ b/include/linux/iio/types.h @@ -65,6 +65,7 @@ enum iio_event_type { enum iio_event_info { IIO_EV_INFO_ENABLE, IIO_EV_INFO_VALUE, + IIO_EV_INFO_HYSTERESIS, }; enum iio_event_direction { -- cgit v1.2.3 From 701a0dc08809936a6d7ba76c347a92ee27b852ea Mon Sep 17 00:00:00 2001 From: Beomho Seo Date: Thu, 17 Oct 2013 03:22:00 +0100 Subject: DT: Add documentation for cm36651 proximity/light sensor This patch adds device tree binding documentation for CM36651 proximity/light sensor. Signed-off-by: Beomho Seo Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/iio/light/cm36651.txt | 26 ++++++++++++++++++++++ .../devicetree/bindings/vendor-prefixes.txt | 1 + 2 files changed, 27 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/light/cm36651.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/iio/light/cm36651.txt b/Documentation/devicetree/bindings/iio/light/cm36651.txt new file mode 100644 index 000000000000..c03e19db4550 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/light/cm36651.txt @@ -0,0 +1,26 @@ +* Capella CM36651 I2C Proximity and Color Light sensor + +Required properties: +- compatible: must be "capella,cm36651" +- reg: the I2C address of the device +- interrupts: interrupt-specifier for the sole interrupt + generated by the device +- vled-supply: regulator for the IR LED. IR_LED is a part + of the cm36651 for proximity detection. + As covered in ../../regulator/regulator.txt + +Example: + + i2c_cm36651: i2c-gpio { + /* ... */ + + cm36651@18 { + compatible = "capella,cm36651"; + reg = <0x18>; + interrupt-parent = <&gpx0>; + interrupts = <2 0>; + vled-supply = <&ps_als_reg>; + }; + + /* ... */ + }; diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 2956800f0240..04eab45dd148 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -15,6 +15,7 @@ atmel Atmel Corporation avago Avago Technologies bosch Bosch Sensortec GmbH brcm Broadcom Corporation +capella Capella Microsystems, Inc cavium Cavium, Inc. chrp Common Hardware Reference Platform cirrus Cirrus Logic, Inc. -- cgit v1.2.3 From c8b11de0404d318c4a67bf6b9066663b9d93786c Mon Sep 17 00:00:00 2001 From: Josh Wu Date: Tue, 8 Oct 2013 04:48:00 +0100 Subject: iio: at91: introduce touch screen support in iio adc driver AT91 ADC hardware integrate touch screen support. So this patch add touch screen support for at91 adc iio driver. To enable touch screen support in adc, you need to add the dt parameters: 1. which type of touch are used? (4 or 5 wires), sample period time. 2. correct pressure detect threshold value. In the meantime, since touch screen will use a interal period trigger of adc, so it is conflict to other hardware triggers. Driver will disable the hardware trigger support if touch screen is enabled. This driver has been tested in AT91SAM9X5-EK and SAMA5D3x-EK. Signed-off-by: Josh Wu Acked-by: Dmitry Torokhov CC: devicetree@vger.kernel.org Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/arm/atmel-adc.txt | 7 + arch/arm/mach-at91/include/mach/at91_adc.h | 34 ++ drivers/iio/adc/at91_adc.c | 388 +++++++++++++++++++-- 3 files changed, 405 insertions(+), 24 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/arm/atmel-adc.txt b/Documentation/devicetree/bindings/arm/atmel-adc.txt index 0e65e0137487..d1061469f63d 100644 --- a/Documentation/devicetree/bindings/arm/atmel-adc.txt +++ b/Documentation/devicetree/bindings/arm/atmel-adc.txt @@ -23,6 +23,13 @@ Optional properties: resolution will be used. - atmel,adc-sleep-mode: Boolean to enable sleep mode when no conversion - atmel,adc-sample-hold-time: Sample and Hold Time in microseconds + - atmel,adc-ts-wires: Number of touch screen wires. Should be 4 or 5. If this + value is set, then adc driver will enable touch screen + support. + NOTE: when adc touch screen enabled, the adc hardware trigger will be + disabled. Since touch screen will occupied the trigger register. + - atmel,adc-ts-pressure-threshold: a pressure threshold for touchscreen. It + make touch detect more precision. Optional trigger Nodes: - Required properties: diff --git a/arch/arm/mach-at91/include/mach/at91_adc.h b/arch/arm/mach-at91/include/mach/at91_adc.h index 048a57f76bd3..c287307b9a3b 100644 --- a/arch/arm/mach-at91/include/mach/at91_adc.h +++ b/arch/arm/mach-at91/include/mach/at91_adc.h @@ -60,14 +60,48 @@ #define AT91_ADC_IER 0x24 /* Interrupt Enable Register */ #define AT91_ADC_IDR 0x28 /* Interrupt Disable Register */ #define AT91_ADC_IMR 0x2C /* Interrupt Mask Register */ +#define AT91_ADC_IER_PEN (1 << 29) +#define AT91_ADC_IER_NOPEN (1 << 30) +#define AT91_ADC_IER_XRDY (1 << 20) +#define AT91_ADC_IER_YRDY (1 << 21) +#define AT91_ADC_IER_PRDY (1 << 22) +#define AT91_ADC_ISR_PENS (1 << 31) #define AT91_ADC_CHR(n) (0x30 + ((n) * 4)) /* Channel Data Register N */ #define AT91_ADC_DATA (0x3ff) #define AT91_ADC_CDR0_9X5 (0x50) /* Channel Data Register 0 for 9X5 */ +#define AT91_ADC_ACR 0x94 /* Analog Control Register */ +#define AT91_ADC_ACR_PENDETSENS (0x3 << 0) /* pull-up resistor */ + +#define AT91_ADC_TSMR 0xB0 +#define AT91_ADC_TSMR_TSMODE (3 << 0) /* Touch Screen Mode */ +#define AT91_ADC_TSMR_TSMODE_NONE (0 << 0) +#define AT91_ADC_TSMR_TSMODE_4WIRE_NO_PRESS (1 << 0) +#define AT91_ADC_TSMR_TSMODE_4WIRE_PRESS (2 << 0) +#define AT91_ADC_TSMR_TSMODE_5WIRE (3 << 0) +#define AT91_ADC_TSMR_TSAV (3 << 4) /* Averages samples */ +#define AT91_ADC_TSMR_TSAV_(x) ((x) << 4) +#define AT91_ADC_TSMR_SCTIM (0x0f << 16) /* Switch closure time */ +#define AT91_ADC_TSMR_PENDBC (0x0f << 28) /* Pen Debounce time */ +#define AT91_ADC_TSMR_PENDBC_(x) ((x) << 28) +#define AT91_ADC_TSMR_NOTSDMA (1 << 22) /* No Touchscreen DMA */ +#define AT91_ADC_TSMR_PENDET_DIS (0 << 24) /* Pen contact detection disable */ +#define AT91_ADC_TSMR_PENDET_ENA (1 << 24) /* Pen contact detection enable */ + +#define AT91_ADC_TSXPOSR 0xB4 +#define AT91_ADC_TSYPOSR 0xB8 +#define AT91_ADC_TSPRESSR 0xBC + #define AT91_ADC_TRGR_9260 AT91_ADC_MR #define AT91_ADC_TRGR_9G45 0x08 #define AT91_ADC_TRGR_9X5 0xC0 +/* Trigger Register bit field */ +#define AT91_ADC_TRGR_TRGPER (0xffff << 16) +#define AT91_ADC_TRGR_TRGPER_(x) ((x) << 16) +#define AT91_ADC_TRGR_TRGMOD (0x7 << 0) +#define AT91_ADC_TRGR_MOD_PERIOD_TRIG (5 << 0) + #endif diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index 690a560e0dab..17df74908db1 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -39,7 +40,23 @@ #define at91_adc_writel(st, reg, val) \ (writel_relaxed(val, st->reg_base + reg)) +#define DRIVER_NAME "at91_adc" +#define MAX_POS_BITS 12 + +#define TOUCH_SAMPLE_PERIOD_US 2000 /* 2ms */ +#define TOUCH_PEN_DETECT_DEBOUNCE_US 200 + struct at91_adc_caps { + bool has_ts; /* Support touch screen */ + bool has_tsmr; /* only at91sam9x5, sama5d3 have TSMR reg */ + /* + * Numbers of sampling data will be averaged. Can be 0~3. + * Hardware can average (2 ^ ts_filter_average) sample data. + */ + u8 ts_filter_average; + /* Pen Detection input pull-up resistor, can be 0~3 */ + u8 ts_pen_detect_sensitivity; + /* startup time calculate function */ u32 (*calc_startup_ticks)(u8 startup_time, u32 adc_clk_khz); @@ -47,6 +64,12 @@ struct at91_adc_caps { struct at91_adc_reg_desc registers; }; +enum atmel_adc_ts_type { + ATMEL_ADC_TOUCHSCREEN_NONE = 0, + ATMEL_ADC_TOUCHSCREEN_4WIRE = 4, + ATMEL_ADC_TOUCHSCREEN_5WIRE = 5, +}; + struct at91_adc_state { struct clk *adc_clk; u16 *buffer; @@ -71,6 +94,26 @@ struct at91_adc_state { bool low_res; /* the resolution corresponds to the lowest one */ wait_queue_head_t wq_data_avail; struct at91_adc_caps *caps; + + /* + * Following ADC channels are shared by touchscreen: + * + * CH0 -- Touch screen XP/UL + * CH1 -- Touch screen XM/UR + * CH2 -- Touch screen YP/LL + * CH3 -- Touch screen YM/Sense + * CH4 -- Touch screen LR(5-wire only) + * + * The bitfields below represents the reserved channel in the + * touchscreen mode. + */ +#define CHAN_MASK_TOUCHSCREEN_4WIRE (0xf << 0) +#define CHAN_MASK_TOUCHSCREEN_5WIRE (0x1f << 0) + enum atmel_adc_ts_type touchscreen_type; + struct input_dev *ts_input; + + u16 ts_sample_period_val; + u32 ts_pressure_threshold; }; static irqreturn_t at91_adc_trigger_handler(int irq, void *p) @@ -99,14 +142,10 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p) return IRQ_HANDLED; } -static irqreturn_t at91_adc_eoc_trigger(int irq, void *private) +/* Handler for classic adc channel eoc trigger */ +void handle_adc_eoc_trigger(int irq, struct iio_dev *idev) { - struct iio_dev *idev = private; struct at91_adc_state *st = iio_priv(idev); - u32 status = at91_adc_readl(st, st->registers->status_register); - - if (!(status & st->registers->drdy_mask)) - return IRQ_HANDLED; if (iio_buffer_enabled(idev)) { disable_irq_nosync(irq); @@ -116,6 +155,115 @@ static irqreturn_t at91_adc_eoc_trigger(int irq, void *private) st->done = true; wake_up_interruptible(&st->wq_data_avail); } +} + +static int at91_ts_sample(struct at91_adc_state *st) +{ + unsigned int xscale, yscale, reg, z1, z2; + unsigned int x, y, pres, xpos, ypos; + unsigned int rxp = 1; + unsigned int factor = 1000; + struct iio_dev *idev = iio_priv_to_dev(st); + + unsigned int xyz_mask_bits = st->res; + unsigned int xyz_mask = (1 << xyz_mask_bits) - 1; + + /* calculate position */ + /* x position = (x / xscale) * max, max = 2^MAX_POS_BITS - 1 */ + reg = at91_adc_readl(st, AT91_ADC_TSXPOSR); + xpos = reg & xyz_mask; + x = (xpos << MAX_POS_BITS) - xpos; + xscale = (reg >> 16) & xyz_mask; + if (xscale == 0) { + dev_err(&idev->dev, "Error: xscale == 0!\n"); + return -1; + } + x /= xscale; + + /* y position = (y / yscale) * max, max = 2^MAX_POS_BITS - 1 */ + reg = at91_adc_readl(st, AT91_ADC_TSYPOSR); + ypos = reg & xyz_mask; + y = (ypos << MAX_POS_BITS) - ypos; + yscale = (reg >> 16) & xyz_mask; + if (yscale == 0) { + dev_err(&idev->dev, "Error: yscale == 0!\n"); + return -1; + } + y /= yscale; + + /* calculate the pressure */ + reg = at91_adc_readl(st, AT91_ADC_TSPRESSR); + z1 = reg & xyz_mask; + z2 = (reg >> 16) & xyz_mask; + + if (z1 != 0) + pres = rxp * (x * factor / 1024) * (z2 * factor / z1 - factor) + / factor; + else + pres = st->ts_pressure_threshold; /* no pen contacted */ + + dev_dbg(&idev->dev, "xpos = %d, xscale = %d, ypos = %d, yscale = %d, z1 = %d, z2 = %d, press = %d\n", + xpos, xscale, ypos, yscale, z1, z2, pres); + + if (pres < st->ts_pressure_threshold) { + dev_dbg(&idev->dev, "x = %d, y = %d, pressure = %d\n", + x, y, pres / factor); + input_report_abs(st->ts_input, ABS_X, x); + input_report_abs(st->ts_input, ABS_Y, y); + input_report_abs(st->ts_input, ABS_PRESSURE, pres); + input_report_key(st->ts_input, BTN_TOUCH, 1); + input_sync(st->ts_input); + } else { + dev_dbg(&idev->dev, "pressure too low: not reporting\n"); + } + + return 0; +} + +static irqreturn_t at91_adc_interrupt(int irq, void *private) +{ + struct iio_dev *idev = private; + struct at91_adc_state *st = iio_priv(idev); + u32 status = at91_adc_readl(st, st->registers->status_register); + const uint32_t ts_data_irq_mask = + AT91_ADC_IER_XRDY | + AT91_ADC_IER_YRDY | + AT91_ADC_IER_PRDY; + + if (status & st->registers->drdy_mask) + handle_adc_eoc_trigger(irq, idev); + + if (status & AT91_ADC_IER_PEN) { + at91_adc_writel(st, AT91_ADC_IDR, AT91_ADC_IER_PEN); + at91_adc_writel(st, AT91_ADC_IER, AT91_ADC_IER_NOPEN | + ts_data_irq_mask); + /* Set up period trigger for sampling */ + at91_adc_writel(st, st->registers->trigger_register, + AT91_ADC_TRGR_MOD_PERIOD_TRIG | + AT91_ADC_TRGR_TRGPER_(st->ts_sample_period_val)); + } else if (status & AT91_ADC_IER_NOPEN) { + at91_adc_writel(st, st->registers->trigger_register, 0); + at91_adc_writel(st, AT91_ADC_IDR, AT91_ADC_IER_NOPEN | + ts_data_irq_mask); + at91_adc_writel(st, AT91_ADC_IER, AT91_ADC_IER_PEN); + + input_report_key(st->ts_input, BTN_TOUCH, 0); + input_sync(st->ts_input); + } else if ((status & ts_data_irq_mask) == ts_data_irq_mask) { + /* Now all touchscreen data is ready */ + + if (status & AT91_ADC_ISR_PENS) { + /* validate data by pen contact */ + at91_ts_sample(st); + } else { + /* triggered by event that is no pen contact, just read + * them to clean the interrupt and discard all. + */ + at91_adc_readl(st, AT91_ADC_TSXPOSR); + at91_adc_readl(st, AT91_ADC_TSYPOSR); + at91_adc_readl(st, AT91_ADC_TSPRESSR); + } + } return IRQ_HANDLED; } @@ -125,6 +273,16 @@ static int at91_adc_channel_init(struct iio_dev *idev) struct at91_adc_state *st = iio_priv(idev); struct iio_chan_spec *chan_array, *timestamp; int bit, idx = 0; + unsigned long rsvd_mask = 0; + + /* If touchscreen is enable, then reserve the adc channels */ + if (st->touchscreen_type == ATMEL_ADC_TOUCHSCREEN_4WIRE) + rsvd_mask = CHAN_MASK_TOUCHSCREEN_4WIRE; + else if (st->touchscreen_type == ATMEL_ADC_TOUCHSCREEN_5WIRE) + rsvd_mask = CHAN_MASK_TOUCHSCREEN_5WIRE; + + /* set up the channel mask to reserve touchscreen channels */ + st->channels_mask &= ~rsvd_mask; idev->num_channels = bitmap_weight(&st->channels_mask, st->num_channels) + 1; @@ -473,6 +631,39 @@ static u32 calc_startup_ticks_9x5(u8 startup_time, u32 adc_clk_khz) static const struct of_device_id at91_adc_dt_ids[]; +static int at91_adc_probe_dt_ts(struct device_node *node, + struct at91_adc_state *st, struct device *dev) +{ + int ret; + u32 prop; + + ret = of_property_read_u32(node, "atmel,adc-ts-wires", &prop); + if (ret) { + dev_info(dev, "ADC Touch screen is disabled.\n"); + return 0; + } + + switch (prop) { + case 4: + case 5: + st->touchscreen_type = prop; + break; + default: + dev_err(dev, "Unsupported number of touchscreen wires (%d). Should be 4 or 5.\n", prop); + return -EINVAL; + } + + prop = 0; + of_property_read_u32(node, "atmel,adc-ts-pressure-threshold", &prop); + st->ts_pressure_threshold = prop; + if (st->ts_pressure_threshold) { + return 0; + } else { + dev_err(dev, "Invalid pressure threshold for the touchscreen\n"); + return -EINVAL; + } +} + static int at91_adc_probe_dt(struct at91_adc_state *st, struct platform_device *pdev) { @@ -554,6 +745,12 @@ static int at91_adc_probe_dt(struct at91_adc_state *st, i++; } + /* Check if touchscreen is supported. */ + if (st->caps->has_ts) + return at91_adc_probe_dt_ts(node, st, &idev->dev); + else + dev_info(&idev->dev, "not support touchscreen in the adc compatible string.\n"); + return 0; error_ret: @@ -585,6 +782,114 @@ static const struct iio_info at91_adc_info = { .read_raw = &at91_adc_read_raw, }; +/* Touchscreen related functions */ +static int atmel_ts_open(struct input_dev *dev) +{ + struct at91_adc_state *st = input_get_drvdata(dev); + + at91_adc_writel(st, AT91_ADC_IER, AT91_ADC_IER_PEN); + return 0; +} + +static void atmel_ts_close(struct input_dev *dev) +{ + struct at91_adc_state *st = input_get_drvdata(dev); + + at91_adc_writel(st, AT91_ADC_IDR, AT91_ADC_IER_PEN); +} + +static int at91_ts_hw_init(struct at91_adc_state *st, u32 adc_clk_khz) +{ + u32 reg = 0, pendbc; + int i = 0; + + if (st->touchscreen_type == ATMEL_ADC_TOUCHSCREEN_4WIRE) + reg = AT91_ADC_TSMR_TSMODE_4WIRE_PRESS; + else + reg = AT91_ADC_TSMR_TSMODE_5WIRE; + + /* a Pen Detect Debounce Time is necessary for the ADC Touch to avoid + * pen detect noise. + * The formula is : Pen Detect Debounce Time = (2 ^ pendbc) / ADCClock + */ + pendbc = round_up(TOUCH_PEN_DETECT_DEBOUNCE_US * adc_clk_khz / 1000, 1); + + while (pendbc >> ++i) + ; /* Empty! Find the shift offset */ + if (abs(pendbc - (1 << i)) < abs(pendbc - (1 << (i - 1)))) + pendbc = i; + else + pendbc = i - 1; + + if (st->caps->has_tsmr) { + reg |= AT91_ADC_TSMR_TSAV_(st->caps->ts_filter_average) + & AT91_ADC_TSMR_TSAV; + reg |= AT91_ADC_TSMR_PENDBC_(pendbc) & AT91_ADC_TSMR_PENDBC; + reg |= AT91_ADC_TSMR_NOTSDMA; + reg |= AT91_ADC_TSMR_PENDET_ENA; + reg |= 0x03 << 8; /* TSFREQ, need bigger than TSAV */ + + at91_adc_writel(st, AT91_ADC_TSMR, reg); + } else { + /* TODO: for 9g45 which has no TSMR */ + } + + /* Change adc internal resistor value for better pen detection, + * default value is 100 kOhm. + * 0 = 200 kOhm, 1 = 150 kOhm, 2 = 100 kOhm, 3 = 50 kOhm + * option only available on ES2 and higher + */ + at91_adc_writel(st, AT91_ADC_ACR, st->caps->ts_pen_detect_sensitivity + & AT91_ADC_ACR_PENDETSENS); + + /* Sample Peroid Time = (TRGPER + 1) / ADCClock */ + st->ts_sample_period_val = round_up((TOUCH_SAMPLE_PERIOD_US * + adc_clk_khz / 1000) - 1, 1); + + return 0; +} + +static int at91_ts_register(struct at91_adc_state *st, + struct platform_device *pdev) +{ + struct input_dev *input; + struct iio_dev *idev = iio_priv_to_dev(st); + int ret; + + input = input_allocate_device(); + if (!input) { + dev_err(&idev->dev, "Failed to allocate TS device!\n"); + return -ENOMEM; + } + + input->name = DRIVER_NAME; + input->id.bustype = BUS_HOST; + input->dev.parent = &pdev->dev; + input->open = atmel_ts_open; + input->close = atmel_ts_close; + + __set_bit(EV_ABS, input->evbit); + __set_bit(EV_KEY, input->evbit); + __set_bit(BTN_TOUCH, input->keybit); + input_set_abs_params(input, ABS_X, 0, (1 << MAX_POS_BITS) - 1, 0, 0); + input_set_abs_params(input, ABS_Y, 0, (1 << MAX_POS_BITS) - 1, 0, 0); + input_set_abs_params(input, ABS_PRESSURE, 0, 0xffffff, 0, 0); + + st->ts_input = input; + input_set_drvdata(input, st); + + ret = input_register_device(input); + if (ret) + input_free_device(st->ts_input); + + return ret; +} + +static void at91_ts_unregister(struct at91_adc_state *st) +{ + input_unregister_device(st->ts_input); +} + static int at91_adc_probe(struct platform_device *pdev) { unsigned int prsc, mstrclk, ticks, adc_clk, adc_clk_khz, shtim; @@ -636,7 +941,7 @@ static int at91_adc_probe(struct platform_device *pdev) at91_adc_writel(st, AT91_ADC_CR, AT91_ADC_SWRST); at91_adc_writel(st, AT91_ADC_IDR, 0xFFFFFFFF); ret = request_irq(st->irq, - at91_adc_eoc_trigger, + at91_adc_interrupt, 0, pdev->dev.driver->name, idev); @@ -681,6 +986,10 @@ static int at91_adc_probe(struct platform_device *pdev) mstrclk = clk_get_rate(st->clk); adc_clk = clk_get_rate(st->adc_clk); adc_clk_khz = adc_clk / 1000; + + dev_dbg(&pdev->dev, "Master clock is set as: %d Hz, adc_clk should set as: %d Hz\n", + mstrclk, adc_clk); + prsc = (mstrclk / (2 * adc_clk)) - 1; if (!st->startup_time) { @@ -717,30 +1026,52 @@ static int at91_adc_probe(struct platform_device *pdev) init_waitqueue_head(&st->wq_data_avail); mutex_init(&st->lock); - ret = at91_adc_buffer_init(idev); - if (ret < 0) { - dev_err(&pdev->dev, "Couldn't initialize the buffer.\n"); - goto error_disable_adc_clk; - } + /* + * Since touch screen will set trigger register as period trigger. So + * when touch screen is enabled, then we have to disable hardware + * trigger for classic adc. + */ + if (!st->touchscreen_type) { + ret = at91_adc_buffer_init(idev); + if (ret < 0) { + dev_err(&pdev->dev, "Couldn't initialize the buffer.\n"); + goto error_disable_adc_clk; + } - ret = at91_adc_trigger_init(idev); - if (ret < 0) { - dev_err(&pdev->dev, "Couldn't setup the triggers.\n"); - goto error_unregister_buffer; + ret = at91_adc_trigger_init(idev); + if (ret < 0) { + dev_err(&pdev->dev, "Couldn't setup the triggers.\n"); + at91_adc_buffer_remove(idev); + goto error_disable_adc_clk; + } + } else { + if (!st->caps->has_tsmr) { + dev_err(&pdev->dev, "We don't support non-TSMR adc\n"); + goto error_disable_adc_clk; + } + + ret = at91_ts_register(st, pdev); + if (ret) + goto error_disable_adc_clk; + + at91_ts_hw_init(st, adc_clk_khz); } ret = iio_device_register(idev); if (ret < 0) { dev_err(&pdev->dev, "Couldn't register the device.\n"); - goto error_remove_triggers; + goto error_iio_device_register; } return 0; -error_remove_triggers: - at91_adc_trigger_remove(idev); -error_unregister_buffer: - at91_adc_buffer_remove(idev); +error_iio_device_register: + if (!st->touchscreen_type) { + at91_adc_trigger_remove(idev); + at91_adc_buffer_remove(idev); + } else { + at91_ts_unregister(st); + } error_disable_adc_clk: clk_disable_unprepare(st->adc_clk); error_disable_clk: @@ -756,8 +1087,12 @@ static int at91_adc_remove(struct platform_device *pdev) struct at91_adc_state *st = iio_priv(idev); iio_device_unregister(idev); - at91_adc_trigger_remove(idev); - at91_adc_buffer_remove(idev); + if (!st->touchscreen_type) { + at91_adc_trigger_remove(idev); + at91_adc_buffer_remove(idev); + } else { + at91_ts_unregister(st); + } clk_disable_unprepare(st->adc_clk); clk_disable_unprepare(st->clk); free_irq(st->irq, idev); @@ -780,6 +1115,7 @@ static struct at91_adc_caps at91sam9260_caps = { }; static struct at91_adc_caps at91sam9g45_caps = { + .has_ts = true, .calc_startup_ticks = calc_startup_ticks_9260, /* same as 9260 */ .num_channels = 8, .registers = { @@ -793,6 +1129,10 @@ static struct at91_adc_caps at91sam9g45_caps = { }; static struct at91_adc_caps at91sam9x5_caps = { + .has_ts = true, + .has_tsmr = true, + .ts_filter_average = 3, + .ts_pen_detect_sensitivity = 2, .calc_startup_ticks = calc_startup_ticks_9x5, .num_channels = 12, .registers = { @@ -819,7 +1159,7 @@ static struct platform_driver at91_adc_driver = { .probe = at91_adc_probe, .remove = at91_adc_remove, .driver = { - .name = "at91_adc", + .name = DRIVER_NAME, .of_match_table = of_match_ptr(at91_adc_dt_ids), }, }; -- cgit v1.2.3