1562b42d3SAndrew Duggan /* 2562b42d3SAndrew Duggan * Copyright (c) 2012-2016 Synaptics Incorporated 3562b42d3SAndrew Duggan * 4562b42d3SAndrew Duggan * This program is free software; you can redistribute it and/or modify it 5562b42d3SAndrew Duggan * under the terms of the GNU General Public License version 2 as published by 6562b42d3SAndrew Duggan * the Free Software Foundation. 7562b42d3SAndrew Duggan */ 8562b42d3SAndrew Duggan 9562b42d3SAndrew Duggan #include <linux/kernel.h> 10562b42d3SAndrew Duggan #include <linux/rmi.h> 11562b42d3SAndrew Duggan #include <linux/input.h> 12562b42d3SAndrew Duggan #include <linux/slab.h> 13562b42d3SAndrew Duggan #include "rmi_driver.h" 14562b42d3SAndrew Duggan 15562b42d3SAndrew Duggan #define RMI_F30_QUERY_SIZE 2 16562b42d3SAndrew Duggan 17562b42d3SAndrew Duggan /* Defs for Query 0 */ 18562b42d3SAndrew Duggan #define RMI_F30_EXTENDED_PATTERNS 0x01 19562b42d3SAndrew Duggan #define RMI_F30_HAS_MAPPABLE_BUTTONS (1 << 1) 20562b42d3SAndrew Duggan #define RMI_F30_HAS_LED (1 << 2) 21562b42d3SAndrew Duggan #define RMI_F30_HAS_GPIO (1 << 3) 22562b42d3SAndrew Duggan #define RMI_F30_HAS_HAPTIC (1 << 4) 23562b42d3SAndrew Duggan #define RMI_F30_HAS_GPIO_DRV_CTL (1 << 5) 24562b42d3SAndrew Duggan #define RMI_F30_HAS_MECH_MOUSE_BTNS (1 << 6) 25562b42d3SAndrew Duggan 26562b42d3SAndrew Duggan /* Defs for Query 1 */ 27562b42d3SAndrew Duggan #define RMI_F30_GPIO_LED_COUNT 0x1F 28562b42d3SAndrew Duggan 29562b42d3SAndrew Duggan /* Defs for Control Registers */ 30562b42d3SAndrew Duggan #define RMI_F30_CTRL_1_GPIO_DEBOUNCE 0x01 31562b42d3SAndrew Duggan #define RMI_F30_CTRL_1_HALT (1 << 4) 32562b42d3SAndrew Duggan #define RMI_F30_CTRL_1_HALTED (1 << 5) 33562b42d3SAndrew Duggan #define RMI_F30_CTRL_10_NUM_MECH_MOUSE_BTNS 0x03 34562b42d3SAndrew Duggan 35562b42d3SAndrew Duggan struct rmi_f30_ctrl_data { 36562b42d3SAndrew Duggan int address; 37562b42d3SAndrew Duggan int length; 38562b42d3SAndrew Duggan u8 *regs; 39562b42d3SAndrew Duggan }; 40562b42d3SAndrew Duggan 41562b42d3SAndrew Duggan #define RMI_F30_CTRL_MAX_REGS 32 42562b42d3SAndrew Duggan #define RMI_F30_CTRL_MAX_BYTES ((RMI_F30_CTRL_MAX_REGS + 7) >> 3) 43562b42d3SAndrew Duggan #define RMI_F30_CTRL_MAX_REG_BLOCKS 11 44562b42d3SAndrew Duggan 45562b42d3SAndrew Duggan #define RMI_F30_CTRL_REGS_MAX_SIZE (RMI_F30_CTRL_MAX_BYTES \ 46562b42d3SAndrew Duggan + 1 \ 47562b42d3SAndrew Duggan + RMI_F30_CTRL_MAX_BYTES \ 48562b42d3SAndrew Duggan + RMI_F30_CTRL_MAX_BYTES \ 49562b42d3SAndrew Duggan + RMI_F30_CTRL_MAX_BYTES \ 50562b42d3SAndrew Duggan + 6 \ 51562b42d3SAndrew Duggan + RMI_F30_CTRL_MAX_REGS \ 52562b42d3SAndrew Duggan + RMI_F30_CTRL_MAX_REGS \ 53562b42d3SAndrew Duggan + RMI_F30_CTRL_MAX_BYTES \ 54562b42d3SAndrew Duggan + 1 \ 55562b42d3SAndrew Duggan + 1) 56562b42d3SAndrew Duggan 57562b42d3SAndrew Duggan struct f30_data { 58562b42d3SAndrew Duggan /* Query Data */ 59562b42d3SAndrew Duggan bool has_extended_pattern; 60562b42d3SAndrew Duggan bool has_mappable_buttons; 61562b42d3SAndrew Duggan bool has_led; 62562b42d3SAndrew Duggan bool has_gpio; 63562b42d3SAndrew Duggan bool has_haptic; 64562b42d3SAndrew Duggan bool has_gpio_driver_control; 65562b42d3SAndrew Duggan bool has_mech_mouse_btns; 66562b42d3SAndrew Duggan u8 gpioled_count; 67562b42d3SAndrew Duggan 68562b42d3SAndrew Duggan u8 register_count; 69562b42d3SAndrew Duggan 70562b42d3SAndrew Duggan /* Control Register Data */ 71562b42d3SAndrew Duggan struct rmi_f30_ctrl_data ctrl[RMI_F30_CTRL_MAX_REG_BLOCKS]; 72562b42d3SAndrew Duggan u8 ctrl_regs[RMI_F30_CTRL_REGS_MAX_SIZE]; 73562b42d3SAndrew Duggan u32 ctrl_regs_size; 74562b42d3SAndrew Duggan 75562b42d3SAndrew Duggan u8 data_regs[RMI_F30_CTRL_MAX_BYTES]; 76562b42d3SAndrew Duggan u16 *gpioled_key_map; 77562b42d3SAndrew Duggan 78562b42d3SAndrew Duggan struct input_dev *input; 79562b42d3SAndrew Duggan }; 80562b42d3SAndrew Duggan 81562b42d3SAndrew Duggan static int rmi_f30_read_control_parameters(struct rmi_function *fn, 82562b42d3SAndrew Duggan struct f30_data *f30) 83562b42d3SAndrew Duggan { 84562b42d3SAndrew Duggan struct rmi_device *rmi_dev = fn->rmi_dev; 85562b42d3SAndrew Duggan int error = 0; 86562b42d3SAndrew Duggan 87562b42d3SAndrew Duggan error = rmi_read_block(rmi_dev, fn->fd.control_base_addr, 88562b42d3SAndrew Duggan f30->ctrl_regs, f30->ctrl_regs_size); 89562b42d3SAndrew Duggan if (error) { 90562b42d3SAndrew Duggan dev_err(&rmi_dev->dev, "%s : Could not read control registers at 0x%x error (%d)\n", 91562b42d3SAndrew Duggan __func__, fn->fd.control_base_addr, error); 92562b42d3SAndrew Duggan return error; 93562b42d3SAndrew Duggan } 94562b42d3SAndrew Duggan 95562b42d3SAndrew Duggan return 0; 96562b42d3SAndrew Duggan } 97562b42d3SAndrew Duggan 98562b42d3SAndrew Duggan static int rmi_f30_attention(struct rmi_function *fn, unsigned long *irq_bits) 99562b42d3SAndrew Duggan { 100562b42d3SAndrew Duggan struct f30_data *f30 = dev_get_drvdata(&fn->dev); 101562b42d3SAndrew Duggan struct rmi_device *rmi_dev = fn->rmi_dev; 102ae9979c3SBenjamin Tissoires struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev); 103562b42d3SAndrew Duggan int retval; 104562b42d3SAndrew Duggan int gpiled = 0; 105562b42d3SAndrew Duggan int value = 0; 106562b42d3SAndrew Duggan int i; 107562b42d3SAndrew Duggan int reg_num; 108562b42d3SAndrew Duggan 109562b42d3SAndrew Duggan if (!f30->input) 110562b42d3SAndrew Duggan return 0; 111562b42d3SAndrew Duggan 112562b42d3SAndrew Duggan /* Read the gpi led data. */ 113ae9979c3SBenjamin Tissoires if (drvdata->attn_data.data) { 114ae9979c3SBenjamin Tissoires if (drvdata->attn_data.size < f30->register_count) { 1156d0dbeaeSAndrew Duggan dev_warn(&fn->dev, "F30 interrupted, but data is missing\n"); 1166d0dbeaeSAndrew Duggan return 0; 1176d0dbeaeSAndrew Duggan } 118ae9979c3SBenjamin Tissoires memcpy(f30->data_regs, drvdata->attn_data.data, 119562b42d3SAndrew Duggan f30->register_count); 120ae9979c3SBenjamin Tissoires drvdata->attn_data.data += f30->register_count; 121ae9979c3SBenjamin Tissoires drvdata->attn_data.size -= f30->register_count; 122562b42d3SAndrew Duggan } else { 123562b42d3SAndrew Duggan retval = rmi_read_block(rmi_dev, fn->fd.data_base_addr, 124562b42d3SAndrew Duggan f30->data_regs, f30->register_count); 125562b42d3SAndrew Duggan 126562b42d3SAndrew Duggan if (retval) { 127562b42d3SAndrew Duggan dev_err(&fn->dev, "%s: Failed to read F30 data registers.\n", 128562b42d3SAndrew Duggan __func__); 129562b42d3SAndrew Duggan return retval; 130562b42d3SAndrew Duggan } 131562b42d3SAndrew Duggan } 132562b42d3SAndrew Duggan 133562b42d3SAndrew Duggan for (reg_num = 0; reg_num < f30->register_count; ++reg_num) { 134562b42d3SAndrew Duggan for (i = 0; gpiled < f30->gpioled_count && i < 8; ++i, 135562b42d3SAndrew Duggan ++gpiled) { 136562b42d3SAndrew Duggan if (f30->gpioled_key_map[gpiled] != 0) { 137562b42d3SAndrew Duggan /* buttons have pull up resistors */ 138562b42d3SAndrew Duggan value = (((f30->data_regs[reg_num] >> i) & 0x01) 139562b42d3SAndrew Duggan == 0); 140562b42d3SAndrew Duggan 141562b42d3SAndrew Duggan rmi_dbg(RMI_DEBUG_FN, &fn->dev, 142562b42d3SAndrew Duggan "%s: call input report key (0x%04x) value (0x%02x)", 143562b42d3SAndrew Duggan __func__, 144562b42d3SAndrew Duggan f30->gpioled_key_map[gpiled], value); 145562b42d3SAndrew Duggan input_report_key(f30->input, 146562b42d3SAndrew Duggan f30->gpioled_key_map[gpiled], 147562b42d3SAndrew Duggan value); 148562b42d3SAndrew Duggan } 149562b42d3SAndrew Duggan 150562b42d3SAndrew Duggan } 151562b42d3SAndrew Duggan } 152562b42d3SAndrew Duggan 153562b42d3SAndrew Duggan return 0; 154562b42d3SAndrew Duggan } 155562b42d3SAndrew Duggan 156562b42d3SAndrew Duggan static int rmi_f30_register_device(struct rmi_function *fn) 157562b42d3SAndrew Duggan { 158562b42d3SAndrew Duggan int i; 159562b42d3SAndrew Duggan struct rmi_device *rmi_dev = fn->rmi_dev; 160562b42d3SAndrew Duggan struct rmi_driver_data *drv_data = dev_get_drvdata(&rmi_dev->dev); 161562b42d3SAndrew Duggan struct f30_data *f30 = dev_get_drvdata(&fn->dev); 162562b42d3SAndrew Duggan struct input_dev *input_dev; 163562b42d3SAndrew Duggan int button_count = 0; 164562b42d3SAndrew Duggan 165562b42d3SAndrew Duggan input_dev = drv_data->input; 166562b42d3SAndrew Duggan if (!input_dev) { 167562b42d3SAndrew Duggan dev_info(&fn->dev, "F30: no input device found, ignoring.\n"); 168562b42d3SAndrew Duggan return -EINVAL; 169562b42d3SAndrew Duggan } 170562b42d3SAndrew Duggan 171562b42d3SAndrew Duggan f30->input = input_dev; 172562b42d3SAndrew Duggan 173562b42d3SAndrew Duggan set_bit(EV_KEY, input_dev->evbit); 174562b42d3SAndrew Duggan 175562b42d3SAndrew Duggan input_dev->keycode = f30->gpioled_key_map; 176562b42d3SAndrew Duggan input_dev->keycodesize = sizeof(u16); 177562b42d3SAndrew Duggan input_dev->keycodemax = f30->gpioled_count; 178562b42d3SAndrew Duggan 179562b42d3SAndrew Duggan for (i = 0; i < f30->gpioled_count; i++) { 180562b42d3SAndrew Duggan if (f30->gpioled_key_map[i] != 0) { 181562b42d3SAndrew Duggan input_set_capability(input_dev, EV_KEY, 182562b42d3SAndrew Duggan f30->gpioled_key_map[i]); 183562b42d3SAndrew Duggan button_count++; 184562b42d3SAndrew Duggan } 185562b42d3SAndrew Duggan } 186562b42d3SAndrew Duggan 187562b42d3SAndrew Duggan if (button_count == 1) 188562b42d3SAndrew Duggan __set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit); 189562b42d3SAndrew Duggan return 0; 190562b42d3SAndrew Duggan } 191562b42d3SAndrew Duggan 192562b42d3SAndrew Duggan static int rmi_f30_config(struct rmi_function *fn) 193562b42d3SAndrew Duggan { 194562b42d3SAndrew Duggan struct f30_data *f30 = dev_get_drvdata(&fn->dev); 195562b42d3SAndrew Duggan struct rmi_driver *drv = fn->rmi_dev->driver; 196562b42d3SAndrew Duggan const struct rmi_device_platform_data *pdata = 197562b42d3SAndrew Duggan rmi_get_platform_data(fn->rmi_dev); 198562b42d3SAndrew Duggan int error; 199562b42d3SAndrew Duggan 2000a135b88SBenjamin Tissoires if (pdata->f30_data.disable) { 201562b42d3SAndrew Duggan drv->clear_irq_bits(fn->rmi_dev, fn->irq_mask); 202562b42d3SAndrew Duggan } else { 203562b42d3SAndrew Duggan /* Write Control Register values back to device */ 204562b42d3SAndrew Duggan error = rmi_write_block(fn->rmi_dev, fn->fd.control_base_addr, 205562b42d3SAndrew Duggan f30->ctrl_regs, f30->ctrl_regs_size); 206562b42d3SAndrew Duggan if (error) { 207562b42d3SAndrew Duggan dev_err(&fn->rmi_dev->dev, 208562b42d3SAndrew Duggan "%s : Could not write control registers at 0x%x error (%d)\n", 209562b42d3SAndrew Duggan __func__, fn->fd.control_base_addr, error); 210562b42d3SAndrew Duggan return error; 211562b42d3SAndrew Duggan } 212562b42d3SAndrew Duggan 213562b42d3SAndrew Duggan drv->set_irq_bits(fn->rmi_dev, fn->irq_mask); 214562b42d3SAndrew Duggan } 215562b42d3SAndrew Duggan return 0; 216562b42d3SAndrew Duggan } 217562b42d3SAndrew Duggan 218562b42d3SAndrew Duggan static inline void rmi_f30_set_ctrl_data(struct rmi_f30_ctrl_data *ctrl, 219562b42d3SAndrew Duggan int *ctrl_addr, int len, u8 **reg) 220562b42d3SAndrew Duggan { 221562b42d3SAndrew Duggan ctrl->address = *ctrl_addr; 222562b42d3SAndrew Duggan ctrl->length = len; 223562b42d3SAndrew Duggan ctrl->regs = *reg; 224562b42d3SAndrew Duggan *ctrl_addr += len; 225562b42d3SAndrew Duggan *reg += len; 226562b42d3SAndrew Duggan } 227562b42d3SAndrew Duggan 228562b42d3SAndrew Duggan static inline bool rmi_f30_is_valid_button(int button, 229562b42d3SAndrew Duggan struct rmi_f30_ctrl_data *ctrl) 230562b42d3SAndrew Duggan { 231562b42d3SAndrew Duggan int byte_position = button >> 3; 232562b42d3SAndrew Duggan int bit_position = button & 0x07; 233562b42d3SAndrew Duggan 234562b42d3SAndrew Duggan /* 235562b42d3SAndrew Duggan * ctrl2 -> dir == 0 -> input mode 236562b42d3SAndrew Duggan * ctrl3 -> data == 1 -> actual button 237562b42d3SAndrew Duggan */ 238562b42d3SAndrew Duggan return !(ctrl[2].regs[byte_position] & BIT(bit_position)) && 239562b42d3SAndrew Duggan (ctrl[3].regs[byte_position] & BIT(bit_position)); 240562b42d3SAndrew Duggan } 241562b42d3SAndrew Duggan 242562b42d3SAndrew Duggan static inline int rmi_f30_initialize(struct rmi_function *fn) 243562b42d3SAndrew Duggan { 244562b42d3SAndrew Duggan struct f30_data *f30; 245562b42d3SAndrew Duggan struct rmi_device *rmi_dev = fn->rmi_dev; 246562b42d3SAndrew Duggan const struct rmi_device_platform_data *pdata; 247562b42d3SAndrew Duggan int retval = 0; 248562b42d3SAndrew Duggan int control_address; 249562b42d3SAndrew Duggan int i; 250562b42d3SAndrew Duggan int button; 251562b42d3SAndrew Duggan u8 buf[RMI_F30_QUERY_SIZE]; 252562b42d3SAndrew Duggan u8 *ctrl_reg; 253562b42d3SAndrew Duggan u8 *map_memory; 254562b42d3SAndrew Duggan 255562b42d3SAndrew Duggan f30 = devm_kzalloc(&fn->dev, sizeof(struct f30_data), 256562b42d3SAndrew Duggan GFP_KERNEL); 257562b42d3SAndrew Duggan if (!f30) 258562b42d3SAndrew Duggan return -ENOMEM; 259562b42d3SAndrew Duggan 260562b42d3SAndrew Duggan dev_set_drvdata(&fn->dev, f30); 261562b42d3SAndrew Duggan 262562b42d3SAndrew Duggan retval = rmi_read_block(fn->rmi_dev, fn->fd.query_base_addr, buf, 263562b42d3SAndrew Duggan RMI_F30_QUERY_SIZE); 264562b42d3SAndrew Duggan 265562b42d3SAndrew Duggan if (retval) { 266562b42d3SAndrew Duggan dev_err(&fn->dev, "Failed to read query register.\n"); 267562b42d3SAndrew Duggan return retval; 268562b42d3SAndrew Duggan } 269562b42d3SAndrew Duggan 270562b42d3SAndrew Duggan f30->has_extended_pattern = buf[0] & RMI_F30_EXTENDED_PATTERNS; 271562b42d3SAndrew Duggan f30->has_mappable_buttons = buf[0] & RMI_F30_HAS_MAPPABLE_BUTTONS; 272562b42d3SAndrew Duggan f30->has_led = buf[0] & RMI_F30_HAS_LED; 273562b42d3SAndrew Duggan f30->has_gpio = buf[0] & RMI_F30_HAS_GPIO; 274562b42d3SAndrew Duggan f30->has_haptic = buf[0] & RMI_F30_HAS_HAPTIC; 275562b42d3SAndrew Duggan f30->has_gpio_driver_control = buf[0] & RMI_F30_HAS_GPIO_DRV_CTL; 276562b42d3SAndrew Duggan f30->has_mech_mouse_btns = buf[0] & RMI_F30_HAS_MECH_MOUSE_BTNS; 277562b42d3SAndrew Duggan f30->gpioled_count = buf[1] & RMI_F30_GPIO_LED_COUNT; 278562b42d3SAndrew Duggan 279562b42d3SAndrew Duggan f30->register_count = (f30->gpioled_count + 7) >> 3; 280562b42d3SAndrew Duggan 281562b42d3SAndrew Duggan control_address = fn->fd.control_base_addr; 282562b42d3SAndrew Duggan ctrl_reg = f30->ctrl_regs; 283562b42d3SAndrew Duggan 284562b42d3SAndrew Duggan if (f30->has_gpio && f30->has_led) 285562b42d3SAndrew Duggan rmi_f30_set_ctrl_data(&f30->ctrl[0], &control_address, 286562b42d3SAndrew Duggan f30->register_count, &ctrl_reg); 287562b42d3SAndrew Duggan 288562b42d3SAndrew Duggan rmi_f30_set_ctrl_data(&f30->ctrl[1], &control_address, sizeof(u8), 289562b42d3SAndrew Duggan &ctrl_reg); 290562b42d3SAndrew Duggan 291562b42d3SAndrew Duggan if (f30->has_gpio) { 292562b42d3SAndrew Duggan rmi_f30_set_ctrl_data(&f30->ctrl[2], &control_address, 293562b42d3SAndrew Duggan f30->register_count, &ctrl_reg); 294562b42d3SAndrew Duggan 295562b42d3SAndrew Duggan rmi_f30_set_ctrl_data(&f30->ctrl[3], &control_address, 296562b42d3SAndrew Duggan f30->register_count, &ctrl_reg); 297562b42d3SAndrew Duggan } 298562b42d3SAndrew Duggan 299562b42d3SAndrew Duggan if (f30->has_led) { 300562b42d3SAndrew Duggan int ctrl5_len; 301562b42d3SAndrew Duggan 302562b42d3SAndrew Duggan rmi_f30_set_ctrl_data(&f30->ctrl[4], &control_address, 303562b42d3SAndrew Duggan f30->register_count, &ctrl_reg); 304562b42d3SAndrew Duggan 305562b42d3SAndrew Duggan if (f30->has_extended_pattern) 306562b42d3SAndrew Duggan ctrl5_len = 6; 307562b42d3SAndrew Duggan else 308562b42d3SAndrew Duggan ctrl5_len = 2; 309562b42d3SAndrew Duggan 310562b42d3SAndrew Duggan rmi_f30_set_ctrl_data(&f30->ctrl[5], &control_address, 311562b42d3SAndrew Duggan ctrl5_len, &ctrl_reg); 312562b42d3SAndrew Duggan } 313562b42d3SAndrew Duggan 314562b42d3SAndrew Duggan if (f30->has_led || f30->has_gpio_driver_control) { 315562b42d3SAndrew Duggan /* control 6 uses a byte per gpio/led */ 316562b42d3SAndrew Duggan rmi_f30_set_ctrl_data(&f30->ctrl[6], &control_address, 317562b42d3SAndrew Duggan f30->gpioled_count, &ctrl_reg); 318562b42d3SAndrew Duggan } 319562b42d3SAndrew Duggan 320562b42d3SAndrew Duggan if (f30->has_mappable_buttons) { 321562b42d3SAndrew Duggan /* control 7 uses a byte per gpio/led */ 322562b42d3SAndrew Duggan rmi_f30_set_ctrl_data(&f30->ctrl[7], &control_address, 323562b42d3SAndrew Duggan f30->gpioled_count, &ctrl_reg); 324562b42d3SAndrew Duggan } 325562b42d3SAndrew Duggan 326562b42d3SAndrew Duggan if (f30->has_haptic) { 327562b42d3SAndrew Duggan rmi_f30_set_ctrl_data(&f30->ctrl[8], &control_address, 328562b42d3SAndrew Duggan f30->register_count, &ctrl_reg); 329562b42d3SAndrew Duggan 330562b42d3SAndrew Duggan rmi_f30_set_ctrl_data(&f30->ctrl[9], &control_address, 331562b42d3SAndrew Duggan sizeof(u8), &ctrl_reg); 332562b42d3SAndrew Duggan } 333562b42d3SAndrew Duggan 334562b42d3SAndrew Duggan if (f30->has_mech_mouse_btns) 335562b42d3SAndrew Duggan rmi_f30_set_ctrl_data(&f30->ctrl[10], &control_address, 336562b42d3SAndrew Duggan sizeof(u8), &ctrl_reg); 337562b42d3SAndrew Duggan 338562b42d3SAndrew Duggan f30->ctrl_regs_size = ctrl_reg - f30->ctrl_regs 339562b42d3SAndrew Duggan ?: RMI_F30_CTRL_REGS_MAX_SIZE; 340562b42d3SAndrew Duggan 341562b42d3SAndrew Duggan retval = rmi_f30_read_control_parameters(fn, f30); 342562b42d3SAndrew Duggan if (retval < 0) { 343562b42d3SAndrew Duggan dev_err(&fn->dev, 344562b42d3SAndrew Duggan "Failed to initialize F19 control params.\n"); 345562b42d3SAndrew Duggan return retval; 346562b42d3SAndrew Duggan } 347562b42d3SAndrew Duggan 348562b42d3SAndrew Duggan map_memory = devm_kzalloc(&fn->dev, 349562b42d3SAndrew Duggan (f30->gpioled_count * (sizeof(u16))), 350562b42d3SAndrew Duggan GFP_KERNEL); 351562b42d3SAndrew Duggan if (!map_memory) { 352562b42d3SAndrew Duggan dev_err(&fn->dev, "Failed to allocate gpioled map memory.\n"); 353562b42d3SAndrew Duggan return -ENOMEM; 354562b42d3SAndrew Duggan } 355562b42d3SAndrew Duggan 356562b42d3SAndrew Duggan f30->gpioled_key_map = (u16 *)map_memory; 357562b42d3SAndrew Duggan 358562b42d3SAndrew Duggan pdata = rmi_get_platform_data(rmi_dev); 3590a135b88SBenjamin Tissoires if (f30->has_gpio) { 360562b42d3SAndrew Duggan button = BTN_LEFT; 361562b42d3SAndrew Duggan for (i = 0; i < f30->gpioled_count; i++) { 362562b42d3SAndrew Duggan if (rmi_f30_is_valid_button(i, f30->ctrl)) { 363562b42d3SAndrew Duggan f30->gpioled_key_map[i] = button++; 364562b42d3SAndrew Duggan 365562b42d3SAndrew Duggan /* 366562b42d3SAndrew Duggan * buttonpad might be given by 367562b42d3SAndrew Duggan * f30->has_mech_mouse_btns, but I am 368562b42d3SAndrew Duggan * not sure, so use only the pdata info 369562b42d3SAndrew Duggan */ 3700a135b88SBenjamin Tissoires if (pdata->f30_data.buttonpad) 371562b42d3SAndrew Duggan break; 372562b42d3SAndrew Duggan } 373562b42d3SAndrew Duggan } 374562b42d3SAndrew Duggan } 375562b42d3SAndrew Duggan 376562b42d3SAndrew Duggan return 0; 377562b42d3SAndrew Duggan } 378562b42d3SAndrew Duggan 379562b42d3SAndrew Duggan static int rmi_f30_probe(struct rmi_function *fn) 380562b42d3SAndrew Duggan { 381562b42d3SAndrew Duggan int rc; 382562b42d3SAndrew Duggan const struct rmi_device_platform_data *pdata = 383562b42d3SAndrew Duggan rmi_get_platform_data(fn->rmi_dev); 384562b42d3SAndrew Duggan 3850a135b88SBenjamin Tissoires if (pdata->f30_data.disable) 386562b42d3SAndrew Duggan return 0; 387562b42d3SAndrew Duggan 388562b42d3SAndrew Duggan rc = rmi_f30_initialize(fn); 389562b42d3SAndrew Duggan if (rc < 0) 390562b42d3SAndrew Duggan goto error_exit; 391562b42d3SAndrew Duggan 392562b42d3SAndrew Duggan rc = rmi_f30_register_device(fn); 393562b42d3SAndrew Duggan if (rc < 0) 394562b42d3SAndrew Duggan goto error_exit; 395562b42d3SAndrew Duggan 396562b42d3SAndrew Duggan return 0; 397562b42d3SAndrew Duggan 398562b42d3SAndrew Duggan error_exit: 399562b42d3SAndrew Duggan return rc; 400562b42d3SAndrew Duggan 401562b42d3SAndrew Duggan } 402562b42d3SAndrew Duggan 403562b42d3SAndrew Duggan struct rmi_function_handler rmi_f30_handler = { 404562b42d3SAndrew Duggan .driver = { 405562b42d3SAndrew Duggan .name = "rmi4_f30", 406562b42d3SAndrew Duggan }, 407562b42d3SAndrew Duggan .func = 0x30, 408562b42d3SAndrew Duggan .probe = rmi_f30_probe, 409562b42d3SAndrew Duggan .config = rmi_f30_config, 410562b42d3SAndrew Duggan .attention = rmi_f30_attention, 411562b42d3SAndrew Duggan }; 412