linux/drivers/input/touchscreen/ads7846.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * ADS7846 based touchscreen and sensor driver
 *
 * Copyright (c) 2005 David Brownell
 * Copyright (c) 2006 Nokia Corporation
 * Various changes: Imre Deak <[email protected]>
 *
 * Using code from:
 *  - corgi_ts.c
 *	Copyright (C) 2004-2005 Richard Purdie
 *  - omap_ts.[hc], ads7846.h, ts_osk.c
 *	Copyright (C) 2002 MontaVista Software
 *	Copyright (C) 2004 Texas Instruments
 *	Copyright (C) 2005 Dirk Behme
 */
#include <linux/types.h>
#include <linux/hwmon.h>
#include <linux/err.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/input.h>
#include <linux/input/touchscreen.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/pm.h>
#include <linux/property.h>
#include <linux/gpio/consumer.h>
#include <linux/spi/spi.h>
#include <linux/spi/ads7846.h>
#include <linux/regulator/consumer.h>
#include <linux/module.h>
#include <linux/unaligned.h>

/*
 * This code has been heavily tested on a Nokia 770, and lightly
 * tested on other ads7846 devices (OSK/Mistral, Lubbock, Spitz).
 * TSC2046 is just newer ads7846 silicon.
 * Support for ads7843 tested on Atmel at91sam926x-EK.
 * Support for ads7845 has only been stubbed in.
 * Support for Analog Devices AD7873 and AD7843 tested.
 *
 * IRQ handling needs a workaround because of a shortcoming in handling
 * edge triggered IRQs on some platforms like the OMAP1/2. These
 * platforms don't handle the ARM lazy IRQ disabling properly, thus we
 * have to maintain our own SW IRQ disabled status. This should be
 * removed as soon as the affected platform's IRQ handling is fixed.
 *
 * App note sbaa036 talks in more detail about accurate sampling...
 * that ought to help in situations like LCDs inducing noise (which
 * can also be helped by using synch signals) and more generally.
 * This driver tries to utilize the measures described in the app
 * note. The strength of filtering can be set in the board-* specific
 * files.
 */

#define TS_POLL_DELAY
#define TS_POLL_PERIOD

/* this driver doesn't aim at the peak continuous sample rate */
#define SAMPLE_BITS

struct ads7846_buf {} __packed;

struct ads7846_buf_layout {};

/*
 * We allocate this separately to avoid cache line sharing issues when
 * driver is used with DMA-based SPI controllers (like atmel_spi) on
 * systems where main memory is not DMA-coherent (most non-x86 boards).
 */
struct ads7846_packet {};

struct ads7846 {};

enum ads7846_filter {};

/* leave chip selected when we're done, for quicker re-select? */
#if	0
#define CS_CHANGE
#else
#define CS_CHANGE(xfer)
#endif

/*--------------------------------------------------------------------------*/

/* The ADS7846 has touchscreen and other sensors.
 * Earlier ads784x chips are somewhat compatible.
 */
#define ADS_START
#define ADS_A2A1A0_d_y
#define ADS_A2A1A0_d_z1
#define ADS_A2A1A0_d_z2
#define ADS_A2A1A0_d_x
#define ADS_A2A1A0_temp0
#define ADS_A2A1A0_vbatt
#define ADS_A2A1A0_vaux
#define ADS_A2A1A0_temp1
#define ADS_8_BIT
#define ADS_12_BIT
#define ADS_SER
#define ADS_DFR
#define ADS_PD10_PDOWN
#define ADS_PD10_ADC_ON
#define ADS_PD10_REF_ON
#define ADS_PD10_ALL_ON

#define MAX_12BIT

/* leave ADC powered up (disables penirq) between differential samples */
#define READ_12BIT_DFR(x, adc, vref)

#define READ_Y(vref)
#define READ_Z1(vref)
#define READ_Z2(vref)
#define READ_X(vref)
#define PWRDOWN

/* single-ended samples need to first power up reference voltage;
 * we leave both ADC and VREF powered
 */
#define READ_12BIT_SER(x)

#define REF_ON
#define REF_OFF

/* Order commands in the most optimal way to reduce Vref switching and
 * settling time:
 * Measure:  X; Vref: X+, X-; IN: Y+
 * Measure:  Y; Vref: Y+, Y-; IN: X+
 * Measure: Z1; Vref: Y+, X-; IN: X+
 * Measure: Z2; Vref: Y+, X-; IN: Y-
 */
enum ads7846_cmds {};

static int get_pendown_state(struct ads7846 *ts)
{}

static void ads7846_report_pen_up(struct ads7846 *ts)
{}

/* Must be called with ts->lock held */
static void ads7846_stop(struct ads7846 *ts)
{}

/* Must be called with ts->lock held */
static void ads7846_restart(struct ads7846 *ts)
{}

/* Must be called with ts->lock held */
static void __ads7846_disable(struct ads7846 *ts)
{}

/* Must be called with ts->lock held */
static void __ads7846_enable(struct ads7846 *ts)
{}

static void ads7846_disable(struct ads7846 *ts)
{}

static void ads7846_enable(struct ads7846 *ts)
{}

/*--------------------------------------------------------------------------*/

/*
 * Non-touchscreen sensors only use single-ended conversions.
 * The range is GND..vREF. The ads7843 and ads7835 must use external vREF;
 * ads7846 lets that pin be unconnected, to use internal vREF.
 */

struct ser_req {};

struct ads7845_ser_req {};

static int ads7846_read12_ser(struct device *dev, unsigned command)
{}

static int ads7845_read12_ser(struct device *dev, unsigned command)
{}

#if IS_ENABLED(CONFIG_HWMON)

#define SHOW(name, var, adjust)


/* Sysfs conventions report temperatures in millidegrees Celsius.
 * ADS7846 could use the low-accuracy two-sample scheme, but can't do the high
 * accuracy scheme without calibration data.  For now we won't try either;
 * userspace sees raw sensor values, and must scale/calibrate appropriately.
 */
static inline unsigned null_adjust(struct ads7846 *ts, ssize_t v)
{}

SHOW()		/* temp1_input */
SHOW()		/* temp2_input */


/* sysfs conventions report voltages in millivolts.  We can convert voltages
 * if we know vREF.  userspace may need to scale vAUX to match the board's
 * external resistors; we assume that vBATT only uses the internal ones.
 */
static inline unsigned vaux_adjust(struct ads7846 *ts, ssize_t v)
{}

static inline unsigned vbatt_adjust(struct ads7846 *ts, ssize_t v)
{}

SHOW()
SHOW()

static umode_t ads7846_is_visible(struct kobject *kobj, struct attribute *attr,
				  int index)
{}

static struct attribute *ads7846_attributes[] =;

static const struct attribute_group ads7846_attr_group =;
__ATTRIBUTE_GROUPS();

static int ads784x_hwmon_register(struct spi_device *spi, struct ads7846 *ts)
{}

#else
static inline int ads784x_hwmon_register(struct spi_device *spi,
					 struct ads7846 *ts)
{
	return 0;
}
#endif

static ssize_t ads7846_pen_down_show(struct device *dev,
				     struct device_attribute *attr, char *buf)
{}

static DEVICE_ATTR(pen_down, S_IRUGO, ads7846_pen_down_show, NULL);

static ssize_t ads7846_disable_show(struct device *dev,
				     struct device_attribute *attr, char *buf)
{}

static ssize_t ads7846_disable_store(struct device *dev,
				     struct device_attribute *attr,
				     const char *buf, size_t count)
{}

static DEVICE_ATTR(disable, 0664, ads7846_disable_show, ads7846_disable_store);

static struct attribute *ads784x_attrs[] =;
ATTRIBUTE_GROUPS();

/*--------------------------------------------------------------------------*/

static int ads7846_debounce_filter(void *ads, int data_idx, int *val)
{}

static int ads7846_no_filter(void *ads, int data_idx, int *val)
{}

static int ads7846_get_value(struct ads7846_buf *buf)
{}

static void ads7846_set_cmd_val(struct ads7846 *ts, enum ads7846_cmds cmd_idx,
				u16 val)
{}

static u8 ads7846_get_cmd(enum ads7846_cmds cmd_idx, int vref)
{}

static bool ads7846_cmd_need_settle(enum ads7846_cmds cmd_idx)
{}

static int ads7846_filter(struct ads7846 *ts)
{}

static void ads7846_wait_for_hsync(struct ads7846 *ts)
{}

static void ads7846_read_state(struct ads7846 *ts)
{}

static void ads7846_report_state(struct ads7846 *ts)
{}

static irqreturn_t ads7846_hard_irq(int irq, void *handle)
{}


static irqreturn_t ads7846_irq(int irq, void *handle)
{}

static int ads7846_suspend(struct device *dev)
{}

static int ads7846_resume(struct device *dev)
{}

static DEFINE_SIMPLE_DEV_PM_OPS(ads7846_pm, ads7846_suspend, ads7846_resume);

static int ads7846_setup_pendown(struct spi_device *spi,
				 struct ads7846 *ts,
				 const struct ads7846_platform_data *pdata)
{}

/*
 * Set up the transfers to read touchscreen state; this assumes we
 * use formula #2 for pressure, not #3.
 */
static int ads7846_setup_spi_msg(struct ads7846 *ts,
				  const struct ads7846_platform_data *pdata)
{}

static const struct of_device_id ads7846_dt_ids[] =;
MODULE_DEVICE_TABLE(of, ads7846_dt_ids);

static const struct spi_device_id ads7846_spi_ids[] =;
MODULE_DEVICE_TABLE(spi, ads7846_spi_ids);

static const struct ads7846_platform_data *ads7846_get_props(struct device *dev)
{}

static void ads7846_regulator_disable(void *regulator)
{}

static int ads7846_probe(struct spi_device *spi)
{}

static void ads7846_remove(struct spi_device *spi)
{}

static struct spi_driver ads7846_driver =;

module_spi_driver();

MODULE_DESCRIPTION();
MODULE_LICENSE();