// SPDX-License-Identifier: GPL-2.0 /* * Rohm BU21029 touchscreen controller driver * * Copyright (C) 2015-2018 Bosch Sicherheitssysteme GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #include <linux/delay.h> #include <linux/gpio/consumer.h> #include <linux/i2c.h> #include <linux/input.h> #include <linux/input/touchscreen.h> #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/module.h> #include <linux/regulator/consumer.h> #include <linux/timer.h> /* * HW_ID1 Register (PAGE=0, ADDR=0x0E, Reset value=0x02, Read only) * +--------+--------+--------+--------+--------+--------+--------+--------+ * | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | * +--------+--------+--------+--------+--------+--------+--------+--------+ * | HW_IDH | * +--------+--------+--------+--------+--------+--------+--------+--------+ * HW_ID2 Register (PAGE=0, ADDR=0x0F, Reset value=0x29, Read only) * +--------+--------+--------+--------+--------+--------+--------+--------+ * | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | * +--------+--------+--------+--------+--------+--------+--------+--------+ * | HW_IDL | * +--------+--------+--------+--------+--------+--------+--------+--------+ * HW_IDH: high 8bits of IC's ID * HW_IDL: low 8bits of IC's ID */ #define BU21029_HWID_REG … #define SUPPORTED_HWID … /* * CFR0 Register (PAGE=0, ADDR=0x00, Reset value=0x20) * +--------+--------+--------+--------+--------+--------+--------+--------+ * | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | * +--------+--------+--------+--------+--------+--------+--------+--------+ * | 0 | 0 | CALIB | INTRM | 0 | 0 | 0 | 0 | * +--------+--------+--------+--------+--------+--------+--------+--------+ * CALIB: 0 = not to use calibration result (*) * 1 = use calibration result * INTRM: 0 = INT output depend on "pen down" (*) * 1 = INT output always "0" */ #define BU21029_CFR0_REG … #define CFR0_VALUE … /* * CFR1 Register (PAGE=0, ADDR=0x01, Reset value=0xA6) * +--------+--------+--------+--------+--------+--------+--------+--------+ * | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | * +--------+--------+--------+--------+--------+--------+--------+--------+ * | MAV | AVE[2:0] | 0 | SMPL[2:0] | * +--------+--------+--------+--------+--------+--------+--------+--------+ * MAV: 0 = median average filter off * 1 = median average filter on (*) * AVE: AVE+1 = number of average samples for MAV, * if AVE>SMPL, then AVE=SMPL (=3) * SMPL: SMPL+1 = number of conversion samples for MAV (=7) */ #define BU21029_CFR1_REG … #define CFR1_VALUE … /* * CFR2 Register (PAGE=0, ADDR=0x02, Reset value=0x04) * +--------+--------+--------+--------+--------+--------+--------+--------+ * | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | * +--------+--------+--------+--------+--------+--------+--------+--------+ * | INTVL_TIME[3:0] | TIME_ST_ADC[3:0] | * +--------+--------+--------+--------+--------+--------+--------+--------+ * INTVL_TIME: waiting time between completion of conversion * and start of next conversion, only usable in * autoscan mode (=20.480ms) * TIME_ST_ADC: waiting time between application of voltage * to panel and start of A/D conversion (=100us) */ #define BU21029_CFR2_REG … #define CFR2_VALUE … /* * CFR3 Register (PAGE=0, ADDR=0x0B, Reset value=0x72) * +--------+--------+--------+--------+--------+--------+--------+--------+ * | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | * +--------+--------+--------+--------+--------+--------+--------+--------+ * | RM8 | STRETCH| PU90K | DUAL | PIDAC_OFS[3:0] | * +--------+--------+--------+--------+--------+--------+--------+--------+ * RM8: 0 = coordinate resolution is 12bit (*) * 1 = coordinate resolution is 8bit * STRETCH: 0 = SCL_STRETCH function off * 1 = SCL_STRETCH function on (*) * PU90K: 0 = internal pull-up resistance for touch detection is ~50kohms (*) * 1 = internal pull-up resistance for touch detection is ~90kohms * DUAL: 0 = dual touch detection off (*) * 1 = dual touch detection on * PIDAC_OFS: dual touch detection circuit adjustment, it is not necessary * to change this from initial value */ #define BU21029_CFR3_REG … #define CFR3_VALUE … /* * LDO Register (PAGE=0, ADDR=0x0C, Reset value=0x00) * +--------+--------+--------+--------+--------+--------+--------+--------+ * | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | * +--------+--------+--------+--------+--------+--------+--------+--------+ * | 0 | PVDD[2:0] | 0 | AVDD[2:0] | * +--------+--------+--------+--------+--------+--------+--------+--------+ * PVDD: output voltage of panel output regulator (=2.000V) * AVDD: output voltage of analog circuit regulator (=2.000V) */ #define BU21029_LDO_REG … #define LDO_VALUE … /* * Serial Interface Command Byte 1 (CID=1) * +--------+--------+--------+--------+--------+--------+--------+--------+ * | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | * +--------+--------+--------+--------+--------+--------+--------+--------+ * | 1 | CF | CMSK | PDM | STP | * +--------+--------+--------+--------+--------+--------+--------+--------+ * CF: conversion function, see table 3 in datasheet p6 (=0000, automatic scan) * CMSK: 0 = executes convert function (*) * 1 = reads the convert result * PDM: 0 = power down after convert function stops (*) * 1 = keep power on after convert function stops * STP: 1 = abort current conversion and power down, set to "0" automatically */ #define BU21029_AUTOSCAN … /* * The timeout value needs to be larger than INTVL_TIME + tConv4 (sample and * conversion time), where tConv4 is calculated by formula: * tPON + tDLY1 + (tTIME_ST_ADC + (tADC * tSMPL) * 2 + tDLY2) * 3 * see figure 8 in datasheet p15 for details of each field. */ #define PEN_UP_TIMEOUT_MS … #define STOP_DELAY_MIN_US … #define STOP_DELAY_MAX_US … #define START_DELAY_MS … #define BUF_LEN … #define SCALE_12BIT … #define MAX_12BIT … #define DRIVER_NAME … struct bu21029_ts_data { … }; static void bu21029_touch_report(struct bu21029_ts_data *bu21029, const u8 *buf) { … } static void bu21029_touch_release(struct timer_list *t) { … } static irqreturn_t bu21029_touch_soft_irq(int irq, void *data) { … } static void bu21029_put_chip_in_reset(struct bu21029_ts_data *bu21029) { … } static int bu21029_start_chip(struct input_dev *dev) { … } static void bu21029_stop_chip(struct input_dev *dev) { … } static int bu21029_probe(struct i2c_client *client) { … } static int bu21029_suspend(struct device *dev) { … } static int bu21029_resume(struct device *dev) { … } static DEFINE_SIMPLE_DEV_PM_OPS(bu21029_pm_ops, bu21029_suspend, bu21029_resume); static const struct i2c_device_id bu21029_ids[] = …; MODULE_DEVICE_TABLE(i2c, bu21029_ids); #ifdef CONFIG_OF static const struct of_device_id bu21029_of_ids[] = …; MODULE_DEVICE_TABLE(of, bu21029_of_ids); #endif static struct i2c_driver bu21029_driver = …; module_i2c_driver(…) …; MODULE_AUTHOR(…) …; MODULE_DESCRIPTION(…) …; MODULE_LICENSE(…) …;