Loading Documentation/devicetree/bindings/input/touchscreen/tsc2007.txt 0 → 100644 +41 −0 Original line number Diff line number Diff line * Texas Instruments tsc2007 touchscreen controller Required properties: - compatible: must be "ti,tsc2007". - reg: I2C address of the chip. - ti,x-plate-ohms: X-plate resistance in ohms. Optional properties: - gpios: the interrupt gpio the chip is connected to (trough the penirq pin). The penirq pin goes to low when the panel is touched. (see GPIO binding[1] for more details). - interrupt-parent: the phandle for the gpio controller (see interrupt binding[0]). - interrupts: (gpio) interrupt to which the chip is connected (see interrupt binding[0]). - ti,max-rt: maximum pressure. - ti,fuzzx: specifies the absolute input fuzz x value. If set, it will permit noise in the data up to +- the value given to the fuzz parameter, that is used to filter noise from the event stream. - ti,fuzzy: specifies the absolute input fuzz y value. - ti,fuzzz: specifies the absolute input fuzz z value. - ti,poll-period: how much time to wait (in milliseconds) before reading again the values from the tsc2007. [0]: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt [1]: Documentation/devicetree/bindings/gpio/gpio.txt Example: &i2c1 { /* ... */ tsc2007@49 { compatible = "ti,tsc2007"; reg = <0x49>; interrupt-parent = <&gpio4>; interrupts = <0x0 0x8>; gpios = <&gpio4 0 0>; ti,x-plate-ohms = <180>; }; /* ... */ }; arch/arm/mach-imx/mach-cpuimx35.c +1 −1 Original line number Diff line number Diff line Loading @@ -53,7 +53,7 @@ static const struct imxi2c_platform_data }; #define TSC2007_IRQGPIO IMX_GPIO_NR(3, 2) static int tsc2007_get_pendown_state(void) static int tsc2007_get_pendown_state(struct device *dev) { return !gpio_get_value(TSC2007_IRQGPIO); } Loading arch/arm/mach-imx/mach-cpuimx51sd.c +1 −1 Original line number Diff line number Diff line Loading @@ -121,7 +121,7 @@ static const struct imxuart_platform_data uart_pdata __initconst = { .flags = IMXUART_HAVE_RTSCTS, }; static int tsc2007_get_pendown_state(void) static int tsc2007_get_pendown_state(struct device *dev) { if (mx51_revision() < IMX_CHIP_REVISION_3_0) return !gpio_get_value(TSC2007_IRQGPIO_REV2); Loading arch/sh/boards/mach-ecovec24/setup.c +1 −1 Original line number Diff line number Diff line Loading @@ -501,7 +501,7 @@ static struct platform_device keysc_device = { /* TouchScreen */ #define IRQ0 evt2irq(0x600) static int ts_get_pendown_state(void) static int ts_get_pendown_state(struct device *dev) { int val = 0; gpio_free(GPIO_FN_INTC_IRQ0); Loading drivers/input/touchscreen/tsc2007.c +133 −40 Original line number Diff line number Diff line Loading @@ -26,6 +26,9 @@ #include <linux/interrupt.h> #include <linux/i2c.h> #include <linux/i2c/tsc2007.h> #include <linux/of_device.h> #include <linux/of.h> #include <linux/of_gpio.h> #define TSC2007_MEASURE_TEMP0 (0x0 << 4) #define TSC2007_MEASURE_AUX (0x2 << 4) Loading Loading @@ -74,13 +77,17 @@ struct tsc2007 { u16 max_rt; unsigned long poll_delay; unsigned long poll_period; int fuzzx; int fuzzy; int fuzzz; unsigned gpio; int irq; wait_queue_head_t wait; bool stopped; int (*get_pendown_state)(void); int (*get_pendown_state)(struct device *); void (*clear_penirq)(void); }; Loading Loading @@ -161,7 +168,7 @@ static bool tsc2007_is_pen_down(struct tsc2007 *ts) if (!ts->get_pendown_state) return true; return ts->get_pendown_state(); return ts->get_pendown_state(&ts->client->dev); } static irqreturn_t tsc2007_soft_irq(int irq, void *handle) Loading @@ -178,7 +185,7 @@ static irqreturn_t tsc2007_soft_irq(int irq, void *handle) rt = tsc2007_calculate_pressure(ts, &tc); if (rt == 0 && !ts->get_pendown_state) { if (!rt && !ts->get_pendown_state) { /* * If pressure reported is 0 and we don't have * callback to check pendown state, we have to Loading Loading @@ -228,7 +235,7 @@ static irqreturn_t tsc2007_hard_irq(int irq, void *handle) { struct tsc2007 *ts = handle; if (!ts->get_pendown_state || likely(ts->get_pendown_state())) if (tsc2007_is_pen_down(ts)) return IRQ_WAKE_THREAD; if (ts->clear_penirq) Loading Loading @@ -273,35 +280,74 @@ static void tsc2007_close(struct input_dev *input_dev) tsc2007_stop(ts); } static int tsc2007_probe(struct i2c_client *client, const struct i2c_device_id *id) #ifdef CONFIG_OF static int tsc2007_get_pendown_state_gpio(struct device *dev) { struct tsc2007 *ts; struct tsc2007_platform_data *pdata = client->dev.platform_data; struct input_dev *input_dev; int err; struct i2c_client *client = to_i2c_client(dev); struct tsc2007 *ts = i2c_get_clientdata(client); if (!pdata) { dev_err(&client->dev, "platform data is required!\n"); return !gpio_get_value(ts->gpio); } static int tsc2007_probe_dt(struct i2c_client *client, struct tsc2007 *ts) { struct device_node *np = client->dev.of_node; u32 val32; u64 val64; if (!np) { dev_err(&client->dev, "missing device tree data\n"); return -EINVAL; } if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_WORD_DATA)) return -EIO; if (!of_property_read_u32(np, "ti,max-rt", &val32)) ts->max_rt = val32; else ts->max_rt = MAX_12BIT; ts = kzalloc(sizeof(struct tsc2007), GFP_KERNEL); input_dev = input_allocate_device(); if (!ts || !input_dev) { err = -ENOMEM; goto err_free_mem; if (!of_property_read_u32(np, "ti,fuzzx", &val32)) ts->fuzzx = val32; if (!of_property_read_u32(np, "ti,fuzzy", &val32)) ts->fuzzy = val32; if (!of_property_read_u32(np, "ti,fuzzz", &val32)) ts->fuzzz = val32; if (!of_property_read_u64(np, "ti,poll-period", &val64)) ts->poll_period = val64; else ts->poll_period = 1; if (!of_property_read_u32(np, "ti,x-plate-ohms", &val32)) { ts->x_plate_ohms = val32; } else { dev_err(&client->dev, "missing ti,x-plate-ohms devicetree property."); return -EINVAL; } ts->client = client; ts->irq = client->irq; ts->input = input_dev; init_waitqueue_head(&ts->wait); ts->gpio = of_get_gpio(np, 0); if (gpio_is_valid(ts->gpio)) ts->get_pendown_state = tsc2007_get_pendown_state_gpio; else dev_warn(&client->dev, "GPIO not specified in DT (of_get_gpio returned %d)\n", ts->gpio); return 0; } #else static int tsc2007_probe_dt(struct i2c_client *client, struct tsc2007 *ts) { dev_err(&client->dev, "platform data is required!\n"); return -EINVAL; } #endif static int tsc2007_probe_pdev(struct i2c_client *client, struct tsc2007 *ts, const struct tsc2007_platform_data *pdata, const struct i2c_device_id *id) { ts->model = pdata->model; ts->x_plate_ohms = pdata->x_plate_ohms; ts->max_rt = pdata->max_rt ? : MAX_12BIT; Loading @@ -309,13 +355,54 @@ static int tsc2007_probe(struct i2c_client *client, ts->poll_period = pdata->poll_period ? : 1; ts->get_pendown_state = pdata->get_pendown_state; ts->clear_penirq = pdata->clear_penirq; ts->fuzzx = pdata->fuzzx; ts->fuzzy = pdata->fuzzy; ts->fuzzz = pdata->fuzzz; if (pdata->x_plate_ohms == 0) { dev_err(&client->dev, "x_plate_ohms is not set up in platform data"); err = -EINVAL; goto err_free_mem; return -EINVAL; } return 0; } static int tsc2007_probe(struct i2c_client *client, const struct i2c_device_id *id) { const struct tsc2007_platform_data *pdata = dev_get_platdata(&client->dev); struct tsc2007 *ts; struct input_dev *input_dev; int err; if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_WORD_DATA)) return -EIO; ts = devm_kzalloc(&client->dev, sizeof(struct tsc2007), GFP_KERNEL); if (!ts) return -ENOMEM; if (pdata) err = tsc2007_probe_pdev(client, ts, pdata, id); else err = tsc2007_probe_dt(client, ts); if (err) return err; input_dev = input_allocate_device(); if (!input_dev) { err = -ENOMEM; goto err_free_input; }; i2c_set_clientdata(client, ts); ts->client = client; ts->irq = client->irq; ts->input = input_dev; init_waitqueue_head(&ts->wait); snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&client->dev)); Loading @@ -331,19 +418,19 @@ static int tsc2007_probe(struct i2c_client *client, input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, pdata->fuzzx, 0); input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, pdata->fuzzy, 0); input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, ts->fuzzx, 0); input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, ts->fuzzy, 0); input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, pdata->fuzzz, 0); ts->fuzzz, 0); if (pdata->init_platform_hw) if (pdata && pdata->init_platform_hw) pdata->init_platform_hw(); err = request_threaded_irq(ts->irq, tsc2007_hard_irq, tsc2007_soft_irq, IRQF_ONESHOT, client->dev.driver->name, ts); if (err < 0) { dev_err(&client->dev, "irq %d busy?\n", ts->irq); goto err_free_mem; goto err_free_input; } tsc2007_stop(ts); Loading @@ -352,28 +439,25 @@ static int tsc2007_probe(struct i2c_client *client, if (err) goto err_free_irq; i2c_set_clientdata(client, ts); return 0; err_free_irq: free_irq(ts->irq, ts); if (pdata->exit_platform_hw) if (pdata && pdata->exit_platform_hw) pdata->exit_platform_hw(); err_free_mem: err_free_input: input_free_device(input_dev); kfree(ts); return err; } static int tsc2007_remove(struct i2c_client *client) { const struct tsc2007_platform_data *pdata = dev_get_platdata(&client->dev); struct tsc2007 *ts = i2c_get_clientdata(client); struct tsc2007_platform_data *pdata = client->dev.platform_data; free_irq(ts->irq, ts); if (pdata->exit_platform_hw) if (pdata && pdata->exit_platform_hw) pdata->exit_platform_hw(); input_unregister_device(ts->input); Loading @@ -389,10 +473,19 @@ static const struct i2c_device_id tsc2007_idtable[] = { MODULE_DEVICE_TABLE(i2c, tsc2007_idtable); #ifdef CONFIG_OF static const struct of_device_id tsc2007_of_match[] = { { .compatible = "ti,tsc2007" }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, tsc2007_of_match); #endif static struct i2c_driver tsc2007_driver = { .driver = { .owner = THIS_MODULE, .name = "tsc2007" .name = "tsc2007", .of_match_table = of_match_ptr(tsc2007_of_match), }, .id_table = tsc2007_idtable, .probe = tsc2007_probe, Loading Loading
Documentation/devicetree/bindings/input/touchscreen/tsc2007.txt 0 → 100644 +41 −0 Original line number Diff line number Diff line * Texas Instruments tsc2007 touchscreen controller Required properties: - compatible: must be "ti,tsc2007". - reg: I2C address of the chip. - ti,x-plate-ohms: X-plate resistance in ohms. Optional properties: - gpios: the interrupt gpio the chip is connected to (trough the penirq pin). The penirq pin goes to low when the panel is touched. (see GPIO binding[1] for more details). - interrupt-parent: the phandle for the gpio controller (see interrupt binding[0]). - interrupts: (gpio) interrupt to which the chip is connected (see interrupt binding[0]). - ti,max-rt: maximum pressure. - ti,fuzzx: specifies the absolute input fuzz x value. If set, it will permit noise in the data up to +- the value given to the fuzz parameter, that is used to filter noise from the event stream. - ti,fuzzy: specifies the absolute input fuzz y value. - ti,fuzzz: specifies the absolute input fuzz z value. - ti,poll-period: how much time to wait (in milliseconds) before reading again the values from the tsc2007. [0]: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt [1]: Documentation/devicetree/bindings/gpio/gpio.txt Example: &i2c1 { /* ... */ tsc2007@49 { compatible = "ti,tsc2007"; reg = <0x49>; interrupt-parent = <&gpio4>; interrupts = <0x0 0x8>; gpios = <&gpio4 0 0>; ti,x-plate-ohms = <180>; }; /* ... */ };
arch/arm/mach-imx/mach-cpuimx35.c +1 −1 Original line number Diff line number Diff line Loading @@ -53,7 +53,7 @@ static const struct imxi2c_platform_data }; #define TSC2007_IRQGPIO IMX_GPIO_NR(3, 2) static int tsc2007_get_pendown_state(void) static int tsc2007_get_pendown_state(struct device *dev) { return !gpio_get_value(TSC2007_IRQGPIO); } Loading
arch/arm/mach-imx/mach-cpuimx51sd.c +1 −1 Original line number Diff line number Diff line Loading @@ -121,7 +121,7 @@ static const struct imxuart_platform_data uart_pdata __initconst = { .flags = IMXUART_HAVE_RTSCTS, }; static int tsc2007_get_pendown_state(void) static int tsc2007_get_pendown_state(struct device *dev) { if (mx51_revision() < IMX_CHIP_REVISION_3_0) return !gpio_get_value(TSC2007_IRQGPIO_REV2); Loading
arch/sh/boards/mach-ecovec24/setup.c +1 −1 Original line number Diff line number Diff line Loading @@ -501,7 +501,7 @@ static struct platform_device keysc_device = { /* TouchScreen */ #define IRQ0 evt2irq(0x600) static int ts_get_pendown_state(void) static int ts_get_pendown_state(struct device *dev) { int val = 0; gpio_free(GPIO_FN_INTC_IRQ0); Loading
drivers/input/touchscreen/tsc2007.c +133 −40 Original line number Diff line number Diff line Loading @@ -26,6 +26,9 @@ #include <linux/interrupt.h> #include <linux/i2c.h> #include <linux/i2c/tsc2007.h> #include <linux/of_device.h> #include <linux/of.h> #include <linux/of_gpio.h> #define TSC2007_MEASURE_TEMP0 (0x0 << 4) #define TSC2007_MEASURE_AUX (0x2 << 4) Loading Loading @@ -74,13 +77,17 @@ struct tsc2007 { u16 max_rt; unsigned long poll_delay; unsigned long poll_period; int fuzzx; int fuzzy; int fuzzz; unsigned gpio; int irq; wait_queue_head_t wait; bool stopped; int (*get_pendown_state)(void); int (*get_pendown_state)(struct device *); void (*clear_penirq)(void); }; Loading Loading @@ -161,7 +168,7 @@ static bool tsc2007_is_pen_down(struct tsc2007 *ts) if (!ts->get_pendown_state) return true; return ts->get_pendown_state(); return ts->get_pendown_state(&ts->client->dev); } static irqreturn_t tsc2007_soft_irq(int irq, void *handle) Loading @@ -178,7 +185,7 @@ static irqreturn_t tsc2007_soft_irq(int irq, void *handle) rt = tsc2007_calculate_pressure(ts, &tc); if (rt == 0 && !ts->get_pendown_state) { if (!rt && !ts->get_pendown_state) { /* * If pressure reported is 0 and we don't have * callback to check pendown state, we have to Loading Loading @@ -228,7 +235,7 @@ static irqreturn_t tsc2007_hard_irq(int irq, void *handle) { struct tsc2007 *ts = handle; if (!ts->get_pendown_state || likely(ts->get_pendown_state())) if (tsc2007_is_pen_down(ts)) return IRQ_WAKE_THREAD; if (ts->clear_penirq) Loading Loading @@ -273,35 +280,74 @@ static void tsc2007_close(struct input_dev *input_dev) tsc2007_stop(ts); } static int tsc2007_probe(struct i2c_client *client, const struct i2c_device_id *id) #ifdef CONFIG_OF static int tsc2007_get_pendown_state_gpio(struct device *dev) { struct tsc2007 *ts; struct tsc2007_platform_data *pdata = client->dev.platform_data; struct input_dev *input_dev; int err; struct i2c_client *client = to_i2c_client(dev); struct tsc2007 *ts = i2c_get_clientdata(client); if (!pdata) { dev_err(&client->dev, "platform data is required!\n"); return !gpio_get_value(ts->gpio); } static int tsc2007_probe_dt(struct i2c_client *client, struct tsc2007 *ts) { struct device_node *np = client->dev.of_node; u32 val32; u64 val64; if (!np) { dev_err(&client->dev, "missing device tree data\n"); return -EINVAL; } if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_WORD_DATA)) return -EIO; if (!of_property_read_u32(np, "ti,max-rt", &val32)) ts->max_rt = val32; else ts->max_rt = MAX_12BIT; ts = kzalloc(sizeof(struct tsc2007), GFP_KERNEL); input_dev = input_allocate_device(); if (!ts || !input_dev) { err = -ENOMEM; goto err_free_mem; if (!of_property_read_u32(np, "ti,fuzzx", &val32)) ts->fuzzx = val32; if (!of_property_read_u32(np, "ti,fuzzy", &val32)) ts->fuzzy = val32; if (!of_property_read_u32(np, "ti,fuzzz", &val32)) ts->fuzzz = val32; if (!of_property_read_u64(np, "ti,poll-period", &val64)) ts->poll_period = val64; else ts->poll_period = 1; if (!of_property_read_u32(np, "ti,x-plate-ohms", &val32)) { ts->x_plate_ohms = val32; } else { dev_err(&client->dev, "missing ti,x-plate-ohms devicetree property."); return -EINVAL; } ts->client = client; ts->irq = client->irq; ts->input = input_dev; init_waitqueue_head(&ts->wait); ts->gpio = of_get_gpio(np, 0); if (gpio_is_valid(ts->gpio)) ts->get_pendown_state = tsc2007_get_pendown_state_gpio; else dev_warn(&client->dev, "GPIO not specified in DT (of_get_gpio returned %d)\n", ts->gpio); return 0; } #else static int tsc2007_probe_dt(struct i2c_client *client, struct tsc2007 *ts) { dev_err(&client->dev, "platform data is required!\n"); return -EINVAL; } #endif static int tsc2007_probe_pdev(struct i2c_client *client, struct tsc2007 *ts, const struct tsc2007_platform_data *pdata, const struct i2c_device_id *id) { ts->model = pdata->model; ts->x_plate_ohms = pdata->x_plate_ohms; ts->max_rt = pdata->max_rt ? : MAX_12BIT; Loading @@ -309,13 +355,54 @@ static int tsc2007_probe(struct i2c_client *client, ts->poll_period = pdata->poll_period ? : 1; ts->get_pendown_state = pdata->get_pendown_state; ts->clear_penirq = pdata->clear_penirq; ts->fuzzx = pdata->fuzzx; ts->fuzzy = pdata->fuzzy; ts->fuzzz = pdata->fuzzz; if (pdata->x_plate_ohms == 0) { dev_err(&client->dev, "x_plate_ohms is not set up in platform data"); err = -EINVAL; goto err_free_mem; return -EINVAL; } return 0; } static int tsc2007_probe(struct i2c_client *client, const struct i2c_device_id *id) { const struct tsc2007_platform_data *pdata = dev_get_platdata(&client->dev); struct tsc2007 *ts; struct input_dev *input_dev; int err; if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_WORD_DATA)) return -EIO; ts = devm_kzalloc(&client->dev, sizeof(struct tsc2007), GFP_KERNEL); if (!ts) return -ENOMEM; if (pdata) err = tsc2007_probe_pdev(client, ts, pdata, id); else err = tsc2007_probe_dt(client, ts); if (err) return err; input_dev = input_allocate_device(); if (!input_dev) { err = -ENOMEM; goto err_free_input; }; i2c_set_clientdata(client, ts); ts->client = client; ts->irq = client->irq; ts->input = input_dev; init_waitqueue_head(&ts->wait); snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&client->dev)); Loading @@ -331,19 +418,19 @@ static int tsc2007_probe(struct i2c_client *client, input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, pdata->fuzzx, 0); input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, pdata->fuzzy, 0); input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, ts->fuzzx, 0); input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, ts->fuzzy, 0); input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, pdata->fuzzz, 0); ts->fuzzz, 0); if (pdata->init_platform_hw) if (pdata && pdata->init_platform_hw) pdata->init_platform_hw(); err = request_threaded_irq(ts->irq, tsc2007_hard_irq, tsc2007_soft_irq, IRQF_ONESHOT, client->dev.driver->name, ts); if (err < 0) { dev_err(&client->dev, "irq %d busy?\n", ts->irq); goto err_free_mem; goto err_free_input; } tsc2007_stop(ts); Loading @@ -352,28 +439,25 @@ static int tsc2007_probe(struct i2c_client *client, if (err) goto err_free_irq; i2c_set_clientdata(client, ts); return 0; err_free_irq: free_irq(ts->irq, ts); if (pdata->exit_platform_hw) if (pdata && pdata->exit_platform_hw) pdata->exit_platform_hw(); err_free_mem: err_free_input: input_free_device(input_dev); kfree(ts); return err; } static int tsc2007_remove(struct i2c_client *client) { const struct tsc2007_platform_data *pdata = dev_get_platdata(&client->dev); struct tsc2007 *ts = i2c_get_clientdata(client); struct tsc2007_platform_data *pdata = client->dev.platform_data; free_irq(ts->irq, ts); if (pdata->exit_platform_hw) if (pdata && pdata->exit_platform_hw) pdata->exit_platform_hw(); input_unregister_device(ts->input); Loading @@ -389,10 +473,19 @@ static const struct i2c_device_id tsc2007_idtable[] = { MODULE_DEVICE_TABLE(i2c, tsc2007_idtable); #ifdef CONFIG_OF static const struct of_device_id tsc2007_of_match[] = { { .compatible = "ti,tsc2007" }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, tsc2007_of_match); #endif static struct i2c_driver tsc2007_driver = { .driver = { .owner = THIS_MODULE, .name = "tsc2007" .name = "tsc2007", .of_match_table = of_match_ptr(tsc2007_of_match), }, .id_table = tsc2007_idtable, .probe = tsc2007_probe, Loading