diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-11 09:32:08 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-11 09:32:08 -0800 |
commit | 718749d56214aa97015fe01b76b6d6dd0c171796 (patch) | |
tree | 2f7355a3527c5579dc76721203d8a0011a40b19b /drivers/input/touchscreen/sun4i-ts.c | |
parent | e0c8453769fcaec654cd5870e84c63175658c842 (diff) | |
parent | 4ba24fef3eb3b142197135223b90ced2f319cd53 (diff) | |
download | linux-718749d56214aa97015fe01b76b6d6dd0c171796.tar.gz |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input updates from Dmitry Torokhov:
"The first round of updates for the input subsystem.
A few new drivers (power button handler for AXP20x PMIC, tps65218
power button driver, sun4i keys driver, regulator haptic driver, NI
Ettus Research USRP E3x0 button, Alwinner A10/A20 PS/2 controller).
Updates to Synaptics and ALPS touchpad drivers (with more to come
later), brand new Focaltech PS/2 support, update to Cypress driver to
handle Gen5 (in addition to Gen3) devices, and number of other fixups
to various drivers as well as input core"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (54 commits)
Input: elan_i2c - fix wrong %p extension
Input: evdev - do not queue SYN_DROPPED if queue is empty
Input: gscps2 - fix MODULE_DEVICE_TABLE invocation
Input: synaptics - use dmax in input_mt_assign_slots
Input: pxa27x_keypad - remove unnecessary ARM includes
Input: ti_am335x_tsc - replace delta filtering with median filtering
ARM: dts: AM335x: Make charge delay a DT parameter for TSC
Input: ti_am335x_tsc - read charge delay from DT
Input: ti_am335x_tsc - remove udelay in interrupt handler
Input: ti_am335x_tsc - interchange touchscreen and ADC steps
Input: MT - add support for balanced slot assignment
Input: drv2667 - remove wrong and unneeded drv2667-haptics modalias
Input: drv260x - remove wrong and unneeded drv260x-haptics modalias
Input: cap11xx - remove wrong and unneeded cap11xx modalias
Input: sun4i-ts - add support for touchpanel controller on A31
Input: serio - add support for Alwinner A10/A20 PS/2 controller
Input: gtco - use sign_extend32() for sign extension
Input: elan_i2c - verify firmware signature applying it
Input: elantech - remove stale comment from Kconfig
Input: cyapa - off by one in cyapa_update_fw_store()
...
Diffstat (limited to 'drivers/input/touchscreen/sun4i-ts.c')
-rw-r--r-- | drivers/input/touchscreen/sun4i-ts.c | 78 |
1 files changed, 72 insertions, 6 deletions
diff --git a/drivers/input/touchscreen/sun4i-ts.c b/drivers/input/touchscreen/sun4i-ts.c index 28a06749ae42..b93a28b955fd 100644 --- a/drivers/input/touchscreen/sun4i-ts.c +++ b/drivers/input/touchscreen/sun4i-ts.c @@ -34,6 +34,7 @@ #include <linux/err.h> #include <linux/hwmon.h> +#include <linux/thermal.h> #include <linux/init.h> #include <linux/input.h> #include <linux/interrupt.h> @@ -71,6 +72,9 @@ #define TP_ADC_SELECT(x) ((x) << 3) #define ADC_CHAN_SELECT(x) ((x) << 0) /* 3 bits */ +/* on sun6i, bits 3~6 are left shifted by 1 to 4~7 */ +#define SUN6I_TP_MODE_EN(x) ((x) << 5) + /* TP_CTRL2 bits */ #define TP_SENSITIVE_ADJUST(x) ((x) << 28) /* 4 bits */ #define TP_MODE_SELECT(x) ((x) << 26) /* 2 bits */ @@ -107,10 +111,13 @@ struct sun4i_ts_data { struct device *dev; struct input_dev *input; + struct thermal_zone_device *tz; void __iomem *base; unsigned int irq; bool ignore_fifo_data; int temp_data; + int temp_offset; + int temp_step; }; static void sun4i_ts_irq_handle_input(struct sun4i_ts_data *ts, u32 reg_val) @@ -180,16 +187,38 @@ static void sun4i_ts_close(struct input_dev *dev) writel(TEMP_IRQ_EN(1), ts->base + TP_INT_FIFOC); } +static int sun4i_get_temp(const struct sun4i_ts_data *ts, long *temp) +{ + /* No temp_data until the first irq */ + if (ts->temp_data == -1) + return -EAGAIN; + + *temp = (ts->temp_data - ts->temp_offset) * ts->temp_step; + + return 0; +} + +static int sun4i_get_tz_temp(void *data, long *temp) +{ + return sun4i_get_temp(data, temp); +} + +static struct thermal_zone_of_device_ops sun4i_ts_tz_ops = { + .get_temp = sun4i_get_tz_temp, +}; + static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, char *buf) { struct sun4i_ts_data *ts = dev_get_drvdata(dev); + long temp; + int error; - /* No temp_data until the first irq */ - if (ts->temp_data == -1) - return -EAGAIN; + error = sun4i_get_temp(ts, &temp); + if (error) + return error; - return sprintf(buf, "%d\n", (ts->temp_data - 1447) * 100); + return sprintf(buf, "%ld\n", temp); } static ssize_t show_temp_label(struct device *dev, @@ -215,6 +244,7 @@ static int sun4i_ts_probe(struct platform_device *pdev) struct device_node *np = dev->of_node; struct device *hwmon; int error; + u32 reg; bool ts_attached; ts = devm_kzalloc(dev, sizeof(struct sun4i_ts_data), GFP_KERNEL); @@ -224,6 +254,25 @@ static int sun4i_ts_probe(struct platform_device *pdev) ts->dev = dev; ts->ignore_fifo_data = true; ts->temp_data = -1; + if (of_device_is_compatible(np, "allwinner,sun6i-a31-ts")) { + /* Allwinner SDK has temperature = -271 + (value / 6) (C) */ + ts->temp_offset = 1626; + ts->temp_step = 167; + } else { + /* + * The user manuals do not contain the formula for calculating + * the temperature. The formula used here is from the AXP209, + * which is designed by X-Powers, an affiliate of Allwinner: + * + * temperature = -144.7 + (value * 0.1) + * + * Allwinner does not have any documentation whatsoever for + * this hardware. Moreover, it is claimed that the sensor + * is inaccurate and cannot work properly. + */ + ts->temp_offset = 1447; + ts->temp_step = 100; + } ts_attached = of_property_read_bool(np, "allwinner,ts-attached"); if (ts_attached) { @@ -280,20 +329,34 @@ static int sun4i_ts_probe(struct platform_device *pdev) * Set stylus up debounce to aprox 10 ms, enable debounce, and * finally enable tp mode. */ - writel(STYLUS_UP_DEBOUN(5) | STYLUS_UP_DEBOUN_EN(1) | TP_MODE_EN(1), - ts->base + TP_CTRL1); + reg = STYLUS_UP_DEBOUN(5) | STYLUS_UP_DEBOUN_EN(1); + if (of_device_is_compatible(np, "allwinner,sun4i-a10-ts")) + reg |= TP_MODE_EN(1); + else + reg |= SUN6I_TP_MODE_EN(1); + writel(reg, ts->base + TP_CTRL1); + /* + * The thermal core does not register hwmon devices for DT-based + * thermal zone sensors, such as this one. + */ hwmon = devm_hwmon_device_register_with_groups(ts->dev, "sun4i_ts", ts, sun4i_ts_groups); if (IS_ERR(hwmon)) return PTR_ERR(hwmon); + ts->tz = thermal_zone_of_sensor_register(ts->dev, 0, ts, + &sun4i_ts_tz_ops); + if (IS_ERR(ts->tz)) + ts->tz = NULL; + writel(TEMP_IRQ_EN(1), ts->base + TP_INT_FIFOC); if (ts_attached) { error = input_register_device(ts->input); if (error) { writel(0, ts->base + TP_INT_FIFOC); + thermal_zone_of_sensor_unregister(ts->dev, ts->tz); return error; } } @@ -310,6 +373,8 @@ static int sun4i_ts_remove(struct platform_device *pdev) if (ts->input) input_unregister_device(ts->input); + thermal_zone_of_sensor_unregister(ts->dev, ts->tz); + /* Deactivate all IRQs */ writel(0, ts->base + TP_INT_FIFOC); @@ -318,6 +383,7 @@ static int sun4i_ts_remove(struct platform_device *pdev) static const struct of_device_id sun4i_ts_of_match[] = { { .compatible = "allwinner,sun4i-a10-ts", }, + { .compatible = "allwinner,sun6i-a31-ts", }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, sun4i_ts_of_match); |