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        int button_count = min_t(u8, f30->gpioled_count, TRACKSTICK_RANGE_END);
 236
 237        f30->gpioled_key_map = devm_kcalloc(&fn->dev,
 238                                            button_count,
 239                                            sizeof(f30->gpioled_key_map[0]),
 240                                            GFP_KERNEL);
 241        if (!f30->gpioled_key_map) {
 242                dev_err(&fn->dev, "Failed to allocate gpioled map memory.\n");
 243                return -ENOMEM;
 244        }
 245
 246        for (i = 0; i < button_count; i++) {
 247                if (!rmi_f30_is_valid_button(i, f30->ctrl))
 248                        continue;
 249
 250                if (pdata->f30_data.trackstick_buttons &&
 251                    i >= TRACKSTICK_RANGE_START && i < TRACKSTICK_RANGE_END) {
 252                        f30->gpioled_key_map[i] = trackstick_button++;
 253                } else if (!pdata->f30_data.buttonpad || !button_mapped) {
 254                        f30->gpioled_key_map[i] = button;
 255                        input_set_capability(input, EV_KEY, button++);
 256                        button_mapped = true;
 257                }
 258        }
 259
 260        input->keycode = f30->gpioled_key_map;
 261        input->keycodesize = sizeof(f30->gpioled_key_map[0]);
 262        input->keycodemax = f30->gpioled_count;
 263
 264        /*
 265         * Buttonpad could be also inferred from f30->has_mech_mouse_btns,
 266         * but I am not sure, so use only the pdata info and the number of
 267         * mapped buttons.
 268         */
 269        if (pdata->f30_data.buttonpad || (button - BTN_LEFT == 1))
 270                __set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
 271
 272        return 0;
 273}
 274
 275static int rmi_f30_initialize(struct rmi_function *fn, struct f30_data *f30)
 276{
 277        u8 *ctrl_reg = f30->ctrl_regs;
 278        int control_address = fn->fd.control_base_addr;
 279        u8 buf[RMI_F30_QUERY_SIZE];
 280        int error;
 281
 282        error = rmi_read_block(fn->rmi_dev, fn->fd.query_base_addr,
 283                               buf, RMI_F30_QUERY_SIZE);
 284        if (error) {
 285                dev_err(&fn->dev, "Failed to read query register\n");
 286                return error;
 287        }
 288
 289        f30->has_extended_pattern = buf[0] & RMI_F30_EXTENDED_PATTERNS;
 290        f30->has_mappable_buttons = buf[0] & RMI_F30_HAS_MAPPABLE_BUTTONS;
 291        f30->has_led = buf[0] & RMI_F30_HAS_LED;
 292        f30->has_gpio = buf[0] & RMI_F30_HAS_GPIO;
 293        f30->has_haptic = buf[0] & RMI_F30_HAS_HAPTIC;
 294        f30->has_gpio_driver_control = buf[0] & RMI_F30_HAS_GPIO_DRV_CTL;
 295        f30->has_mech_mouse_btns = buf[0] & RMI_F30_HAS_MECH_MOUSE_BTNS;
 296        f30->gpioled_count = buf[1] & RMI_F30_GPIO_LED_COUNT;
 297
 298        f30->register_count = DIV_ROUND_UP(f30->gpioled_count, 8);
 299
 300        if (f30->has_gpio && f30->has_led)
 301                rmi_f30_set_ctrl_data(&f30->ctrl[0], &control_address,
 302                                      f30->register_count, &ctrl_reg);
 303
 304        rmi_f30_set_ctrl_data(&f30->ctrl[1], &control_address,
 305                              sizeof(u8), &ctrl_reg);
 306
 307        if (f30->has_gpio) {
 308                rmi_f30_set_ctrl_data(&f30->ctrl[2], &control_address,
 309                                      f30->register_count, &ctrl_reg);
 310
 311                rmi_f30_set_ctrl_data(&f30->ctrl[3], &control_address,
 312                                      f30->register_count, &ctrl_reg);
 313        }
 314
 315        if (f30->has_led) {
 316                rmi_f30_set_ctrl_data(&f30->ctrl[4], &control_address,
 317                                      f30->register_count, &ctrl_reg);
 318
 319                rmi_f30_set_ctrl_data(&f30->ctrl[5], &control_address,
 320                                      f30->has_extended_pattern ? 6 : 2,
 321                                      &ctrl_reg);
 322        }
 323
 324        if (f30->has_led || f30->has_gpio_driver_control) {
 325                /* control 6 uses a byte per gpio/led */
 326                rmi_f30_set_ctrl_data(&f30->ctrl[6], &control_address,
 327                                      f30->gpioled_count, &ctrl_reg);
 328        }
 329
 330        if (f30->has_mappable_buttons) {
 331                /* control 7 uses a byte per gpio/led */
 332                rmi_f30_set_ctrl_data(&f30->ctrl[7], &control_address,
 333                                      f30->gpioled_count, &ctrl_reg);
 334        }
 335
 336        if (f30->has_haptic) {
 337                rmi_f30_set_ctrl_data(&f30->ctrl[8], &control_address,
 338                                      f30->register_count, &ctrl_reg);
 339
 340                rmi_f30_set_ctrl_data(&f30->ctrl[9], &control_address,
 341                                      sizeof(u8), &ctrl_reg);
 342        }
 343
 344        if (f30->has_mech_mouse_btns)
 345                rmi_f30_set_ctrl_data(&f30->ctrl[10], &control_address,
 346                                      sizeof(u8), &ctrl_reg);
 347
 348        f30->ctrl_regs_size = ctrl_reg -
 349                                f30->ctrl_regs ?: RMI_F30_CTRL_REGS_MAX_SIZE;
 350
 351        error = rmi_f30_read_control_parameters(fn, f30);
 352        if (error) {
 353                dev_err(&fn->dev,
 354                        "Failed to initialize F30 control params: %d\n",
 355                        error);
 356                return error;
 357        }
 358
 359        if (f30->has_gpio) {
 360                error = rmi_f30_map_gpios(fn, f30);
 361                if (error)
 362                        return error;
 363        }
 364
 365        return 0;
 366}
 367
 368static int rmi_f30_probe(struct rmi_function *fn)
 369{
 370        struct rmi_device *rmi_dev = fn->rmi_dev;
 371        const struct rmi_device_platform_data *pdata =
 372                                        rmi_get_platform_data(rmi_dev);
 373        struct rmi_driver_data *drv_data = dev_get_drvdata(&rmi_dev->dev);
 374        struct f30_data *f30;
 375        int error;
 376
 377        if (pdata->f30_data.disable)
 378                return 0;
 379
 380        if (!drv_data->input) {
 381                dev_info(&fn->dev, "F30: no input device found, ignoring\n");
 382                return -ENXIO;
 383        }
 384
 385        f30 = devm_kzalloc(&fn->dev, sizeof(*f30), GFP_KERNEL);
 386        if (!f30)
 387                return -ENOMEM;
 388
 389        f30->input = drv_data->input;
 390
 391        error = rmi_f30_initialize(fn, f30);
 392        if (error)
 393                return error;
 394
 395        dev_set_drvdata(&fn->dev, f30);
 396        return 0;
 397}
 398
 399struct rmi_function_handler rmi_f30_handler = {
 400        .driver = {
 401                .name = "rmi4_f30",
 402        },
 403        .func = 0x30,
 404        .probe = rmi_f30_probe,
 405        .config = rmi_f30_config,
 406        .attention = rmi_f30_attention,
 407};
 408