diff options
Diffstat (limited to 'drivers/input')
38 files changed, 616 insertions, 78 deletions
diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c index e9120ba6bae0..009822fa61b8 100644 --- a/drivers/input/ff-memless.c +++ b/drivers/input/ff-memless.c @@ -136,7 +136,7 @@ static void ml_schedule_timer(struct ml_device *ml) if (!events) { pr_debug("no actions\n"); - del_timer(&ml->timer); + timer_delete(&ml->timer); } else { pr_debug("timer set\n"); mod_timer(&ml->timer, earliest); @@ -489,7 +489,7 @@ static void ml_ff_destroy(struct ff_device *ff) * do not actually stop the timer, and therefore we should * do it here. */ - del_timer_sync(&ml->timer); + timer_delete_sync(&ml->timer); kfree(ml->private); } diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index 10cc95867415..ae51f108bfae 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c @@ -191,7 +191,7 @@ void gameport_stop_polling(struct gameport *gameport) spin_lock(&gameport->timer_lock); if (!--gameport->poll_cnt) - del_timer(&gameport->poll_timer); + timer_delete(&gameport->poll_timer); spin_unlock(&gameport->timer_lock); } @@ -847,7 +847,7 @@ EXPORT_SYMBOL(gameport_open); void gameport_close(struct gameport *gameport) { - del_timer_sync(&gameport->poll_timer); + timer_delete_sync(&gameport->poll_timer); gameport->poll_handler = NULL; gameport->poll_interval = 0; gameport_set_drv(gameport, NULL); diff --git a/drivers/input/input.c b/drivers/input/input.c index c9e3ac64bcd0..ec4346f20efd 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -96,7 +96,7 @@ static void input_start_autorepeat(struct input_dev *dev, int code) static void input_stop_autorepeat(struct input_dev *dev) { - del_timer(&dev->timer); + timer_delete(&dev->timer); } /* @@ -2223,7 +2223,7 @@ static void __input_unregister_device(struct input_dev *dev) handle->handler->disconnect(handle); WARN_ON(!list_empty(&dev->h_list)); - del_timer_sync(&dev->timer); + timer_delete_sync(&dev->timer); list_del_init(&dev->node); input_wakeup_procfs_readers(); diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c index a9f1946cf0d6..d7a253835889 100644 --- a/drivers/input/joystick/db9.c +++ b/drivers/input/joystick/db9.c @@ -531,7 +531,7 @@ static void db9_close(struct input_dev *dev) guard(mutex)(&db9->mutex); if (!--db9->used) { - del_timer_sync(&db9->timer); + timer_delete_sync(&db9->timer); parport_write_control(port, 0x00); parport_data_forward(port); parport_release(db9->pd); diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index b53cafd7a5ee..9fc629ad58b8 100644 --- a/drivers/input/joystick/gamecon.c +++ b/drivers/input/joystick/gamecon.c @@ -786,7 +786,7 @@ static void gc_close(struct input_dev *dev) guard(mutex)(&gc->mutex); if (!--gc->used) { - del_timer_sync(&gc->timer); + timer_delete_sync(&gc->timer); parport_write_control(gc->pd->port, 0x00); parport_release(gc->pd); } diff --git a/drivers/input/joystick/n64joy.c b/drivers/input/joystick/n64joy.c index c344dbc0c493..94d2f4e96fe6 100644 --- a/drivers/input/joystick/n64joy.c +++ b/drivers/input/joystick/n64joy.c @@ -216,7 +216,7 @@ static void n64joy_close(struct input_dev *dev) guard(mutex)(&priv->n64joy_mutex); if (!--priv->n64joy_opened) - del_timer_sync(&priv->timer); + timer_delete_sync(&priv->timer); } static const u64 __initconst scandata[] ____cacheline_aligned = { diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c index db696ba61a3b..aa3e7d471b96 100644 --- a/drivers/input/joystick/turbografx.c +++ b/drivers/input/joystick/turbografx.c @@ -124,7 +124,7 @@ static void tgfx_close(struct input_dev *dev) guard(mutex)(&tgfx->sem); if (!--tgfx->used) { - del_timer_sync(&tgfx->timer); + timer_delete_sync(&tgfx->timer); parport_write_control(tgfx->pd->port, 0x00); parport_release(tgfx->pd); } diff --git a/drivers/input/joystick/walkera0701.c b/drivers/input/joystick/walkera0701.c index 59eea813f258..15370fb82317 100644 --- a/drivers/input/joystick/walkera0701.c +++ b/drivers/input/joystick/walkera0701.c @@ -232,8 +232,7 @@ static void walkera0701_attach(struct parport *pp) goto err_unregister_device; } - hrtimer_init(&w->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - w->timer.function = timer_handler; + hrtimer_setup(&w->timer, timer_handler, CLOCK_MONOTONIC, HRTIMER_MODE_REL); w->input_dev = input_allocate_device(); if (!w->input_dev) { diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 5eef66516e37..5c39a217b94c 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -590,9 +590,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev, INIT_DELAYED_WORK(&bdata->work, gpio_keys_gpio_work_func); - hrtimer_init(&bdata->debounce_timer, - CLOCK_REALTIME, HRTIMER_MODE_REL); - bdata->debounce_timer.function = gpio_keys_debounce_timer; + hrtimer_setup(&bdata->debounce_timer, gpio_keys_debounce_timer, + CLOCK_REALTIME, HRTIMER_MODE_REL); isr = gpio_keys_gpio_isr; irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; @@ -628,9 +627,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev, } bdata->release_delay = button->debounce_interval; - hrtimer_init(&bdata->release_timer, - CLOCK_REALTIME, HRTIMER_MODE_REL_HARD); - bdata->release_timer.function = gpio_keys_irq_timer; + hrtimer_setup(&bdata->release_timer, gpio_keys_irq_timer, + CLOCK_REALTIME, HRTIMER_MODE_REL_HARD); isr = gpio_keys_irq_isr; irqflags = 0; diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c index b92268ddfd84..3cd47fa44efc 100644 --- a/drivers/input/keyboard/imx_keypad.c +++ b/drivers/input/keyboard/imx_keypad.c @@ -370,7 +370,7 @@ static void imx_keypad_close(struct input_dev *dev) /* Mark keypad as being inactive */ keypad->enabled = false; synchronize_irq(keypad->irq); - del_timer_sync(&keypad->check_matrix_timer); + timer_delete_sync(&keypad->check_matrix_timer); imx_keypad_inhibit(keypad); diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index 2a3b3bfc2878..e46473cb817c 100644 --- a/drivers/input/keyboard/matrix_keypad.c +++ b/drivers/input/keyboard/matrix_keypad.c @@ -26,6 +26,7 @@ struct matrix_keypad { unsigned int row_shift; unsigned int col_scan_delay_us; + unsigned int all_cols_on_delay_us; /* key debounce interval in milli-second */ unsigned int debounce_ms; bool drive_inactive_cols; @@ -68,7 +69,7 @@ static void activate_col(struct matrix_keypad *keypad, int col, bool on) __activate_col(keypad, col, on); if (on && keypad->col_scan_delay_us) - udelay(keypad->col_scan_delay_us); + fsleep(keypad->col_scan_delay_us); } static void activate_all_cols(struct matrix_keypad *keypad, bool on) @@ -77,6 +78,9 @@ static void activate_all_cols(struct matrix_keypad *keypad, bool on) for (col = 0; col < keypad->num_col_gpios; col++) __activate_col(keypad, col, on); + + if (on && keypad->all_cols_on_delay_us) + fsleep(keypad->all_cols_on_delay_us); } static bool row_asserted(struct matrix_keypad *keypad, int row) @@ -392,6 +396,8 @@ static int matrix_keypad_probe(struct platform_device *pdev) &keypad->debounce_ms); device_property_read_u32(&pdev->dev, "col-scan-delay-us", &keypad->col_scan_delay_us); + device_property_read_u32(&pdev->dev, "all-cols-on-delay-us", + &keypad->all_cols_on_delay_us); err = matrix_keypad_init_gpio(pdev, keypad); if (err) diff --git a/drivers/input/keyboard/snvs_pwrkey.c b/drivers/input/keyboard/snvs_pwrkey.c index f7b5f1e25c80..bbf409dda89f 100644 --- a/drivers/input/keyboard/snvs_pwrkey.c +++ b/drivers/input/keyboard/snvs_pwrkey.c @@ -104,7 +104,7 @@ static void imx_snvs_pwrkey_act(void *pdata) { struct pwrkey_drv_data *pd = pdata; - del_timer_sync(&pd->check_timer); + timer_delete_sync(&pd->check_timer); } static int imx_snvs_pwrkey_probe(struct platform_device *pdev) diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index 6776dd94ce76..32a676f0de53 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c @@ -416,7 +416,7 @@ static void tegra_kbc_stop(struct tegra_kbc *kbc) } disable_irq(kbc->irq); - del_timer_sync(&kbc->timer); + timer_delete_sync(&kbc->timer); clk_disable_unprepare(kbc->clk); } @@ -703,7 +703,7 @@ static int tegra_kbc_suspend(struct device *dev) if (device_may_wakeup(&pdev->dev)) { disable_irq(kbc->irq); - del_timer_sync(&kbc->timer); + timer_delete_sync(&kbc->timer); tegra_kbc_set_fifo_interrupt(kbc, false); /* Forcefully clear the interrupt status */ diff --git a/drivers/input/misc/pm8941-pwrkey.c b/drivers/input/misc/pm8941-pwrkey.c index d0c46665e527..d952c16f2458 100644 --- a/drivers/input/misc/pm8941-pwrkey.c +++ b/drivers/input/misc/pm8941-pwrkey.c @@ -154,8 +154,8 @@ static irqreturn_t pm8941_pwrkey_irq(int irq, void *_data) if (pwrkey->sw_debounce_time_us) { if (ktime_before(ktime_get(), pwrkey->sw_debounce_end_time)) { dev_dbg(pwrkey->dev, - "ignoring key event received before debounce end %llu us\n", - pwrkey->sw_debounce_end_time); + "ignoring key event received before debounce end %lld us\n", + ktime_to_us(pwrkey->sw_debounce_end_time)); return IRQ_HANDLED; } } diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 0728b5c08f02..0bd7b09b0aa3 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -1519,7 +1519,7 @@ static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) return PSMOUSE_GOOD_DATA; } - del_timer(&priv->timer); + timer_delete(&priv->timer); if (psmouse->packet[6] & 0x80) { diff --git a/drivers/input/mouse/byd.c b/drivers/input/mouse/byd.c index 654b38d249f3..4ee084e00a7c 100644 --- a/drivers/input/mouse/byd.c +++ b/drivers/input/mouse/byd.c @@ -425,7 +425,7 @@ static void byd_disconnect(struct psmouse *psmouse) struct byd_data *priv = psmouse->private; if (priv) { - del_timer(&priv->timer); + timer_delete(&priv->timer); kfree(psmouse->private); psmouse->private = NULL; } diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index 2f2d925a55d7..00c87c0532a6 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -1080,8 +1080,8 @@ static ssize_t cyapa_update_fw_store(struct device *dev, char fw_name[NAME_MAX]; int ret, error; - if (count >= NAME_MAX) { - dev_err(dev, "File name too long\n"); + if (!count || count >= NAME_MAX) { + dev_err(dev, "Bad file name size\n"); return -EINVAL; } diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index aba57abe6978..309c360aab55 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -161,6 +161,7 @@ static const char * const topbuttonpad_pnp_ids[] = { NULL }; +#ifdef CONFIG_MOUSE_PS2_SYNAPTICS_SMBUS static const char * const smbus_pnp_ids[] = { /* all of the topbuttonpad_pnp_ids are valid, we just add some extras */ "LEN0048", /* X1 Carbon 3 */ @@ -196,6 +197,7 @@ static const char * const smbus_pnp_ids[] = { "SYN3257", /* HP Envy 13-ad105ng */ NULL }; +#endif static const char * const forcepad_pnp_ids[] = { "SYN300D", diff --git a/drivers/input/rmi4/rmi_f54.c b/drivers/input/rmi4/rmi_f54.c index 5c3da910b5b2..ac4041a69fcd 100644 --- a/drivers/input/rmi4/rmi_f54.c +++ b/drivers/input/rmi4/rmi_f54.c @@ -372,8 +372,6 @@ static const struct vb2_ops rmi_f54_queue_ops = { .queue_setup = rmi_f54_queue_setup, .buf_queue = rmi_f54_buffer_queue, .stop_streaming = rmi_f54_stop_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, }; static const struct vb2_queue rmi_f54_queue = { diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c index d36e89d6fc54..94e8bcbbf94d 100644 --- a/drivers/input/serio/hil_mlc.c +++ b/drivers/input/serio/hil_mlc.c @@ -1017,7 +1017,7 @@ static int __init hil_mlc_init(void) static void __exit hil_mlc_exit(void) { - del_timer_sync(&hil_mlcs_kicker); + timer_delete_sync(&hil_mlcs_kicker); tasklet_kill(&hil_mlcs_tasklet); } diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c index 13eacf6ab431..0eec4c5585cb 100644 --- a/drivers/input/serio/hp_sdc.c +++ b/drivers/input/serio/hp_sdc.c @@ -980,7 +980,7 @@ static void hp_sdc_exit(void) free_irq(hp_sdc.irq, &hp_sdc); write_unlock_irq(&hp_sdc.lock); - del_timer_sync(&hp_sdc.kicker); + timer_delete_sync(&hp_sdc.kicker); tasklet_kill(&hp_sdc.task); diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 1a03de7fcfa6..91a2b584dab1 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -103,6 +103,19 @@ config TOUCHSCREEN_ADC To compile this driver as a module, choose M here: the module will be called resistive-adc-touch.ko. +config TOUCHSCREEN_APPLE_Z2 + tristate "Apple Z2 touchscreens" + default ARCH_APPLE + depends on SPI && (ARCH_APPLE || COMPILE_TEST) + help + Say Y here if you have an ARM Apple device with + a touchscreen or a touchbar. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called apple_z2. + config TOUCHSCREEN_AR1021_I2C tristate "Microchip AR1020/1021 i2c touchscreen" depends on I2C && OF diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 82bc837ca01e..97a025c6a377 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_TOUCHSCREEN_AD7879_I2C) += ad7879-i2c.o obj-$(CONFIG_TOUCHSCREEN_AD7879_SPI) += ad7879-spi.o obj-$(CONFIG_TOUCHSCREEN_ADC) += resistive-adc-touch.o obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o +obj-$(CONFIG_TOUCHSCREEN_APPLE_Z2) += apple_z2.o obj-$(CONFIG_TOUCHSCREEN_AR1021_I2C) += ar1021_i2c.o obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT) += atmel_mxt_ts.o obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR) += auo-pixcir-ts.o diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c index a0598e9c7aff..8d8392ce7005 100644 --- a/drivers/input/touchscreen/ad7877.c +++ b/drivers/input/touchscreen/ad7877.c @@ -415,7 +415,7 @@ static void ad7877_disable(void *data) ts->disabled = true; disable_irq(ts->spi->irq); - if (del_timer_sync(&ts->timer)) + if (timer_delete_sync(&ts->timer)) ad7877_ts_event_release(ts); } diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c index e5d69bf2276e..f661e199b63c 100644 --- a/drivers/input/touchscreen/ad7879.c +++ b/drivers/input/touchscreen/ad7879.c @@ -273,7 +273,7 @@ static void __ad7879_disable(struct ad7879 *ts) AD7879_PM(AD7879_PM_SHUTDOWN); disable_irq(ts->irq); - if (del_timer_sync(&ts->timer)) + if (timer_delete_sync(&ts->timer)) ad7879_ts_event_release(ts); ad7879_write(ts, AD7879_REG_CTRL2, reg); diff --git a/drivers/input/touchscreen/apple_z2.c b/drivers/input/touchscreen/apple_z2.c new file mode 100644 index 000000000000..0de161eae59a --- /dev/null +++ b/drivers/input/touchscreen/apple_z2.c @@ -0,0 +1,477 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Apple Z2 touchscreen driver + * + * Copyright (C) The Asahi Linux Contributors + */ + +#include <linux/delay.h> +#include <linux/firmware.h> +#include <linux/input.h> +#include <linux/input/mt.h> +#include <linux/input/touchscreen.h> +#include <linux/interrupt.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/spi/spi.h> +#include <linux/unaligned.h> + +#define APPLE_Z2_NUM_FINGERS_OFFSET 16 +#define APPLE_Z2_FINGERS_OFFSET 24 +#define APPLE_Z2_TOUCH_STARTED 3 +#define APPLE_Z2_TOUCH_MOVED 4 +#define APPLE_Z2_CMD_READ_INTERRUPT_DATA 0xEB +#define APPLE_Z2_HBPP_CMD_BLOB 0x3001 +#define APPLE_Z2_FW_MAGIC 0x5746325A +#define LOAD_COMMAND_INIT_PAYLOAD 0 +#define LOAD_COMMAND_SEND_BLOB 1 +#define LOAD_COMMAND_SEND_CALIBRATION 2 +#define CAL_PROP_NAME "apple,z2-cal-blob" + +struct apple_z2 { + struct spi_device *spidev; + struct gpio_desc *reset_gpio; + struct input_dev *input_dev; + struct completion boot_irq; + bool booted; + int index_parity; + struct touchscreen_properties props; + const char *fw_name; + u8 *tx_buf; + u8 *rx_buf; +}; + +struct apple_z2_finger { + u8 finger; + u8 state; + __le16 unknown2; + __le16 abs_x; + __le16 abs_y; + __le16 rel_x; + __le16 rel_y; + __le16 tool_major; + __le16 tool_minor; + __le16 orientation; + __le16 touch_major; + __le16 touch_minor; + __le16 unused[2]; + __le16 pressure; + __le16 multi; +} __packed; + +struct apple_z2_hbpp_blob_hdr { + __le16 cmd; + __le16 len; + __le32 addr; + __le16 checksum; +}; + +struct apple_z2_fw_hdr { + __le32 magic; + __le32 version; +}; + +struct apple_z2_read_interrupt_cmd { + u8 cmd; + u8 counter; + u8 unused[12]; + __le16 checksum; +}; + +static void apple_z2_parse_touches(struct apple_z2 *z2, + const u8 *msg, size_t msg_len) +{ + int i; + int nfingers; + int slot; + int slot_valid; + struct apple_z2_finger *fingers; + + if (msg_len <= APPLE_Z2_NUM_FINGERS_OFFSET) + return; + nfingers = msg[APPLE_Z2_NUM_FINGERS_OFFSET]; + fingers = (struct apple_z2_finger *)(msg + APPLE_Z2_FINGERS_OFFSET); + for (i = 0; i < nfingers; i++) { + slot = input_mt_get_slot_by_key(z2->input_dev, fingers[i].finger); + if (slot < 0) { + dev_warn(&z2->spidev->dev, "unable to get slot for finger\n"); + continue; + } + slot_valid = fingers[i].state == APPLE_Z2_TOUCH_STARTED || + fingers[i].state == APPLE_Z2_TOUCH_MOVED; + input_mt_slot(z2->input_dev, slot); + if (!input_mt_report_slot_state(z2->input_dev, MT_TOOL_FINGER, slot_valid)) + continue; + touchscreen_report_pos(z2->input_dev, &z2->props, + le16_to_cpu(fingers[i].abs_x), + le16_to_cpu(fingers[i].abs_y), + true); + input_report_abs(z2->input_dev, ABS_MT_WIDTH_MAJOR, + le16_to_cpu(fingers[i].tool_major)); + input_report_abs(z2->input_dev, ABS_MT_WIDTH_MINOR, + le16_to_cpu(fingers[i].tool_minor)); + input_report_abs(z2->input_dev, ABS_MT_ORIENTATION, + le16_to_cpu(fingers[i].orientation)); + input_report_abs(z2->input_dev, ABS_MT_TOUCH_MAJOR, + le16_to_cpu(fingers[i].touch_major)); + input_report_abs(z2->input_dev, ABS_MT_TOUCH_MINOR, + le16_to_cpu(fingers[i].touch_minor)); + } + input_mt_sync_frame(z2->input_dev); + input_sync(z2->input_dev); +} + +static int apple_z2_read_packet(struct apple_z2 *z2) +{ + struct apple_z2_read_interrupt_cmd *len_cmd = (void *)z2->tx_buf; + struct spi_transfer xfer; + int error; + size_t pkt_len; + + memset(&xfer, 0, sizeof(xfer)); + len_cmd->cmd = APPLE_Z2_CMD_READ_INTERRUPT_DATA; + len_cmd->counter = z2->index_parity + 1; + len_cmd->checksum = + cpu_to_le16(APPLE_Z2_CMD_READ_INTERRUPT_DATA + len_cmd->counter); + z2->index_parity = !z2->index_parity; + xfer.tx_buf = z2->tx_buf; + xfer.rx_buf = z2->rx_buf; + xfer.len = sizeof(*len_cmd); + + error = spi_sync_transfer(z2->spidev, &xfer, 1); + if (error) + return error; + + pkt_len = (get_unaligned_le16(z2->rx_buf + 1) + 8) & 0xfffffffc; + + error = spi_read(z2->spidev, z2->rx_buf, pkt_len); + if (error) + return error; + + apple_z2_parse_touches(z2, z2->rx_buf + 5, pkt_len - 5); + + return 0; +} + +static irqreturn_t apple_z2_irq(int irq, void *data) +{ + struct apple_z2 *z2 = data; + + if (unlikely(!z2->booted)) + complete(&z2->boot_irq); + else + apple_z2_read_packet(z2); + + return IRQ_HANDLED; +} + +/* Build calibration blob, caller is responsible for freeing the blob data. */ +static const u8 *apple_z2_build_cal_blob(struct apple_z2 *z2, + u32 address, size_t *size) +{ + u8 *cal_data; + int cal_size; + size_t blob_size; + u32 checksum; + u16 checksum_hdr; + int i; + struct apple_z2_hbpp_blob_hdr *hdr; + int error; + + if (!device_property_present(&z2->spidev->dev, CAL_PROP_NAME)) + return NULL; + + cal_size = device_property_count_u8(&z2->spidev->dev, CAL_PROP_NAME); + if (cal_size < 0) + return ERR_PTR(cal_size); + + blob_size = sizeof(struct apple_z2_hbpp_blob_hdr) + cal_size + sizeof(__le32); + u8 *blob_data __free(kfree) = kzalloc(blob_size, GFP_KERNEL); + if (!blob_data) + return ERR_PTR(-ENOMEM); + + hdr = (struct apple_z2_hbpp_blob_hdr *)blob_data; + hdr->cmd = cpu_to_le16(APPLE_Z2_HBPP_CMD_BLOB); + hdr->len = cpu_to_le16(round_up(cal_size, 4) / 4); + hdr->addr = cpu_to_le32(address); + + checksum_hdr = 0; + for (i = 2; i < 8; i++) + checksum_hdr += blob_data[i]; + hdr->checksum = cpu_to_le16(checksum_hdr); + + cal_data = blob_data + sizeof(struct apple_z2_hbpp_blob_hdr); + error = device_property_read_u8_array(&z2->spidev->dev, CAL_PROP_NAME, + cal_data, cal_size); + if (error) + return ERR_PTR(error); + + checksum = 0; + for (i = 0; i < cal_size; i++) + checksum += cal_data[i]; + put_unaligned_le32(checksum, cal_data + cal_size); + + *size = blob_size; + return no_free_ptr(blob_data); +} + +static int apple_z2_send_firmware_blob(struct apple_z2 *z2, const u8 *data, + u32 size, bool init) +{ + struct spi_message msg; + struct spi_transfer blob_xfer, ack_xfer; + int error; + + z2->tx_buf[0] = 0x1a; + z2->tx_buf[1] = 0xa1; + + spi_message_init(&msg); + memset(&blob_xfer, 0, sizeof(blob_xfer)); + memset(&ack_xfer, 0, sizeof(ack_xfer)); + + blob_xfer.tx_buf = data; + blob_xfer.len = size; + blob_xfer.bits_per_word = init ? 8 : 16; + spi_message_add_tail(&blob_xfer, &msg); + + ack_xfer.tx_buf = z2->tx_buf; + ack_xfer.len = 2; + spi_message_add_tail(&ack_xfer, &msg); + + reinit_completion(&z2->boot_irq); + error = spi_sync(z2->spidev, &msg); + if (error) + return error; + + /* Irq only happens sometimes, but the thing boots reliably nonetheless */ + wait_for_completion_timeout(&z2->boot_irq, msecs_to_jiffies(20)); + + return 0; +} + +static int apple_z2_upload_firmware(struct apple_z2 *z2) +{ + const struct apple_z2_fw_hdr *fw_hdr; + size_t fw_idx = sizeof(struct apple_z2_fw_hdr); + int error; + u32 load_cmd; + u32 address; + bool init; + size_t size; + + const struct firmware *fw __free(firmware) = NULL; + error = request_firmware(&fw, z2->fw_name, &z2->spidev->dev); + if (error) { + dev_err(&z2->spidev->dev, "unable to load firmware\n"); + return error; + } + + fw_hdr = (const struct apple_z2_fw_hdr *)fw->data; + if (le32_to_cpu(fw_hdr->magic) != APPLE_Z2_FW_MAGIC || le32_to_cpu(fw_hdr->version) != 1) { + dev_err(&z2->spidev->dev, "invalid firmware header\n"); + return -EINVAL; + } + + /* + * This will interrupt the upload half-way if the file is malformed + * As the device has no non-volatile storage to corrupt, and gets reset + * on boot anyway, this is fine. + */ + while (fw_idx < fw->size) { + if (fw->size - fw_idx < 8) { + dev_err(&z2->spidev->dev, "firmware malformed\n"); + return -EINVAL; + } + + load_cmd = le32_to_cpup((__force __le32 *)(fw->data + fw_idx)); + fw_idx += sizeof(u32); + if (load_cmd == LOAD_COMMAND_INIT_PAYLOAD || load_cmd == LOAD_COMMAND_SEND_BLOB) { + size = le32_to_cpup((__force __le32 *)(fw->data + fw_idx)); + fw_idx += sizeof(u32); + if (fw->size - fw_idx < size) { + dev_err(&z2->spidev->dev, "firmware malformed\n"); + return -EINVAL; + } + init = load_cmd == LOAD_COMMAND_INIT_PAYLOAD; + error = apple_z2_send_firmware_blob(z2, fw->data + fw_idx, + size, init); + if (error) + return error; + fw_idx += size; + } else if (load_cmd == LOAD_COMMAND_SEND_CALIBRATION) { + address = le32_to_cpup((__force __le32 *)(fw->data + fw_idx)); + fw_idx += sizeof(u32); + + const u8 *data __free(kfree) = + apple_z2_build_cal_blob(z2, address, &size); + if (IS_ERR(data)) + return PTR_ERR(data); + + if (data) { + error = apple_z2_send_firmware_blob(z2, data, size, false); + if (error) + return error; + } + } else { + dev_err(&z2->spidev->dev, "firmware malformed\n"); + return -EINVAL; + } + fw_idx = round_up(fw_idx, 4); + } + + + z2->booted = true; + apple_z2_read_packet(z2); + return 0; +} + +static int apple_z2_boot(struct apple_z2 *z2) +{ + int error; + + reinit_completion(&z2->boot_irq); + enable_irq(z2->spidev->irq); + gpiod_set_value(z2->reset_gpio, 0); + if (!wait_for_completion_timeout(&z2->boot_irq, msecs_to_jiffies(20))) + return -ETIMEDOUT; + + error = apple_z2_upload_firmware(z2); + if (error) { + gpiod_set_value(z2->reset_gpio, 1); + disable_irq(z2->spidev->irq); + return error; + } + + return 0; +} + +static int apple_z2_probe(struct spi_device *spi) +{ + struct device *dev = &spi->dev; + struct apple_z2 *z2; + int error; + + z2 = devm_kzalloc(dev, sizeof(*z2), GFP_KERNEL); + if (!z2) + return -ENOMEM; + + z2->tx_buf = devm_kzalloc(dev, sizeof(struct apple_z2_read_interrupt_cmd), GFP_KERNEL); + if (!z2->tx_buf) + return -ENOMEM; + /* 4096 will end up being rounded up to 8192 due to devres header */ + z2->rx_buf = devm_kzalloc(dev, 4000, GFP_KERNEL); + if (!z2->rx_buf) + return -ENOMEM; + + z2->spidev = spi; + init_completion(&z2->boot_irq); + spi_set_drvdata(spi, z2); + + /* Reset the device on boot */ + z2->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(z2->reset_gpio)) + return dev_err_probe(dev, PTR_ERR(z2->reset_gpio), "unable to get reset\n"); + + error = devm_request_threaded_irq(dev, z2->spidev->irq, NULL, apple_z2_irq, + IRQF_ONESHOT | IRQF_NO_AUTOEN, + "apple-z2-irq", z2); + if (error) + return dev_err_probe(dev, error, "unable to request irq\n"); + + error = device_property_read_string(dev, "firmware-name", &z2->fw_name); + if (error) + return dev_err_probe(dev, error, "unable to get firmware name\n"); + + z2->input_dev = devm_input_allocate_device(dev); + if (!z2->input_dev) + return -ENOMEM; + + z2->input_dev->name = (char *)spi_get_device_id(spi)->driver_data; + z2->input_dev->phys = "apple_z2"; + z2->input_dev->id.bustype = BUS_SPI; + + /* Allocate the axes before setting from DT */ + input_set_abs_params(z2->input_dev, ABS_MT_POSITION_X, 0, 0, 0, 0); + input_set_abs_params(z2->input_dev, ABS_MT_POSITION_Y, 0, 0, 0, 0); + touchscreen_parse_properties(z2->input_dev, true, &z2->props); + input_abs_set_res(z2->input_dev, ABS_MT_POSITION_X, 100); + input_abs_set_res(z2->input_dev, ABS_MT_POSITION_Y, 100); + input_set_abs_params(z2->input_dev, ABS_MT_WIDTH_MAJOR, 0, 65535, 0, 0); + input_set_abs_params(z2->input_dev, ABS_MT_WIDTH_MINOR, 0, 65535, 0, 0); + input_set_abs_params(z2->input_dev, ABS_MT_TOUCH_MAJOR, 0, 65535, 0, 0); + input_set_abs_params(z2->input_dev, ABS_MT_TOUCH_MINOR, 0, 65535, 0, 0); + input_set_abs_params(z2->input_dev, ABS_MT_ORIENTATION, -32768, 32767, 0, 0); + + error = input_mt_init_slots(z2->input_dev, 256, INPUT_MT_DIRECT); + if (error) + return dev_err_probe(dev, error, "unable to initialize multitouch slots\n"); + + error = input_register_device(z2->input_dev); + if (error) + return dev_err_probe(dev, error, "unable to register input device\n"); + + /* Wait for device reset to finish */ + usleep_range(5000, 10000); + error = apple_z2_boot(z2); + if (error) + return error; + + return 0; +} + +static void apple_z2_shutdown(struct spi_device *spi) +{ + struct apple_z2 *z2 = spi_get_drvdata(spi); + + disable_irq(z2->spidev->irq); + gpiod_direction_output(z2->reset_gpio, 1); + z2->booted = false; +} + +static int apple_z2_suspend(struct device *dev) +{ + apple_z2_shutdown(to_spi_device(dev)); + + return 0; +} + +static int apple_z2_resume(struct device *dev) +{ + struct apple_z2 *z2 = spi_get_drvdata(to_spi_device(dev)); + + return apple_z2_boot(z2); +} + +static DEFINE_SIMPLE_DEV_PM_OPS(apple_z2_pm, apple_z2_suspend, apple_z2_resume); + +static const struct of_device_id apple_z2_of_match[] = { + { .compatible = "apple,j293-touchbar" }, + { .compatible = "apple,j493-touchbar" }, + {} +}; +MODULE_DEVICE_TABLE(of, apple_z2_of_match); + +static struct spi_device_id apple_z2_of_id[] = { + { .name = "j293-touchbar", .driver_data = (kernel_ulong_t)"MacBookPro17,1 Touch Bar" }, + { .name = "j493-touchbar", .driver_data = (kernel_ulong_t)"Mac14,7 Touch Bar" }, + {} +}; +MODULE_DEVICE_TABLE(spi, apple_z2_of_id); + +static struct spi_driver apple_z2_driver = { + .driver = { + .name = "apple-z2", + .pm = pm_sleep_ptr(&apple_z2_pm), + .of_match_table = apple_z2_of_match, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, + }, + .id_table = apple_z2_of_id, + .probe = apple_z2_probe, + .remove = apple_z2_shutdown, +}; + +module_spi_driver(apple_z2_driver); + +MODULE_LICENSE("GPL"); +MODULE_FIRMWARE("apple/dfrmtfw-*.bin"); +MODULE_DESCRIPTION("Apple Z2 touchscreens driver"); diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 3ddabc5a2c99..322d5a3d40a0 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -2535,8 +2535,6 @@ fault: static const struct vb2_ops mxt_queue_ops = { .queue_setup = mxt_queue_setup, .buf_queue = mxt_buffer_queue, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, }; static const struct vb2_queue mxt_queue = { diff --git a/drivers/input/touchscreen/bu21029_ts.c b/drivers/input/touchscreen/bu21029_ts.c index 686d0a6b1570..3c997fba7048 100644 --- a/drivers/input/touchscreen/bu21029_ts.c +++ b/drivers/input/touchscreen/bu21029_ts.c @@ -325,7 +325,7 @@ static void bu21029_stop_chip(struct input_dev *dev) struct bu21029_ts_data *bu21029 = input_get_drvdata(dev); disable_irq(bu21029->client->irq); - del_timer_sync(&bu21029->timer); + timer_delete_sync(&bu21029->timer); bu21029_put_chip_in_reset(bu21029); regulator_disable(bu21029->vdd); diff --git a/drivers/input/touchscreen/exc3000.c b/drivers/input/touchscreen/exc3000.c index fdda8412b164..9a5977d8cad2 100644 --- a/drivers/input/touchscreen/exc3000.c +++ b/drivers/input/touchscreen/exc3000.c @@ -174,7 +174,7 @@ static int exc3000_handle_mt_event(struct exc3000_data *data) /* * We read full state successfully, no contacts will be "stuck". */ - del_timer_sync(&data->timer); + timer_delete_sync(&data->timer); while (total_slots > 0) { int slots = min(total_slots, EXC3000_SLOTS_PER_FRAME); diff --git a/drivers/input/touchscreen/goodix_berlin.h b/drivers/input/touchscreen/goodix_berlin.h index 38b6f9ddbdef..d8bbd4853206 100644 --- a/drivers/input/touchscreen/goodix_berlin.h +++ b/drivers/input/touchscreen/goodix_berlin.h @@ -12,12 +12,26 @@ #include <linux/pm.h> +#define GOODIX_BERLIN_FW_VERSION_INFO_ADDR_A 0x1000C +#define GOODIX_BERLIN_FW_VERSION_INFO_ADDR_D 0x10014 + +#define GOODIX_BERLIN_IC_INFO_ADDR_A 0x10068 +#define GOODIX_BERLIN_IC_INFO_ADDR_D 0x10070 + +struct goodix_berlin_ic_data { + int fw_version_info_addr; + int ic_info_addr; + ssize_t read_dummy_len; + ssize_t read_prefix_len; +}; + struct device; struct input_id; struct regmap; int goodix_berlin_probe(struct device *dev, int irq, const struct input_id *id, - struct regmap *regmap); + struct regmap *regmap, + const struct goodix_berlin_ic_data *ic_data); extern const struct dev_pm_ops goodix_berlin_pm_ops; extern const struct attribute_group *goodix_berlin_groups[]; diff --git a/drivers/input/touchscreen/goodix_berlin_core.c b/drivers/input/touchscreen/goodix_berlin_core.c index 7f8cfdd106fa..02a1d9a465f2 100644 --- a/drivers/input/touchscreen/goodix_berlin_core.c +++ b/drivers/input/touchscreen/goodix_berlin_core.c @@ -12,7 +12,7 @@ * to the previous generations. * * Currently the driver only handles Multitouch events with already - * programmed firmware and "config" for "Revision D" Berlin IC. + * programmed firmware and "config" for "Revision A/D" Berlin IC. * * Support is missing for: * - ESD Management @@ -20,7 +20,7 @@ * - "Config" update/flashing * - Stylus Events * - Gesture Events - * - Support for older revisions (A & B) + * - Support for revision B */ #include <linux/bitfield.h> @@ -28,6 +28,7 @@ #include <linux/input.h> #include <linux/input/mt.h> #include <linux/input/touchscreen.h> +#include <linux/property.h> #include <linux/regmap.h> #include <linux/regulator/consumer.h> #include <linux/sizes.h> @@ -53,10 +54,8 @@ #define GOODIX_BERLIN_DEV_CONFIRM_VAL 0xAA #define GOODIX_BERLIN_BOOTOPTION_ADDR 0x10000 -#define GOODIX_BERLIN_FW_VERSION_INFO_ADDR 0x10014 #define GOODIX_BERLIN_IC_INFO_MAX_LEN SZ_1K -#define GOODIX_BERLIN_IC_INFO_ADDR 0x10070 #define GOODIX_BERLIN_CHECKSUM_SIZE sizeof(u16) @@ -175,6 +174,8 @@ struct goodix_berlin_core { /* Runtime parameters extracted from IC_INFO buffer */ u32 touch_data_addr; + const struct goodix_berlin_ic_data *ic_data; + struct goodix_berlin_event event; }; @@ -299,7 +300,7 @@ static int goodix_berlin_read_version(struct goodix_berlin_core *cd) { int error; - error = regmap_raw_read(cd->regmap, GOODIX_BERLIN_FW_VERSION_INFO_ADDR, + error = regmap_raw_read(cd->regmap, cd->ic_data->fw_version_info_addr, &cd->fw_version, sizeof(cd->fw_version)); if (error) { dev_err(cd->dev, "error reading fw version, %d\n", error); @@ -367,7 +368,7 @@ static int goodix_berlin_get_ic_info(struct goodix_berlin_core *cd) if (!afe_data) return -ENOMEM; - error = regmap_raw_read(cd->regmap, GOODIX_BERLIN_IC_INFO_ADDR, + error = regmap_raw_read(cd->regmap, cd->ic_data->ic_info_addr, &length_raw, sizeof(length_raw)); if (error) { dev_err(cd->dev, "failed get ic info length, %d\n", error); @@ -380,8 +381,8 @@ static int goodix_berlin_get_ic_info(struct goodix_berlin_core *cd) return -EINVAL; } - error = regmap_raw_read(cd->regmap, GOODIX_BERLIN_IC_INFO_ADDR, - afe_data, length); + error = regmap_raw_read(cd->regmap, cd->ic_data->ic_info_addr, afe_data, + length); if (error) { dev_err(cd->dev, "failed get ic info data, %d\n", error); return error; @@ -673,7 +674,7 @@ static void goodix_berlin_power_off_act(void *data) } static ssize_t registers_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, + const struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { struct device *dev = kobj_to_dev(kobj); @@ -686,7 +687,7 @@ static ssize_t registers_read(struct file *filp, struct kobject *kobj, } static ssize_t registers_write(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, + const struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { struct device *dev = kobj_to_dev(kobj); @@ -698,15 +699,15 @@ static ssize_t registers_write(struct file *filp, struct kobject *kobj, return error ? error : count; } -static BIN_ATTR_ADMIN_RW(registers, 0); +static const BIN_ATTR_ADMIN_RW(registers, 0); -static struct bin_attribute *goodix_berlin_bin_attrs[] = { +static const struct bin_attribute *const goodix_berlin_bin_attrs[] = { &bin_attr_registers, NULL, }; static const struct attribute_group goodix_berlin_attr_group = { - .bin_attrs = goodix_berlin_bin_attrs, + .bin_attrs_new = goodix_berlin_bin_attrs, }; const struct attribute_group *goodix_berlin_groups[] = { @@ -716,7 +717,8 @@ const struct attribute_group *goodix_berlin_groups[] = { EXPORT_SYMBOL_GPL(goodix_berlin_groups); int goodix_berlin_probe(struct device *dev, int irq, const struct input_id *id, - struct regmap *regmap) + struct regmap *regmap, + const struct goodix_berlin_ic_data *ic_data) { struct goodix_berlin_core *cd; int error; @@ -733,6 +735,7 @@ int goodix_berlin_probe(struct device *dev, int irq, const struct input_id *id, cd->dev = dev; cd->regmap = regmap; cd->irq = irq; + cd->ic_data = ic_data; cd->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(cd->reset_gpio)) diff --git a/drivers/input/touchscreen/goodix_berlin_i2c.c b/drivers/input/touchscreen/goodix_berlin_i2c.c index ad7a60d94338..929090a094bf 100644 --- a/drivers/input/touchscreen/goodix_berlin_i2c.c +++ b/drivers/input/touchscreen/goodix_berlin_i2c.c @@ -31,6 +31,8 @@ static const struct input_id goodix_berlin_i2c_input_id = { static int goodix_berlin_i2c_probe(struct i2c_client *client) { + const struct goodix_berlin_ic_data *ic_data = + i2c_get_match_data(client); struct regmap *regmap; int error; @@ -39,22 +41,28 @@ static int goodix_berlin_i2c_probe(struct i2c_client *client) return PTR_ERR(regmap); error = goodix_berlin_probe(&client->dev, client->irq, - &goodix_berlin_i2c_input_id, regmap); + &goodix_berlin_i2c_input_id, regmap, + ic_data); if (error) return error; return 0; } +static const struct goodix_berlin_ic_data gt9916_data = { + .fw_version_info_addr = GOODIX_BERLIN_FW_VERSION_INFO_ADDR_D, + .ic_info_addr = GOODIX_BERLIN_IC_INFO_ADDR_D, +}; + static const struct i2c_device_id goodix_berlin_i2c_id[] = { - { "gt9916" }, + { .name = "gt9916", .driver_data = (long)>9916_data }, { } }; MODULE_DEVICE_TABLE(i2c, goodix_berlin_i2c_id); static const struct of_device_id goodix_berlin_i2c_of_match[] = { - { .compatible = "goodix,gt9916", }, + { .compatible = "goodix,gt9916", .data = >9916_data }, { } }; MODULE_DEVICE_TABLE(of, goodix_berlin_i2c_of_match); diff --git a/drivers/input/touchscreen/goodix_berlin_spi.c b/drivers/input/touchscreen/goodix_berlin_spi.c index 0662e87b8692..01f850f484c2 100644 --- a/drivers/input/touchscreen/goodix_berlin_spi.c +++ b/drivers/input/touchscreen/goodix_berlin_spi.c @@ -18,10 +18,14 @@ #define GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN 1 #define GOODIX_BERLIN_REGISTER_WIDTH 4 -#define GOODIX_BERLIN_SPI_READ_DUMMY_LEN 3 -#define GOODIX_BERLIN_SPI_READ_PREFIX_LEN (GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN + \ +#define GOODIX_BERLIN_SPI_READ_DUMMY_LEN_A 4 +#define GOODIX_BERLIN_SPI_READ_DUMMY_LEN_D 3 +#define GOODIX_BERLIN_SPI_READ_PREFIX_LEN_A (GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN + \ GOODIX_BERLIN_REGISTER_WIDTH + \ - GOODIX_BERLIN_SPI_READ_DUMMY_LEN) + GOODIX_BERLIN_SPI_READ_DUMMY_LEN_A) +#define GOODIX_BERLIN_SPI_READ_PREFIX_LEN_D (GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN + \ + GOODIX_BERLIN_REGISTER_WIDTH + \ + GOODIX_BERLIN_SPI_READ_DUMMY_LEN_D) #define GOODIX_BERLIN_SPI_WRITE_PREFIX_LEN (GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN + \ GOODIX_BERLIN_REGISTER_WIDTH) @@ -33,6 +37,7 @@ static int goodix_berlin_spi_read(void *context, const void *reg_buf, size_t val_size) { struct spi_device *spi = context; + const struct goodix_berlin_ic_data *ic_data = spi_get_device_match_data(spi); struct spi_transfer xfers; struct spi_message spi_msg; const u32 *reg = reg_buf; /* reg is stored as native u32 at start of buffer */ @@ -42,23 +47,22 @@ static int goodix_berlin_spi_read(void *context, const void *reg_buf, return -EINVAL; u8 *buf __free(kfree) = - kzalloc(GOODIX_BERLIN_SPI_READ_PREFIX_LEN + val_size, - GFP_KERNEL); + kzalloc(ic_data->read_prefix_len + val_size, GFP_KERNEL); if (!buf) return -ENOMEM; spi_message_init(&spi_msg); memset(&xfers, 0, sizeof(xfers)); - /* buffer format: 0xF1 + addr(4bytes) + dummy(3bytes) + data */ + /* buffer format: 0xF1 + addr(4bytes) + dummy(3/4bytes) + data */ buf[0] = GOODIX_BERLIN_SPI_READ_FLAG; put_unaligned_be32(*reg, buf + GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN); memset(buf + GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN + GOODIX_BERLIN_REGISTER_WIDTH, - 0xff, GOODIX_BERLIN_SPI_READ_DUMMY_LEN); + 0xff, ic_data->read_dummy_len); xfers.tx_buf = buf; xfers.rx_buf = buf; - xfers.len = GOODIX_BERLIN_SPI_READ_PREFIX_LEN + val_size; + xfers.len = ic_data->read_prefix_len + val_size; xfers.cs_change = 0; spi_message_add_tail(&xfers, &spi_msg); @@ -68,7 +72,7 @@ static int goodix_berlin_spi_read(void *context, const void *reg_buf, return error; } - memcpy(val_buf, buf + GOODIX_BERLIN_SPI_READ_PREFIX_LEN, val_size); + memcpy(val_buf, buf + ic_data->read_prefix_len, val_size); return error; } @@ -123,6 +127,7 @@ static const struct input_id goodix_berlin_spi_input_id = { static int goodix_berlin_spi_probe(struct spi_device *spi) { + const struct goodix_berlin_ic_data *ic_data = spi_get_device_match_data(spi); struct regmap_config regmap_config; struct regmap *regmap; size_t max_size; @@ -137,7 +142,7 @@ static int goodix_berlin_spi_probe(struct spi_device *spi) max_size = spi_max_transfer_size(spi); regmap_config = goodix_berlin_spi_regmap_conf; - regmap_config.max_raw_read = max_size - GOODIX_BERLIN_SPI_READ_PREFIX_LEN; + regmap_config.max_raw_read = max_size - ic_data->read_prefix_len; regmap_config.max_raw_write = max_size - GOODIX_BERLIN_SPI_WRITE_PREFIX_LEN; regmap = devm_regmap_init(&spi->dev, NULL, spi, ®map_config); @@ -145,21 +150,38 @@ static int goodix_berlin_spi_probe(struct spi_device *spi) return PTR_ERR(regmap); error = goodix_berlin_probe(&spi->dev, spi->irq, - &goodix_berlin_spi_input_id, regmap); + &goodix_berlin_spi_input_id, regmap, + ic_data); if (error) return error; return 0; } +static const struct goodix_berlin_ic_data gt9897_data = { + .fw_version_info_addr = GOODIX_BERLIN_FW_VERSION_INFO_ADDR_A, + .ic_info_addr = GOODIX_BERLIN_IC_INFO_ADDR_A, + .read_dummy_len = GOODIX_BERLIN_SPI_READ_DUMMY_LEN_A, + .read_prefix_len = GOODIX_BERLIN_SPI_READ_PREFIX_LEN_A, +}; + +static const struct goodix_berlin_ic_data gt9916_data = { + .fw_version_info_addr = GOODIX_BERLIN_FW_VERSION_INFO_ADDR_D, + .ic_info_addr = GOODIX_BERLIN_IC_INFO_ADDR_D, + .read_dummy_len = GOODIX_BERLIN_SPI_READ_DUMMY_LEN_D, + .read_prefix_len = GOODIX_BERLIN_SPI_READ_PREFIX_LEN_D, +}; + static const struct spi_device_id goodix_berlin_spi_ids[] = { - { "gt9916" }, + { .name = "gt9897", .driver_data = (long)>9897_data }, + { .name = "gt9916", .driver_data = (long)>9916_data }, { }, }; MODULE_DEVICE_TABLE(spi, goodix_berlin_spi_ids); static const struct of_device_id goodix_berlin_spi_of_match[] = { - { .compatible = "goodix,gt9916", }, + { .compatible = "goodix,gt9897", .data = >9897_data }, + { .compatible = "goodix,gt9916", .data = >9916_data }, { } }; MODULE_DEVICE_TABLE(of, goodix_berlin_spi_of_match); diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c index 8365a2ac6fce..7b3b10cbfcfc 100644 --- a/drivers/input/touchscreen/sur40.c +++ b/drivers/input/touchscreen/sur40.c @@ -1108,8 +1108,6 @@ static const struct vb2_ops sur40_queue_ops = { .buf_queue = sur40_buffer_queue, .start_streaming = sur40_start_streaming, .stop_streaming = sur40_stop_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, }; static const struct vb2_queue sur40_queue = { diff --git a/drivers/input/touchscreen/sx8654.c b/drivers/input/touchscreen/sx8654.c index f5c5881cef6b..e59b8d0ed19e 100644 --- a/drivers/input/touchscreen/sx8654.c +++ b/drivers/input/touchscreen/sx8654.c @@ -290,7 +290,7 @@ static void sx8654_close(struct input_dev *dev) disable_irq(client->irq); if (!sx8654->data->has_irq_penrelease) - del_timer_sync(&sx8654->timer); + timer_delete_sync(&sx8654->timer); /* enable manual mode mode */ error = i2c_smbus_write_byte(client, sx8654->data->cmd_manual); diff --git a/drivers/input/touchscreen/tsc2007.h b/drivers/input/touchscreen/tsc2007.h index 69b08dd6c8df..e346fb4f7552 100644 --- a/drivers/input/touchscreen/tsc2007.h +++ b/drivers/input/touchscreen/tsc2007.h @@ -19,6 +19,7 @@ #ifndef _TSC2007_H #define _TSC2007_H +#include <linux/input/touchscreen.h> struct gpio_desc; #define TSC2007_MEASURE_TEMP0 (0x0 << 4) @@ -63,6 +64,7 @@ struct tsc2007 { struct i2c_client *client; + struct touchscreen_properties prop; u16 model; u16 x_plate_ohms; u16 max_rt; diff --git a/drivers/input/touchscreen/tsc2007_core.c b/drivers/input/touchscreen/tsc2007_core.c index 8d832a372b89..5252301686ec 100644 --- a/drivers/input/touchscreen/tsc2007_core.c +++ b/drivers/input/touchscreen/tsc2007_core.c @@ -142,8 +142,7 @@ static irqreturn_t tsc2007_soft_irq(int irq, void *handle) rt = ts->max_rt - rt; input_report_key(input, BTN_TOUCH, 1); - input_report_abs(input, ABS_X, tc.x); - input_report_abs(input, ABS_Y, tc.y); + touchscreen_report_pos(input, &ts->prop, tc.x, tc.y, false); input_report_abs(input, ABS_PRESSURE, rt); input_sync(input); @@ -339,9 +338,9 @@ static int tsc2007_probe(struct i2c_client *client) input_set_drvdata(input_dev, ts); input_set_capability(input_dev, EV_KEY, BTN_TOUCH); - 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); + touchscreen_parse_properties(input_dev, false, &ts->prop); input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, ts->fuzzz, 0); diff --git a/drivers/input/touchscreen/tsc200x-core.c b/drivers/input/touchscreen/tsc200x-core.c index df39dee13e1c..252a93753ee5 100644 --- a/drivers/input/touchscreen/tsc200x-core.c +++ b/drivers/input/touchscreen/tsc200x-core.c @@ -229,7 +229,7 @@ static void __tsc200x_disable(struct tsc200x *ts) guard(disable_irq)(&ts->irq); - del_timer_sync(&ts->penup_timer); + timer_delete_sync(&ts->penup_timer); cancel_delayed_work_sync(&ts->esd_work); } @@ -388,7 +388,7 @@ static void tsc200x_esd_work(struct work_struct *work) dev_info(ts->dev, "TSC200X not responding - resetting\n"); scoped_guard(disable_irq, &ts->irq) { - del_timer_sync(&ts->penup_timer); + timer_delete_sync(&ts->penup_timer); tsc200x_update_pen_state(ts, 0, 0, 0); tsc200x_reset(ts); } |