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