cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

jornada720_ts.c (4242B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * drivers/input/touchscreen/jornada720_ts.c
      4 *
      5 * Copyright (C) 2007 Kristoffer Ericson <Kristoffer.Ericson@gmail.com>
      6 *
      7 *  Copyright (C) 2006 Filip Zyzniewski <filip.zyzniewski@tefnet.pl>
      8 *  based on HP Jornada 56x touchscreen driver by Alex Lange <chicken@handhelds.org>
      9 *
     10 * HP Jornada 710/720/729 Touchscreen Driver
     11 */
     12
     13#include <linux/gpio/consumer.h>
     14#include <linux/platform_device.h>
     15#include <linux/input.h>
     16#include <linux/interrupt.h>
     17#include <linux/module.h>
     18#include <linux/slab.h>
     19#include <linux/io.h>
     20
     21#include <mach/jornada720.h>
     22
     23MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>");
     24MODULE_DESCRIPTION("HP Jornada 710/720/728 touchscreen driver");
     25MODULE_LICENSE("GPL v2");
     26
     27struct jornada_ts {
     28	struct input_dev *dev;
     29	struct gpio_desc *gpio;
     30	int x_data[4];		/* X sample values */
     31	int y_data[4];		/* Y sample values */
     32};
     33
     34static void jornada720_ts_collect_data(struct jornada_ts *jornada_ts)
     35{
     36	/* 3 low word X samples */
     37	jornada_ts->x_data[0] = jornada_ssp_byte(TXDUMMY);
     38	jornada_ts->x_data[1] = jornada_ssp_byte(TXDUMMY);
     39	jornada_ts->x_data[2] = jornada_ssp_byte(TXDUMMY);
     40
     41	/* 3 low word Y samples */
     42	jornada_ts->y_data[0] = jornada_ssp_byte(TXDUMMY);
     43	jornada_ts->y_data[1] = jornada_ssp_byte(TXDUMMY);
     44	jornada_ts->y_data[2] = jornada_ssp_byte(TXDUMMY);
     45
     46	/* combined x samples bits */
     47	jornada_ts->x_data[3] = jornada_ssp_byte(TXDUMMY);
     48
     49	/* combined y samples bits */
     50	jornada_ts->y_data[3] = jornada_ssp_byte(TXDUMMY);
     51}
     52
     53static int jornada720_ts_average(int coords[4])
     54{
     55	int coord, high_bits = coords[3];
     56
     57	coord  = coords[0] | ((high_bits & 0x03) << 8);
     58	coord += coords[1] | ((high_bits & 0x0c) << 6);
     59	coord += coords[2] | ((high_bits & 0x30) << 4);
     60
     61	return coord / 3;
     62}
     63
     64static irqreturn_t jornada720_ts_interrupt(int irq, void *dev_id)
     65{
     66	struct platform_device *pdev = dev_id;
     67	struct jornada_ts *jornada_ts = platform_get_drvdata(pdev);
     68	struct input_dev *input = jornada_ts->dev;
     69	int x, y;
     70
     71	/* If gpio is high then report pen up */
     72	if (gpiod_get_value(jornada_ts->gpio)) {
     73		input_report_key(input, BTN_TOUCH, 0);
     74		input_sync(input);
     75	} else {
     76		jornada_ssp_start();
     77
     78		/* proper reply to request is always TXDUMMY */
     79		if (jornada_ssp_inout(GETTOUCHSAMPLES) == TXDUMMY) {
     80			jornada720_ts_collect_data(jornada_ts);
     81
     82			x = jornada720_ts_average(jornada_ts->x_data);
     83			y = jornada720_ts_average(jornada_ts->y_data);
     84
     85			input_report_key(input, BTN_TOUCH, 1);
     86			input_report_abs(input, ABS_X, x);
     87			input_report_abs(input, ABS_Y, y);
     88			input_sync(input);
     89		}
     90
     91		jornada_ssp_end();
     92	}
     93
     94	return IRQ_HANDLED;
     95}
     96
     97static int jornada720_ts_probe(struct platform_device *pdev)
     98{
     99	struct jornada_ts *jornada_ts;
    100	struct input_dev *input_dev;
    101	int error, irq;
    102
    103	jornada_ts = devm_kzalloc(&pdev->dev, sizeof(*jornada_ts), GFP_KERNEL);
    104	if (!jornada_ts)
    105		return -ENOMEM;
    106
    107	input_dev = devm_input_allocate_device(&pdev->dev);
    108	if (!input_dev)
    109		return -ENOMEM;
    110
    111	platform_set_drvdata(pdev, jornada_ts);
    112
    113	jornada_ts->gpio = devm_gpiod_get(&pdev->dev, "penup", GPIOD_IN);
    114	if (IS_ERR(jornada_ts->gpio))
    115		return PTR_ERR(jornada_ts->gpio);
    116
    117	irq = gpiod_to_irq(jornada_ts->gpio);
    118	if (irq <= 0)
    119		return irq < 0 ? irq : -EINVAL;
    120
    121	jornada_ts->dev = input_dev;
    122
    123	input_dev->name = "HP Jornada 7xx Touchscreen";
    124	input_dev->phys = "jornadats/input0";
    125	input_dev->id.bustype = BUS_HOST;
    126	input_dev->dev.parent = &pdev->dev;
    127
    128	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
    129	input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
    130	input_set_abs_params(input_dev, ABS_X, 270, 3900, 0, 0);
    131	input_set_abs_params(input_dev, ABS_Y, 180, 3700, 0, 0);
    132
    133	error = devm_request_irq(&pdev->dev, irq, jornada720_ts_interrupt,
    134				 IRQF_TRIGGER_RISING,
    135				 "HP7XX Touchscreen driver", pdev);
    136	if (error) {
    137		dev_err(&pdev->dev, "HP7XX TS : Unable to acquire irq!\n");
    138		return error;
    139	}
    140
    141	error = input_register_device(jornada_ts->dev);
    142	if (error)
    143		return error;
    144
    145	return 0;
    146}
    147
    148/* work with hotplug and coldplug */
    149MODULE_ALIAS("platform:jornada_ts");
    150
    151static struct platform_driver jornada720_ts_driver = {
    152	.probe		= jornada720_ts_probe,
    153	.driver		= {
    154		.name	= "jornada_ts",
    155	},
    156};
    157module_platform_driver(jornada720_ts_driver);