162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2012-2020 Synaptics Incorporated 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <linux/kernel.h> 762306a36Sopenharmony_ci#include <linux/rmi.h> 862306a36Sopenharmony_ci#include <linux/input.h> 962306a36Sopenharmony_ci#include <linux/slab.h> 1062306a36Sopenharmony_ci#include "rmi_driver.h" 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#define RMI_F3A_MAX_GPIO_COUNT 128 1362306a36Sopenharmony_ci#define RMI_F3A_MAX_REG_SIZE DIV_ROUND_UP(RMI_F3A_MAX_GPIO_COUNT, 8) 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci/* Defs for Query 0 */ 1662306a36Sopenharmony_ci#define RMI_F3A_GPIO_COUNT 0x7F 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#define RMI_F3A_DATA_REGS_MAX_SIZE RMI_F3A_MAX_REG_SIZE 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#define TRACKSTICK_RANGE_START 3 2162306a36Sopenharmony_ci#define TRACKSTICK_RANGE_END 6 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistruct f3a_data { 2462306a36Sopenharmony_ci /* Query Data */ 2562306a36Sopenharmony_ci u8 gpio_count; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci u8 register_count; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci u8 data_regs[RMI_F3A_DATA_REGS_MAX_SIZE]; 3062306a36Sopenharmony_ci u16 *gpio_key_map; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci struct input_dev *input; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci struct rmi_function *f03; 3562306a36Sopenharmony_ci bool trackstick_buttons; 3662306a36Sopenharmony_ci}; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_cistatic void rmi_f3a_report_button(struct rmi_function *fn, 3962306a36Sopenharmony_ci struct f3a_data *f3a, unsigned int button) 4062306a36Sopenharmony_ci{ 4162306a36Sopenharmony_ci u16 key_code = f3a->gpio_key_map[button]; 4262306a36Sopenharmony_ci bool key_down = !(f3a->data_regs[0] & BIT(button)); 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci if (f3a->trackstick_buttons && 4562306a36Sopenharmony_ci button >= TRACKSTICK_RANGE_START && 4662306a36Sopenharmony_ci button <= TRACKSTICK_RANGE_END) { 4762306a36Sopenharmony_ci rmi_f03_overwrite_button(f3a->f03, key_code, key_down); 4862306a36Sopenharmony_ci } else { 4962306a36Sopenharmony_ci rmi_dbg(RMI_DEBUG_FN, &fn->dev, 5062306a36Sopenharmony_ci "%s: call input report key (0x%04x) value (0x%02x)", 5162306a36Sopenharmony_ci __func__, key_code, key_down); 5262306a36Sopenharmony_ci input_report_key(f3a->input, key_code, key_down); 5362306a36Sopenharmony_ci } 5462306a36Sopenharmony_ci} 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cistatic irqreturn_t rmi_f3a_attention(int irq, void *ctx) 5762306a36Sopenharmony_ci{ 5862306a36Sopenharmony_ci struct rmi_function *fn = ctx; 5962306a36Sopenharmony_ci struct f3a_data *f3a = dev_get_drvdata(&fn->dev); 6062306a36Sopenharmony_ci struct rmi_driver_data *drvdata = dev_get_drvdata(&fn->rmi_dev->dev); 6162306a36Sopenharmony_ci int error; 6262306a36Sopenharmony_ci int i; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci if (drvdata->attn_data.data) { 6562306a36Sopenharmony_ci if (drvdata->attn_data.size < f3a->register_count) { 6662306a36Sopenharmony_ci dev_warn(&fn->dev, 6762306a36Sopenharmony_ci "F3A interrupted, but data is missing\n"); 6862306a36Sopenharmony_ci return IRQ_HANDLED; 6962306a36Sopenharmony_ci } 7062306a36Sopenharmony_ci memcpy(f3a->data_regs, drvdata->attn_data.data, 7162306a36Sopenharmony_ci f3a->register_count); 7262306a36Sopenharmony_ci drvdata->attn_data.data += f3a->register_count; 7362306a36Sopenharmony_ci drvdata->attn_data.size -= f3a->register_count; 7462306a36Sopenharmony_ci } else { 7562306a36Sopenharmony_ci error = rmi_read_block(fn->rmi_dev, fn->fd.data_base_addr, 7662306a36Sopenharmony_ci f3a->data_regs, f3a->register_count); 7762306a36Sopenharmony_ci if (error) { 7862306a36Sopenharmony_ci dev_err(&fn->dev, 7962306a36Sopenharmony_ci "%s: Failed to read F3a data registers: %d\n", 8062306a36Sopenharmony_ci __func__, error); 8162306a36Sopenharmony_ci return IRQ_RETVAL(error); 8262306a36Sopenharmony_ci } 8362306a36Sopenharmony_ci } 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci for (i = 0; i < f3a->gpio_count; i++) 8662306a36Sopenharmony_ci if (f3a->gpio_key_map[i] != KEY_RESERVED) 8762306a36Sopenharmony_ci rmi_f3a_report_button(fn, f3a, i); 8862306a36Sopenharmony_ci if (f3a->trackstick_buttons) 8962306a36Sopenharmony_ci rmi_f03_commit_buttons(f3a->f03); 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci return IRQ_HANDLED; 9262306a36Sopenharmony_ci} 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_cistatic int rmi_f3a_config(struct rmi_function *fn) 9562306a36Sopenharmony_ci{ 9662306a36Sopenharmony_ci struct f3a_data *f3a = dev_get_drvdata(&fn->dev); 9762306a36Sopenharmony_ci struct rmi_driver *drv = fn->rmi_dev->driver; 9862306a36Sopenharmony_ci const struct rmi_device_platform_data *pdata = 9962306a36Sopenharmony_ci rmi_get_platform_data(fn->rmi_dev); 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci if (!f3a) 10262306a36Sopenharmony_ci return 0; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci if (pdata->gpio_data.trackstick_buttons) { 10562306a36Sopenharmony_ci /* Try [re-]establish link to F03. */ 10662306a36Sopenharmony_ci f3a->f03 = rmi_find_function(fn->rmi_dev, 0x03); 10762306a36Sopenharmony_ci f3a->trackstick_buttons = f3a->f03 != NULL; 10862306a36Sopenharmony_ci } 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci drv->set_irq_bits(fn->rmi_dev, fn->irq_mask); 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci return 0; 11362306a36Sopenharmony_ci} 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_cistatic bool rmi_f3a_is_valid_button(int button, struct f3a_data *f3a, 11662306a36Sopenharmony_ci u8 *query1_regs, u8 *ctrl1_regs) 11762306a36Sopenharmony_ci{ 11862306a36Sopenharmony_ci /* gpio exist && direction input */ 11962306a36Sopenharmony_ci return (query1_regs[0] & BIT(button)) && !(ctrl1_regs[0] & BIT(button)); 12062306a36Sopenharmony_ci} 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_cistatic int rmi_f3a_map_gpios(struct rmi_function *fn, struct f3a_data *f3a, 12362306a36Sopenharmony_ci u8 *query1_regs, u8 *ctrl1_regs) 12462306a36Sopenharmony_ci{ 12562306a36Sopenharmony_ci const struct rmi_device_platform_data *pdata = 12662306a36Sopenharmony_ci rmi_get_platform_data(fn->rmi_dev); 12762306a36Sopenharmony_ci struct input_dev *input = f3a->input; 12862306a36Sopenharmony_ci unsigned int button = BTN_LEFT; 12962306a36Sopenharmony_ci unsigned int trackstick_button = BTN_LEFT; 13062306a36Sopenharmony_ci bool button_mapped = false; 13162306a36Sopenharmony_ci int i; 13262306a36Sopenharmony_ci int button_count = min_t(u8, f3a->gpio_count, TRACKSTICK_RANGE_END); 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci f3a->gpio_key_map = devm_kcalloc(&fn->dev, 13562306a36Sopenharmony_ci button_count, 13662306a36Sopenharmony_ci sizeof(f3a->gpio_key_map[0]), 13762306a36Sopenharmony_ci GFP_KERNEL); 13862306a36Sopenharmony_ci if (!f3a->gpio_key_map) { 13962306a36Sopenharmony_ci dev_err(&fn->dev, "Failed to allocate gpio map memory.\n"); 14062306a36Sopenharmony_ci return -ENOMEM; 14162306a36Sopenharmony_ci } 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci for (i = 0; i < button_count; i++) { 14462306a36Sopenharmony_ci if (!rmi_f3a_is_valid_button(i, f3a, query1_regs, ctrl1_regs)) 14562306a36Sopenharmony_ci continue; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci if (pdata->gpio_data.trackstick_buttons && 14862306a36Sopenharmony_ci i >= TRACKSTICK_RANGE_START && 14962306a36Sopenharmony_ci i < TRACKSTICK_RANGE_END) { 15062306a36Sopenharmony_ci f3a->gpio_key_map[i] = trackstick_button++; 15162306a36Sopenharmony_ci } else if (!pdata->gpio_data.buttonpad || !button_mapped) { 15262306a36Sopenharmony_ci f3a->gpio_key_map[i] = button; 15362306a36Sopenharmony_ci input_set_capability(input, EV_KEY, button++); 15462306a36Sopenharmony_ci button_mapped = true; 15562306a36Sopenharmony_ci } 15662306a36Sopenharmony_ci } 15762306a36Sopenharmony_ci input->keycode = f3a->gpio_key_map; 15862306a36Sopenharmony_ci input->keycodesize = sizeof(f3a->gpio_key_map[0]); 15962306a36Sopenharmony_ci input->keycodemax = f3a->gpio_count; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci if (pdata->gpio_data.buttonpad || (button - BTN_LEFT == 1)) 16262306a36Sopenharmony_ci __set_bit(INPUT_PROP_BUTTONPAD, input->propbit); 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci return 0; 16562306a36Sopenharmony_ci} 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_cistatic int rmi_f3a_initialize(struct rmi_function *fn, struct f3a_data *f3a) 16862306a36Sopenharmony_ci{ 16962306a36Sopenharmony_ci u8 query1[RMI_F3A_MAX_REG_SIZE]; 17062306a36Sopenharmony_ci u8 ctrl1[RMI_F3A_MAX_REG_SIZE]; 17162306a36Sopenharmony_ci u8 buf; 17262306a36Sopenharmony_ci int error; 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci error = rmi_read(fn->rmi_dev, fn->fd.query_base_addr, &buf); 17562306a36Sopenharmony_ci if (error < 0) { 17662306a36Sopenharmony_ci dev_err(&fn->dev, "Failed to read general info register: %d\n", 17762306a36Sopenharmony_ci error); 17862306a36Sopenharmony_ci return -ENODEV; 17962306a36Sopenharmony_ci } 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci f3a->gpio_count = buf & RMI_F3A_GPIO_COUNT; 18262306a36Sopenharmony_ci f3a->register_count = DIV_ROUND_UP(f3a->gpio_count, 8); 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci /* Query1 -> gpio exist */ 18562306a36Sopenharmony_ci error = rmi_read_block(fn->rmi_dev, fn->fd.query_base_addr + 1, 18662306a36Sopenharmony_ci query1, f3a->register_count); 18762306a36Sopenharmony_ci if (error) { 18862306a36Sopenharmony_ci dev_err(&fn->dev, "Failed to read query1 register\n"); 18962306a36Sopenharmony_ci return error; 19062306a36Sopenharmony_ci } 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci /* Ctrl1 -> gpio direction */ 19362306a36Sopenharmony_ci error = rmi_read_block(fn->rmi_dev, fn->fd.control_base_addr + 1, 19462306a36Sopenharmony_ci ctrl1, f3a->register_count); 19562306a36Sopenharmony_ci if (error) { 19662306a36Sopenharmony_ci dev_err(&fn->dev, "Failed to read control1 register\n"); 19762306a36Sopenharmony_ci return error; 19862306a36Sopenharmony_ci } 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci error = rmi_f3a_map_gpios(fn, f3a, query1, ctrl1); 20162306a36Sopenharmony_ci if (error) 20262306a36Sopenharmony_ci return error; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci return 0; 20562306a36Sopenharmony_ci} 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_cistatic int rmi_f3a_probe(struct rmi_function *fn) 20862306a36Sopenharmony_ci{ 20962306a36Sopenharmony_ci struct rmi_device *rmi_dev = fn->rmi_dev; 21062306a36Sopenharmony_ci struct rmi_driver_data *drv_data = dev_get_drvdata(&rmi_dev->dev); 21162306a36Sopenharmony_ci struct f3a_data *f3a; 21262306a36Sopenharmony_ci int error; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci if (!drv_data->input) { 21562306a36Sopenharmony_ci dev_info(&fn->dev, "F3A: no input device found, ignoring\n"); 21662306a36Sopenharmony_ci return -ENXIO; 21762306a36Sopenharmony_ci } 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci f3a = devm_kzalloc(&fn->dev, sizeof(*f3a), GFP_KERNEL); 22062306a36Sopenharmony_ci if (!f3a) 22162306a36Sopenharmony_ci return -ENOMEM; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci f3a->input = drv_data->input; 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci error = rmi_f3a_initialize(fn, f3a); 22662306a36Sopenharmony_ci if (error) 22762306a36Sopenharmony_ci return error; 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci dev_set_drvdata(&fn->dev, f3a); 23062306a36Sopenharmony_ci return 0; 23162306a36Sopenharmony_ci} 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_cistruct rmi_function_handler rmi_f3a_handler = { 23462306a36Sopenharmony_ci .driver = { 23562306a36Sopenharmony_ci .name = "rmi4_f3a", 23662306a36Sopenharmony_ci }, 23762306a36Sopenharmony_ci .func = 0x3a, 23862306a36Sopenharmony_ci .probe = rmi_f3a_probe, 23962306a36Sopenharmony_ci .config = rmi_f3a_config, 24062306a36Sopenharmony_ci .attention = rmi_f3a_attention, 24162306a36Sopenharmony_ci}; 242