linux/drivers/input/rmi4/rmi_f30.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (c) 2012-2016 Synaptics Incorporated
   4 */
   5
   6#include <linux/kernel.h>
   7#include <linux/rmi.h>
   8#include <linux/input.h>
   9#include <linux/slab.h>
  10#include "rmi_driver.h"
  11
  12#define RMI_F30_QUERY_SIZE                      2
  13
  14/* Defs for Query 0 */
  15#define RMI_F30_EXTENDED_PATTERNS               0x01
  16#define RMI_F30_HAS_MAPPABLE_BUTTONS            BIT(1)
  17#define RMI_F30_HAS_LED                         BIT(2)
  18#define RMI_F30_HAS_GPIO                        BIT(3)
  19#define RMI_F30_HAS_HAPTIC                      BIT(4)
  20#define RMI_F30_HAS_GPIO_DRV_CTL                BIT(5)
  21#define RMI_F30_HAS_MECH_MOUSE_BTNS             BIT(6)
  22
  23/* Defs for Query 1 */
  24#define RMI_F30_GPIO_LED_COUNT                  0x1F
  25
  26/* Defs for Control Registers */
  27#define RMI_F30_CTRL_1_GPIO_DEBOUNCE            0x01
  28#define RMI_F30_CTRL_1_HALT                     BIT(4)
  29#define RMI_F30_CTRL_1_HALTED                   BIT(5)
  30#define RMI_F30_CTRL_10_NUM_MECH_MOUSE_BTNS     0x03
  31
  32#define RMI_F30_CTRL_MAX_REGS           32
  33#define RMI_F30_CTRL_MAX_BYTES          DIV_ROUND_UP(RMI_F30_CTRL_MAX_REGS, 8)
  34#define RMI_F30_CTRL_MAX_REG_BLOCKS     11
  35
  36#define RMI_F30_CTRL_REGS_MAX_SIZE (RMI_F30_CTRL_MAX_BYTES              \
  37                                        + 1                             \
  38                                        + RMI_F30_CTRL_MAX_BYTES        \
  39                                        + RMI_F30_CTRL_MAX_BYTES        \
  40                                        + RMI_F30_CTRL_MAX_BYTES        \
  41                                        + 6                             \
  42                                        + RMI_F30_CTRL_MAX_REGS         \
  43                                        + RMI_F30_CTRL_MAX_REGS         \
  44                                        + RMI_F30_CTRL_MAX_BYTES        \
  45                                        + 1                             \
  46                                        + 1)
  47
  48#define TRACKSTICK_RANGE_START          3
  49#define TRACKSTICK_RANGE_END            6
  50
  51struct rmi_f30_ctrl_data {
  52        int address;
  53        int length;
  54        u8 *regs;
  55};
  56
  57struct f30_data {
  58        /* Query Data */
  59        bool has_extended_pattern;
  60        bool has_mappable_buttons;
  61        bool has_led;
  62        bool has_gpio;
  63        bool has_haptic;
  64        bool has_gpio_driver_control;
  65        bool has_mech_mouse_btns;
  66        u8 gpioled_count;
  67
  68        u8 register_count;
  69
  70        /* Control Register Data */
  71        struct rmi_f30_ctrl_data ctrl[RMI_F30_CTRL_MAX_REG_BLOCKS];
  72        u8 ctrl_regs[RMI_F30_CTRL_REGS_MAX_SIZE];
  73        u32 ctrl_regs_size;
  74
  75        u8 data_regs[RMI_F30_CTRL_MAX_BYTES];
  76        u16 *gpioled_key_map;
  77
  78        struct input_dev *input;
  79
  80        struct rmi_function *f03;
  81        bool trackstick_buttons;
  82};
  83
  84static int rmi_f30_read_control_parameters(struct rmi_function *fn,
  85                                                struct f30_data *f30)
  86{
  87        int error;
  88
  89        error = rmi_read_block(fn->rmi_dev, fn->fd.control_base_addr,
  90                               f30->ctrl_regs, f30->ctrl_regs_size);
  91        if (error) {
  92                dev_err(&fn->dev,
  93                        "%s: Could not read control registers at 0x%x: %d\n",
  94                        __func__, fn->fd.control_base_addr, error);
  95                return error;
  96        }
  97
  98        return 0;
  99}
 100
 101static void rmi_f30_report_button(struct rmi_function *fn,
 102                                  struct f30_data *f30, unsigned int button)
 103{
 104        unsigned int reg_num = button >> 3;
 105        unsigned int bit_num = button & 0x07;
 106        u16 key_code = f30->gpioled_key_map[button];
 107        bool key_down = !(f30->data_regs[reg_num] & BIT(bit_num));
 108
 109        if (f30->trackstick_buttons &&
 110            button >= TRACKSTICK_RANGE_START &&
 111            button <= TRACKSTICK_RANGE_END) {
 112                rmi_f03_overwrite_button(f30->f03, key_code, key_down);
 113        } else {
 114                rmi_dbg(RMI_DEBUG_FN, &fn->dev,
 115                        "%s: call input report key (0x%04x) value (0x%02x)",
 116                        __func__, key_code, key_down);
 117
 118                input_report_key(f30->input, key_code, key_down);
 119        }
 120}
 121
 122static irqreturn_t rmi_f30_attention(int irq, void *ctx)
 123{
 124        struct rmi_function *fn = ctx;
 125        struct f30_data *f30 = dev_get_drvdata(&fn->dev);
 126        struct rmi_driver_data *drvdata = dev_get_drvdata(&fn->rmi_dev->dev);
 127        int error;
 128        int i;
 129
 130        /* Read the gpi led data. */
 131        if (drvdata->attn_data.data) {
 132                if (drvdata->attn_data.size < f30->register_count) {
 133                        dev_warn(&fn->dev,
 134                                 "F30 interrupted, but data is missing\n");
 135                        return IRQ_HANDLED;
 136                }
 137                memcpy(f30->data_regs, drvdata->attn_data.data,
 138                        f30->register_count);
 139                drvdata->attn_data.data += f30->register_count;
 140                drvdata->attn_data.size -= f30->register_count;
 141        } else {
 142                error = rmi_read_block(fn->rmi_dev, fn->fd.data_base_addr,
 143                                       f30->data_regs, f30->register_count);
 144                if (error) {
 145                        dev_err(&fn->dev,
 146                                "%s: Failed to read F30 data registers: %d\n",
 147                                __func__, error);
 148                        return IRQ_RETVAL(error);
 149                }
 150        }
 151
 152        if (f30->has_gpio) {
 153                for (i = 0; i < f30->gpioled_count; i++)
 154                        if (f30->gpioled_key_map[i] != KEY_RESERVED)
 155                                rmi_f30_report_button(fn, f30, i);
 156                if (f30->trackstick_buttons)
 157                        rmi_f03_commit_buttons(f30->f03);
 158        }
 159
 160        return IRQ_HANDLED;
 161}
 162
 163static int rmi_f30_config(struct rmi_function *fn)
 164{
 165        struct f30_data *f30 = dev_get_drvdata(&fn->dev);
 166        struct rmi_driver *drv = fn->rmi_dev->driver;
 167        const struct rmi_device_platform_data *pdata =
 168                                rmi_get_platform_data(fn->rmi_dev);
 169        int error;
 170
 171        /* can happen if f30_data.disable is set */
 172        if (!f30)
 173                return 0;
 174
 175        if (pdata->f30_data.trackstick_buttons) {
 176                /* Try [re-]establish link to F03. */
 177                f30->f03 = rmi_find_function(fn->rmi_dev, 0x03);
 178                f30->trackstick_buttons = f30->f03 != NULL;
 179        }
 180
 181        if (pdata->f30_data.disable) {
 182                drv->clear_irq_bits(fn->rmi_dev, fn->irq_mask);
 183        } else {
 184                /* Write Control Register values back to device */
 185                error = rmi_write_block(fn->rmi_dev, fn->fd.control_base_addr,
 186                                        f30->ctrl_regs, f30->ctrl_regs_size);
 187                if (error) {
 188                        dev_err(&fn->dev,
 189                                "%s: Could not write control registers at 0x%x: %d\n",
 190                                __func__, fn->fd.control_base_addr, error);
 191                        return error;
 192                }
 193
 194                drv->set_irq_bits(fn->rmi_dev, fn->irq_mask);
 195        }
 196
 197        return 0;
 198}
 199
 200static void rmi_f30_set_ctrl_data(struct rmi_f30_ctrl_data *ctrl,
 201                                  int *ctrl_addr, int len, u8 **reg)
 202{
 203        ctrl->address = *ctrl_addr;
 204        ctrl->length = len;
 205        ctrl->regs = *reg;
 206        *ctrl_addr += len;
 207        *reg += len;
 208}
 209
 210static bool rmi_f30_is_valid_button(int button, struct rmi_f30_ctrl_data *ctrl)
 211{
 212        int byte_position = button >> 3;
 213        int bit_position = button & 0x07;
 214
 215        /*
 216         * ctrl2 -> dir == 0 -> input mode
 217         * ctrl3 -> data == 1 -> actual button
 218         */
 219        return !(ctrl[2].regs[byte_position] & BIT(bit_position)) &&
 220                (ctrl[3].regs[byte_position] & BIT(bit_position));
 221}
 222
 223static int rmi_f30_map_gpios(struct rmi_function *fn,
 224                             struct f30_data *f30)
 225{
 226        const struct rmi_device_platform_data *pdata =
 227                                        rmi_get_platform_data(fn->rmi_dev);
 228        struct input_dev *input = f30->input;
 229        unsigned int button = BTN_LEFT;
 230        unsigned int trackstick_button = BTN_LEFT;
 231        bool button_mapped = false;
 232        int i;
 233        int button_count = min_t(u8, f30->gpioled_count, TRACKSTICK_RANGE_END);
 234
 235        f30->gpioled_key_map = devm_kcalloc(&fn->dev,
 236                                            button_count,
 237                                            sizeof(f30->gpioled_key_map[0]),
 238                                            GFP_KERNEL);
 239        if (!f30->gpioled_key_map) {
 240                dev_err(&fn->dev, "Failed to allocate gpioled map memory.\n");
 241                return -ENOMEM;
 242        }
 243
 244        for (i = 0; i < button_count; i++) {
 245                if (!rmi_f30_is_valid_button(i, f30->ctrl))
 246                        continue;
 247
 248                if (pdata->f30_data.trackstick_buttons &&
 249                    i >= TRACKSTICK_RANGE_START && i < TRACKSTICK_RANGE_END) {
 250                        f30->gpioled_key_map[i] = trackstick_button++;
 251                } else if (!pdata->f30_data.buttonpad || !button_mapped) {
 252                        f30->gpioled_key_map[i] = button;
 253                        input_set_capability(input, EV_KEY, button++);
 254                        button_mapped = true;
 255                }
 256        }
 257
 258        input->keycode = f30->gpioled_key_map;
 259        input->keycodesize = sizeof(f30->gpioled_key_map[0]);
 260        input->keycodemax = f30->gpioled_count;
 261
 262        /*
 263         * Buttonpad could be also inferred from f30->has_mech_mouse_btns,
 264         * but I am not sure, so use only the pdata info and the number of
 265         * mapped buttons.
 266         */
 267        if (pdata->f30_data.buttonpad || (button - BTN_LEFT == 1))
 268                __set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
 269
 270        return 0;
 271}
 272
 273static int rmi_f30_initialize(struct rmi_function *fn, struct f30_data *f30)
 274{
 275        u8 *ctrl_reg = f30->ctrl_regs;
 276        int control_address = fn->fd.control_base_addr;
 277        u8 buf[RMI_F30_QUERY_SIZE];
 278        int error;
 279
 280        error = rmi_read_block(fn->rmi_dev, fn->fd.query_base_addr,
 281                               buf, RMI_F30_QUERY_SIZE);
 282        if (error) {
 283                dev_err(&fn->dev, "Failed to read query register\n");
 284                return error;
 285        }
 286
 287        f30->has_extended_pattern = buf[0] & RMI_F30_EXTENDED_PATTERNS;
 288        f30->has_mappable_buttons = buf[0] & RMI_F30_HAS_MAPPABLE_BUTTONS;
 289        f30->has_led = buf[0] & RMI_F30_HAS_LED;
 290        f30->has_gpio = buf[0] & RMI_F30_HAS_GPIO;
 291        f30->has_haptic = buf[0] & RMI_F30_HAS_HAPTIC;
 292        f30->has_gpio_driver_control = buf[0] & RMI_F30_HAS_GPIO_DRV_CTL;
 293        f30->has_mech_mouse_btns = buf[0] & RMI_F30_HAS_MECH_MOUSE_BTNS;
 294        f30->gpioled_count = buf[1] & RMI_F30_GPIO_LED_COUNT;
 295
 296        f30->register_count = DIV_ROUND_UP(f30->gpioled_count, 8);
 297
 298        if (f30->has_gpio && f30->has_led)
 299                rmi_f30_set_ctrl_data(&f30->ctrl[0], &control_address,
 300                                      f30->register_count, &ctrl_reg);
 301
 302        rmi_f30_set_ctrl_data(&f30->ctrl[1], &control_address,
 303                              sizeof(u8), &ctrl_reg);
 304
 305        if (f30->has_gpio) {
 306                rmi_f30_set_ctrl_data(&f30->ctrl[2], &control_address,
 307                                      f30->register_count, &ctrl_reg);
 308
 309                rmi_f30_set_ctrl_data(&f30->ctrl[3], &control_address,
 310                                      f30->register_count, &ctrl_reg);
 311        }
 312
 313        if (f30->has_led) {
 314                rmi_f30_set_ctrl_data(&f30->ctrl[4], &control_address,
 315                                      f30->register_count, &ctrl_reg);
 316
 317                rmi_f30_set_ctrl_data(&f30->ctrl[5], &control_address,
 318                                      f30->has_extended_pattern ? 6 : 2,
 319                                      &ctrl_reg);
 320        }
 321
 322        if (f30->has_led || f30->has_gpio_driver_control) {
 323                /* control 6 uses a byte per gpio/led */
 324                rmi_f30_set_ctrl_data(&f30->ctrl[6], &control_address,
 325                                      f30->gpioled_count, &ctrl_reg);
 326        }
 327
 328        if (f30->has_mappable_buttons) {
 329                /* control 7 uses a byte per gpio/led */
 330                rmi_f30_set_ctrl_data(&f30->ctrl[7], &control_address,
 331                                      f30->gpioled_count, &ctrl_reg);
 332        }
 333
 334        if (f30->has_haptic) {
 335                rmi_f30_set_ctrl_data(&f30->ctrl[8], &control_address,
 336                                      f30->register_count, &ctrl_reg);
 337
 338                rmi_f30_set_ctrl_data(&f30->ctrl[9], &control_address,
 339                                      sizeof(u8), &ctrl_reg);
 340        }
 341
 342        if (f30->has_mech_mouse_btns)
 343                rmi_f30_set_ctrl_data(&f30->ctrl[10], &control_address,
 344                                      sizeof(u8), &ctrl_reg);
 345
 346        f30->ctrl_regs_size = ctrl_reg -
 347                                f30->ctrl_regs ?: RMI_F30_CTRL_REGS_MAX_SIZE;
 348
 349        error = rmi_f30_read_control_parameters(fn, f30);
 350        if (error) {
 351                dev_err(&fn->dev,
 352                        "Failed to initialize F30 control params: %d\n",
 353                        error);
 354                return error;
 355        }
 356
 357        if (f30->has_gpio) {
 358                error = rmi_f30_map_gpios(fn, f30);
 359                if (error)
 360                        return error;
 361        }
 362
 363        return 0;
 364}
 365
 366static int rmi_f30_probe(struct rmi_function *fn)
 367{
 368        struct rmi_device *rmi_dev = fn->rmi_dev;
 369        const struct rmi_device_platform_data *pdata =
 370                                        rmi_get_platform_data(rmi_dev);
 371        struct rmi_driver_data *drv_data = dev_get_drvdata(&rmi_dev->dev);
 372        struct f30_data *f30;
 373        int error;
 374
 375        if (pdata->f30_data.disable)
 376                return 0;
 377
 378        if (!drv_data->input) {
 379                dev_info(&fn->dev, "F30: no input device found, ignoring\n");
 380                return -ENXIO;
 381        }
 382
 383        f30 = devm_kzalloc(&fn->dev, sizeof(*f30), GFP_KERNEL);
 384        if (!f30)
 385                return -ENOMEM;
 386
 387        f30->input = drv_data->input;
 388
 389        error = rmi_f30_initialize(fn, f30);
 390        if (error)
 391                return error;
 392
 393        dev_set_drvdata(&fn->dev, f30);
 394        return 0;
 395}
 396
 397struct rmi_function_handler rmi_f30_handler = {
 398        .driver = {
 399                .name = "rmi4_f30",
 400        },
 401        .func = 0x30,
 402        .probe = rmi_f30_probe,
 403        .config = rmi_f30_config,
 404        .attention = rmi_f30_attention,
 405};
 406