int gpio_event_matrix_func(struct gpio_event_input_devs *input_devs, struct gpio_event_info *info, void **data, int func) { int i; int err; int key_count; struct gpio_kp *kp; struct gpio_event_matrix_info *mi; mi = container_of(info, struct gpio_event_matrix_info, info); if (func == GPIO_EVENT_FUNC_SUSPEND || func == GPIO_EVENT_FUNC_RESUME) { /* TODO: disable scanning */ return 0; } if (func == GPIO_EVENT_FUNC_INIT) { if (mi->keymap == NULL || mi->input_gpios == NULL || mi->output_gpios == NULL) { err = -ENODEV; pr_err("gpiomatrix: Incomplete pdata\n"); goto err_invalid_platform_data; } key_count = mi->ninputs * mi->noutputs; *data = kp = kzalloc(sizeof(*kp) + sizeof(kp->keys_pressed[0]) * BITS_TO_LONGS(key_count), GFP_KERNEL); if (kp == NULL) { err = -ENOMEM; pr_err("gpiomatrix: Failed to allocate private data\n"); goto err_kp_alloc_failed; } kp->input_devs = input_devs; kp->keypad_info = mi; for (i = 0; i < key_count; i++) { unsigned short keyentry = mi->keymap[i]; unsigned short keycode = keyentry & MATRIX_KEY_MASK; unsigned short dev = keyentry >> MATRIX_CODE_BITS; if (dev >= input_devs->count) { pr_err("gpiomatrix: bad device index %d >= " "%d for key code %d\n", dev, input_devs->count, keycode); err = -EINVAL; goto err_bad_keymap; } if (keycode && keycode <= KEY_MAX) input_set_capability(input_devs->dev[dev], EV_KEY, keycode); } set_bit(KEY_BACK & KEY_MAX, input_devs->dev[0]->keybit); set_bit(KEY_HOME & KEY_MAX, input_devs->dev[0]->keybit); for (i = 0; i < mi->noutputs; i++) { if (gpio_cansleep(mi->output_gpios[i])) { pr_err("gpiomatrix: unsupported output gpio %d," " can sleep\n", mi->output_gpios[i]); err = -EINVAL; goto err_request_output_gpio_failed; } err = gpio_request(mi->output_gpios[i], "gpio_kp_out"); if (err) { pr_err("gpiomatrix: gpio_request failed for " "output %d\n", mi->output_gpios[i]); goto err_request_output_gpio_failed; } if (mi->flags & GPIOKPF_DRIVE_INACTIVE) err = gpio_direction_output(mi->output_gpios[i], !(mi->flags & GPIOKPF_ACTIVE_HIGH)); else { unsigned gpio_config = GPIO_CFG(mi->output_gpios[i], 0, GPIO_INPUT, GPIO_PULL_UP, GPIO_2MA); gpio_tlmm_config(gpio_config, GPIO_ENABLE); err = gpio_direction_input(mi->output_gpios[i]); } if (err) { pr_err("gpiomatrix: gpio_configure failed for " "output %d\n", mi->output_gpios[i]); goto err_output_gpio_configure_failed; } } for (i = 0; i < mi->ninputs; i++) { err = gpio_request(mi->input_gpios[i], "gpio_kp_in"); if (err) { pr_err("gpiomatrix: gpio_request failed for " "input %d\n", mi->input_gpios[i]); goto err_request_input_gpio_failed; } err = gpio_direction_input(mi->input_gpios[i]); if (err) { pr_err("gpiomatrix: gpio_direction_input failed" " for input %d\n", mi->input_gpios[i]); goto err_gpio_direction_input_failed; } } kp->current_output = mi->noutputs; kp->key_state_changed = 1; hrtimer_init(&kp->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); #ifdef CONFIG_HUAWEI_BACK_KEY_MULTI kp->back_pressed = FALSE; #endif kp->timer.function = gpio_keypad_timer_func; hrtimer_init(&kp->back_key_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); kp->back_key_timer.function = back_key_timer_func; wake_lock_init(&kp->wake_lock, WAKE_LOCK_SUSPEND, "gpio_kp"); err = gpio_keypad_request_irqs(kp); kp->use_irq = err == 0; pr_info("GPIO Matrix Keypad Driver: Start keypad matrix for " "%s%s in %s mode\n", input_devs->dev[0]->name, (input_devs->count > 1) ? "..." : "", kp->use_irq ? "interrupt" : "polling"); if (kp->use_irq) wake_lock(&kp->wake_lock); hrtimer_start(&kp->timer, ktime_set(0, 0), HRTIMER_MODE_REL); return 0; } err = 0; kp = *data; if (kp->use_irq) for (i = mi->noutputs - 1; i >= 0; i--) free_irq(gpio_to_irq(mi->input_gpios[i]), kp); hrtimer_cancel(&kp->timer); wake_lock_destroy(&kp->wake_lock); for (i = mi->noutputs - 1; i >= 0; i--) { err_gpio_direction_input_failed: gpio_free(mi->input_gpios[i]); err_request_input_gpio_failed: ; } for (i = mi->noutputs - 1; i >= 0; i--) { err_output_gpio_configure_failed: gpio_free(mi->output_gpios[i]); err_request_output_gpio_failed: ; } err_bad_keymap: kfree(kp); err_kp_alloc_failed: err_invalid_platform_data: return err; }
int gpio_event_matrix_func(struct input_dev *input_dev, struct gpio_event_info *info, void **data, int func) { int i; int err; int key_count; struct gpio_kp *kp; struct gpio_event_matrix_info *mi; mi = container_of(info, struct gpio_event_matrix_info, info); if (func == GPIO_EVENT_FUNC_SUSPEND || func == GPIO_EVENT_FUNC_RESUME) { /* TODO: disable scanning */ return 0; } if (func == GPIO_EVENT_FUNC_INIT) { if (mi->keymap == NULL || mi->input_gpios == NULL || mi->output_gpios == NULL) { err = -ENODEV; pr_err("gpiomatrix: Incomplete pdata\n"); goto err_invalid_platform_data; } key_count = mi->ninputs * mi->noutputs; *data = kp = kzalloc(sizeof(*kp) + sizeof(kp->keys_pressed[0]) * BITS_TO_LONGS(key_count), GFP_KERNEL); if (kp == NULL) { err = -ENOMEM; pr_err("gpiomatrix: Failed to allocate private data\n"); goto err_kp_alloc_failed; } kp->input_dev = input_dev; kp->keypad_info = mi; set_bit(EV_KEY, input_dev->evbit); for (i = 0; i < key_count; i++) { if (mi->keymap[i]) set_bit(mi->keymap[i] & KEY_MAX, input_dev->keybit); } for (i = 0; i < mi->noutputs; i++) { if (gpio_cansleep(mi->output_gpios[i])) { pr_err("gpiomatrix: unsupported output gpio %d," " can sleep\n", mi->output_gpios[i]); err = -EINVAL; goto err_request_output_gpio_failed; } err = gpio_request(mi->output_gpios[i], "gpio_kp_out"); if (err) { pr_err("gpiomatrix: gpio_request failed for " "output %d\n", mi->output_gpios[i]); goto err_request_output_gpio_failed; } if (mi->flags & GPIOKPF_DRIVE_INACTIVE) err = gpio_direction_output(mi->output_gpios[i], !(mi->flags & GPIOKPF_ACTIVE_HIGH)); else err = gpio_direction_input(mi->output_gpios[i]); if (err) { pr_err("gpiomatrix: gpio_configure failed for " "output %d\n", mi->output_gpios[i]); goto err_output_gpio_configure_failed; } } for (i = 0; i < mi->ninputs; i++) { err = gpio_request(mi->input_gpios[i], "gpio_kp_in"); if (err) { pr_err("gpiomatrix: gpio_request failed for " "input %d\n", mi->input_gpios[i]); goto err_request_input_gpio_failed; } err = gpio_direction_input(mi->input_gpios[i]); if (err) { pr_err("gpiomatrix: gpio_direction_input failed" " for input %d\n", mi->input_gpios[i]); goto err_gpio_direction_input_failed; } } kp->current_output = mi->noutputs; kp->key_state_changed = 1; hrtimer_init(&kp->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); kp->timer.function = gpio_keypad_timer_func; wake_lock_init(&kp->wake_lock, WAKE_LOCK_SUSPEND, "gpio_kp"); err = gpio_keypad_request_irqs(kp); kp->use_irq = err == 0; pr_info("GPIO Matrix Keypad Driver: Start keypad matrix for %s " "in %s mode\n", input_dev->name, kp->use_irq ? "interrupt" : "polling"); if (kp->use_irq) wake_lock(&kp->wake_lock); hrtimer_start(&kp->timer, ktime_set(0, 0), HRTIMER_MODE_REL); return 0; } err = 0; kp = *data; if (kp->use_irq) for (i = mi->noutputs - 1; i >= 0; i--) free_irq(gpio_to_irq(mi->input_gpios[i]), kp); hrtimer_cancel(&kp->timer); wake_lock_destroy(&kp->wake_lock); for (i = mi->noutputs - 1; i >= 0; i--) { err_gpio_direction_input_failed: gpio_free(mi->input_gpios[i]); err_request_input_gpio_failed: ; } for (i = mi->noutputs - 1; i >= 0; i--) { err_output_gpio_configure_failed: gpio_free(mi->output_gpios[i]); err_request_output_gpio_failed: ; } kfree(kp); err_kp_alloc_failed: err_invalid_platform_data: return err; }
int gpio_event_matrix_func(struct gpio_event_input_devs *input_devs, struct gpio_event_info *info, void **data, int func) { int i; int err; int key_count; #ifdef CONFIG_KEYBOARD_WAKEUP int wakeup_keys_status; int irq; static int irq_status = 1; #endif struct gpio_kp *kp; struct gpio_event_matrix_info *mi; // pr_info("[KEY TEST] %s, %d \n", __func__, __LINE__); mi = container_of(info, struct gpio_event_matrix_info, info); if (func == GPIO_EVENT_FUNC_SUSPEND || func == GPIO_EVENT_FUNC_RESUME) { /* TODO: disable scanning */ #ifdef CONFIG_KEYBOARD_WAKEUP wakeup_keys_status = gpio_event_get_wakeup_keys_status() & 0x01; if (irq_status != wakeup_keys_status) irq_status = wakeup_keys_status; else return 0; for (i = 0; i < mi->ninputs; i++) { irq = gpio_to_irq(mi->input_gpios[i]); if (irq_status == 1) err = enable_irq_wake(irq); else err = disable_irq_wake(irq); } /* HOME Key is wakeup source */ for (i = 0; i < mi->nwakeups; i++) { irq = gpio_to_irq(mi->wakeup_gpios[i]); err = enable_irq_wake(irq); } #endif return 0; } if (func == GPIO_EVENT_FUNC_INIT) { if (mi->keymap == NULL || mi->input_gpios == NULL || mi->output_gpios == NULL) { err = -ENODEV; pr_err("gpiomatrix: Incomplete pdata\n"); goto err_invalid_platform_data; } key_count = mi->ninputs * mi->noutputs; pgpio_key = *data = kp = kzalloc(sizeof(*kp) + sizeof(kp->keys_pressed[0]) * BITS_TO_LONGS(key_count), GFP_KERNEL); if (kp == NULL) { err = -ENOMEM; pr_err("gpiomatrix: Failed to allocate private data\n"); goto err_kp_alloc_failed; } kp->input_devs = input_devs; kp->keypad_info = mi; for (i = 0; i < key_count; i++) { unsigned short keyentry = mi->keymap[i]; unsigned short keycode = keyentry & MATRIX_KEY_MASK; unsigned short dev = keyentry >> MATRIX_CODE_BITS; if (dev >= input_devs->count) { pr_err("gpiomatrix: bad device index %d >= " "%d for key code %d\n", dev, input_devs->count, keycode); err = -EINVAL; goto err_bad_keymap; } if (keycode && keycode <= KEY_MAX) input_set_capability(input_devs->dev[dev], EV_KEY, keycode); } for (i = 0; i < mi->noutputs; i++) { err = gpio_request(mi->output_gpios[i], "gpio_kp_out"); if (err) { pr_err("gpiomatrix: gpio_request failed for " "output %d\n", mi->output_gpios[i]); goto err_request_output_gpio_failed; } if (gpio_cansleep(mi->output_gpios[i])) { pr_err("gpiomatrix: unsupported output gpio %d," " can sleep\n", mi->output_gpios[i]); err = -EINVAL; goto err_output_gpio_configure_failed; } if (mi->flags & GPIOKPF_DRIVE_INACTIVE) err = gpio_direction_output(mi->output_gpios[i], !(mi->flags & GPIOKPF_ACTIVE_HIGH)); else err = gpio_direction_input(mi->output_gpios[i]); if (err) { pr_err("gpiomatrix: gpio_configure failed for " "output %d\n", mi->output_gpios[i]); goto err_output_gpio_configure_failed; } } for (i = 0; i < mi->ninputs; i++) { err = gpio_request(mi->input_gpios[i], "gpio_kp_in"); if (err) { pr_err("gpiomatrix: gpio_request failed for " "input %d\n", mi->input_gpios[i]); goto err_request_input_gpio_failed; } err = gpio_direction_input(mi->input_gpios[i]); if (err) { pr_err("gpiomatrix: gpio_direction_input failed" " for input %d\n", mi->input_gpios[i]); goto err_gpio_direction_input_failed; } } kp->current_output = mi->noutputs; kp->key_state_changed = 1; hrtimer_init(&kp->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); kp->timer.function = gpio_keypad_timer_func; wake_lock_init(&kp->wake_lock, WAKE_LOCK_SUSPEND, "gpio_kp"); err = gpio_keypad_request_irqs(kp); kp->use_irq = err == 0; #ifdef CONFIG_KEYBOARD_WAKEUP kpd_dev = device_create(sec_class, NULL, 0, NULL, "sec_key"); if (!kpd_dev) printk(KERN_WARNING "Failed to create device(sec_key)!\n"); if (device_create_file(kpd_dev, &dev_attr_sec_key_pressed) < 0) printk(KERN_WARNING "Failed to create file(%s)!\n" , dev_attr_sec_key_pressed.attr.name); #endif pr_info("GPIO Matrix Keypad Driver: Start keypad matrix for " "%s%s in %s mode\n", input_devs->dev[0]->name, (input_devs->count > 1) ? "..." : "", kp->use_irq ? "interrupt" : "polling"); if (kp->use_irq) wake_lock(&kp->wake_lock); hrtimer_start(&kp->timer, ktime_set(0, 0), HRTIMER_MODE_REL); return 0; } err = 0; kp = *data; if (kp->use_irq) for (i = mi->noutputs - 1; i >= 0; i--) free_irq(gpio_to_irq(mi->input_gpios[i]), kp); hrtimer_cancel(&kp->timer); wake_lock_destroy(&kp->wake_lock); for (i = mi->noutputs - 1; i >= 0; i--) { err_gpio_direction_input_failed: gpio_free(mi->input_gpios[i]); err_request_input_gpio_failed: ; } for (i = mi->noutputs - 1; i >= 0; i--) { err_output_gpio_configure_failed: gpio_free(mi->output_gpios[i]); err_request_output_gpio_failed: ; } err_bad_keymap: kfree(kp); err_kp_alloc_failed: err_invalid_platform_data: return err; }
int gpio_event_matrix_func(struct gpio_event_input_devs *input_devs, struct gpio_event_info *info, void **data, int func) { int i; int err; int key_count; struct gpio_kp *kp; struct gpio_event_matrix_info *mi; mi = container_of(info, struct gpio_event_matrix_info, info); if (func == GPIO_EVENT_FUNC_SUSPEND || func == GPIO_EVENT_FUNC_RESUME) { /* TODO: disable scanning */ return 0; } if (func == GPIO_EVENT_FUNC_INIT) { if (mi->keymap == NULL || mi->input_gpios == NULL || mi->output_gpios == NULL) { err = -ENODEV; pr_err("gpiomatrix: Incomplete pdata\n"); goto err_invalid_platform_data; } printk("[%s:%d] hw rev = %d\n", __func__, __LINE__, board_hw_revision); #if defined(CONFIG_MACH_EUROPA) if(board_hw_revision >= 3) { mi->keymap[(0)*mi->ninputs + (1)] = KEY_RESERVED; mi->keymap[(3)*mi->ninputs + (1)] = KEY_VOLUMEDOWN; mi->keymap[(3)*mi->ninputs + (4)] = KEY_VOLUMEUP; if(board_hw_revision >= 4) { mi->input_gpios[4] = 76; } } #endif #if defined(CONFIG_MACH_CALLISTO) // hsil input_set_capability(input_devs->dev[0], EV_SW, SW_LID); #endif key_count = mi->ninputs * mi->noutputs; *data = kp = kzalloc(sizeof(*kp) + sizeof(kp->keys_pressed[0]) * BITS_TO_LONGS(key_count), GFP_KERNEL); if (kp == NULL) { err = -ENOMEM; pr_err("gpiomatrix: Failed to allocate private data\n"); goto err_kp_alloc_failed; } kp->input_devs = input_devs; kp->keypad_info = mi; for (i = 0; i < key_count; i++) { unsigned short keyentry = mi->keymap[i]; unsigned short keycode = keyentry & MATRIX_KEY_MASK; unsigned short dev = keyentry >> MATRIX_CODE_BITS; if (dev >= input_devs->count) { pr_err("gpiomatrix: bad device index %d >= " "%d for key code %d\n", dev, input_devs->count, keycode); err = -EINVAL; goto err_bad_keymap; } if (keycode && keycode <= KEY_MAX) input_set_capability(input_devs->dev[dev], EV_KEY, keycode); } input_set_capability(input_devs->dev[0],EV_KEY, KEY_END); // for COOPER #if defined(CONFIG_MACH_COOPER) || defined(CONFIG_MACH_BENI) || defined(CONFIG_MACH_TASS) || defined(CONFIG_MACH_LUCAS) #if defined(CONFIG_KERNEL_SEC_MMICHECK) for(i = 0 ; i < ARRAY_SIZE(mmi_keycode) ; i++) input_set_capability(input_devs->dev[0],EV_KEY, mmi_keycode[i]); // for COOPER #endif #endif for (i = 0; i < mi->noutputs; i++) { if (gpio_cansleep(mi->output_gpios[i])) { pr_err("gpiomatrix: unsupported output gpio %d," " can sleep\n", mi->output_gpios[i]); err = -EINVAL; goto err_request_output_gpio_failed; } err = gpio_request(mi->output_gpios[i], "gpio_kp_out"); if (err) { pr_err("gpiomatrix: gpio_request failed for " "output %d\n", mi->output_gpios[i]); goto err_request_output_gpio_failed; } if (mi->flags & GPIOKPF_DRIVE_INACTIVE) err = gpio_direction_output(mi->output_gpios[i], !(mi->flags & GPIOKPF_ACTIVE_HIGH)); else err = gpio_direction_input(mi->output_gpios[i]); if (err) { pr_err("gpiomatrix: gpio_configure failed for " "output %d\n", mi->output_gpios[i]); goto err_output_gpio_configure_failed; } } for (i = 0; i < mi->ninputs; i++) { err = gpio_request(mi->input_gpios[i], "gpio_kp_in"); if (err) { pr_err("gpiomatrix: gpio_request failed for " "input %d\n", mi->input_gpios[i]); goto err_request_input_gpio_failed; } err = gpio_direction_input(mi->input_gpios[i]); if (err) { pr_err("gpiomatrix: gpio_direction_input failed" " for input %d\n", mi->input_gpios[i]); goto err_gpio_direction_input_failed; } } // for COOPER err = gpio_request(GPIO_POWERKEY, "gpio_powerkey"); if (err) { pr_err("gpiomatrix: gpio_request failed for " "input GPIO_POWERKEY %d\n", GPIO_POWERKEY); goto err_request_input_gpio_failed; } err = gpio_direction_input(GPIO_POWERKEY); if (err) { pr_err("gpiomatrix: gpio_direction_input failed" " for input GPIO_POWERKEY %d\n", GPIO_POWERKEY); goto err_gpio_direction_input_failed; } kp->current_output = mi->noutputs; kp->key_state_changed = 1; hrtimer_init(&kp->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); kp->timer.function = gpio_keypad_timer_func; wake_lock_init(&kp->wake_lock, WAKE_LOCK_SUSPEND, "gpio_kp"); err = gpio_keypad_request_irqs(kp); kp->use_irq = err == 0; pr_info("GPIO Matrix Keypad Driver: Start keypad matrix for " "%s%s in %s mode\n", input_devs->dev[0]->name, (input_devs->count > 1) ? "..." : "", kp->use_irq ? "interrupt" : "polling"); if (kp->use_irq) wake_lock(&kp->wake_lock); hrtimer_start(&kp->timer, ktime_set(0, 0), HRTIMER_MODE_REL); return 0; } err = 0; kp = *data; if (kp->use_irq) for (i = mi->noutputs - 1; i >= 0; i--) free_irq(gpio_to_irq(mi->input_gpios[i]), kp); hrtimer_cancel(&kp->timer); wake_lock_destroy(&kp->wake_lock); for (i = mi->noutputs - 1; i >= 0; i--) { err_gpio_direction_input_failed: gpio_free(mi->input_gpios[i]); err_request_input_gpio_failed: ; } for (i = mi->noutputs - 1; i >= 0; i--) { err_output_gpio_configure_failed: gpio_free(mi->output_gpios[i]); err_request_output_gpio_failed: ; } err_bad_keymap: kfree(kp); err_kp_alloc_failed: err_invalid_platform_data: return err; }
int gpio_event_matrix_func(struct gpio_event_input_devs *input_devs, struct gpio_event_info *info, void **data, int func) { int i; int err; int key_count; struct gpio_kp *kp; struct gpio_event_matrix_info *mi; #if defined(CONFIG_MACH_RANT3) || defined(CONFIG_MACH_REALITY2) || defined(CONFIG_MACH_VINO) || defined(CONFIG_MACH_ROOKIE) || defined(CONFIG_MACH_ESCAPE) || defined(CONFIG_MACH_GIO) || defined(CONFIG_MACH_GIOS) /* Implementation for sysfs entries , creating Keypad-backlight class */ bl_class = class_create(THIS_MODULE, "keypad-backlight"); if ( bl_class) { printk(KERN_WARNING "Unable to create Keypad Backlight class \n"); } /* Creating the device backlight under keypad-backlight class */ kpd_dev = device_create( bl_class, NULL, 0, NULL, "backlight"); if (!kpd_dev){ class_destroy(bl_class); printk("Failed to create device(keypad backlight) \n"); } if (device_create_file(kpd_dev, &dev_attr_key_pressed) < 0) printk("Failed to create device file(%s)!\n", dev_attr_key_pressed.attr.name); if (device_create_file(kpd_dev, &dev_attr_backlight_ctrl) < 0) printk("Failed to create device file(%s)!\n", dev_attr_backlight_ctrl.attr.name); if (device_create_file(kpd_dev, &dev_attr_backlight_lpm_ctrl) < 0) printk("Failed to create device file(%s)!\n", dev_attr_backlight_lpm_ctrl.attr.name); #if defined(CONFIG_MACH_VINO) || defined(CONFIG_MACH_GIOS) if (device_create_file(kpd_dev, &dev_attr_volumnkey_ctrl) < 0) printk("Failed to create device file(%s)!\n", dev_attr_volumnkey_ctrl.attr.name); #endif /* Creating device attributes for setting keypad backlight time */ if (device_create_file(kpd_dev, &bl_keypad_attributes[0]) < 0){ printk("Failed to create device attributes for Keypad Backlight \n"); device_destroy(bl_class,0); class_destroy(bl_class); } /* Initializing delayed work for Back light off */ INIT_DELAYED_WORK(&backlightoff, keypad_backlightoff_work); #endif mi = container_of(info, struct gpio_event_matrix_info, info); if (func == GPIO_EVENT_FUNC_SUSPEND || func == GPIO_EVENT_FUNC_RESUME) { #if defined(CONFIG_MACH_RANT3) || defined(CONFIG_MACH_REALITY2) || defined(CONFIG_MACH_VINO) || defined(CONFIG_MACH_ROOKIE) || defined(CONFIG_MACH_ESCAPE) || defined(CONFIG_MACH_GIO) || defined(CONFIG_MACH_GIOS) if(func == GPIO_EVENT_FUNC_SUSPEND) keypad_backlight_power(OFF); else keypad_backlight_power(ON); #endif /* TODO: disable scanning */ return 0; } if (func == GPIO_EVENT_FUNC_INIT) { if (mi->keymap == NULL || mi->input_gpios == NULL || mi->output_gpios == NULL) { err = -ENODEV; pr_err("gpiomatrix: Incomplete pdata\n"); goto err_invalid_platform_data; } key_count = mi->ninputs * mi->noutputs; pgpio_key=*data = kp = kzalloc(sizeof(*kp) + sizeof(kp->keys_pressed[0]) * BITS_TO_LONGS(key_count), GFP_KERNEL); if (kp == NULL) { err = -ENOMEM; pr_err("gpiomatrix: Failed to allocate private data\n"); goto err_kp_alloc_failed; } kp->input_devs = input_devs; kp->keypad_info = mi; for (i = 0; i < key_count; i++) { unsigned short keyentry = mi->keymap[i]; unsigned short keycode = keyentry & MATRIX_KEY_MASK; unsigned short dev = keyentry >> MATRIX_CODE_BITS; if (dev >= input_devs->count) { pr_err("gpiomatrix: bad device index %d >= " "%d for key code %d\n", dev, input_devs->count, keycode); err = -EINVAL; goto err_bad_keymap; } if (keycode && keycode <= KEY_MAX) input_set_capability(input_devs->dev[dev], EV_KEY, keycode); } #if defined(CONFIG_MACH_ESCAPE) input_set_capability(kp->input_devs->dev[0], EV_SW, SW_LID); if(gpio_get_value(HALL_GPIO)) kp->input_devs->dev[0]->sw[SW_LID] = 0; else kp->input_devs->dev[0]->sw[SW_LID] = 1; #endif for (i = 0; i < mi->noutputs; i++) { err = gpio_request(mi->output_gpios[i], "gpio_kp_out"); if (err) { pr_err("gpiomatrix: gpio_request failed for " "output %d\n", mi->output_gpios[i]); goto err_request_output_gpio_failed; } if (gpio_cansleep(mi->output_gpios[i])) { pr_err("gpiomatrix: unsupported output gpio %d," " can sleep\n", mi->output_gpios[i]); err = -EINVAL; goto err_output_gpio_configure_failed; } if (mi->flags & GPIOKPF_DRIVE_INACTIVE){ #if defined(CONFIG_MACH_RANT3) || defined(CONFIG_MACH_ESCAPE) #if defined(CONFIG_MACH_RANT3) if(hw_version < 6) #endif { err = gpio_tlmm_config(GPIO_CFG(mi->output_gpios[i] , 0, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP,GPIO_CFG_2MA), GPIO_CFG_ENABLE); printk("Gpio config %d return %d \r\n",mi->output_gpios[i] ,err); if (err) { pr_err("gpiomatrix: gpio_tlmm_config failed for " "output %d\n", mi->output_gpios[i]); goto err_request_output_gpio_failed; } } #endif err = gpio_direction_output(mi->output_gpios[i], !(mi->flags & GPIOKPF_ACTIVE_HIGH)); } else err = gpio_direction_input(mi->output_gpios[i]); if (err) { pr_err("gpiomatrix: gpio_configure failed for " "output %d\n", mi->output_gpios[i]); goto err_output_gpio_configure_failed; } } for (i = 0; i < mi->ninputs; i++) { err = gpio_request(mi->input_gpios[i], "gpio_kp_in"); if (err) { pr_err("gpiomatrix: gpio_request failed for " "input %d\n", mi->input_gpios[i]); goto err_request_input_gpio_failed; } #if defined (CONFIG_MACH_ROOKIE) || defined(CONFIG_MACH_ESCAPE)// || defined(CONFIG_MACH_GIO) if ( i >= mi->ninputs-2) // ( (i == 2) || (i == 3)) err = gpio_tlmm_config(GPIO_CFG(mi->input_gpios[i] , 0, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL,GPIO_CFG_2MA), GPIO_CFG_ENABLE); else #endif #if defined(CONFIG_MACH_RANT3) if(hw_version < 6) { err = gpio_tlmm_config(GPIO_CFG(mi->input_gpios[i] , 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN,GPIO_CFG_2MA), GPIO_CFG_ENABLE); pr_err("Gpio config %d return %d\r\n",mi->input_gpios[i] ,err); if (err) { printk("gpiomatrix: gpio_tlmm_config failed for " "input %d\n", mi->input_gpios[i]); goto err_request_input_gpio_failed; } } #elif defined(CONFIG_MACH_GIO) || defined(CONFIG_MACH_VINO) || defined(CONFIG_MACH_GIOS) #else err = gpio_tlmm_config(GPIO_CFG(mi->input_gpios[i] , 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN,GPIO_CFG_2MA), GPIO_CFG_ENABLE); pr_err("Gpio config %d return %d\r\n",mi->input_gpios[i] ,err); if (err) { printk("gpiomatrix: gpio_tlmm_config failed for " "input %d\n", mi->input_gpios[i]); goto err_request_input_gpio_failed; } #endif err = gpio_direction_input(mi->input_gpios[i]); if (err) { pr_err("gpiomatrix: gpio_direction_input failed" " for input %d\n", mi->input_gpios[i]); goto err_gpio_direction_input_failed; } } for (i = 0; i < mi->ninputs; i++) { printk("Reading Input GPIO %d at init is %d \r\n",mi->input_gpios[i],gpio_get_value(mi->input_gpios[i])); } kp->current_output = mi->noutputs; kp->key_state_changed = 1; hrtimer_init(&kp->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); kp->timer.function = gpio_keypad_timer_func; wake_lock_init(&kp->wake_lock, WAKE_LOCK_SUSPEND, "gpio_kp"); err = gpio_keypad_request_irqs(kp); kp->use_irq = err == 0; pr_debug("GPIO Matrix Keypad Driver: Start keypad matrix for " "%s%s in %s mode\n", input_devs->dev[0]->name, (input_devs->count > 1) ? "..." : "", kp->use_irq ? "interrupt" : "polling"); if (kp->use_irq) wake_lock(&kp->wake_lock); hrtimer_start(&kp->timer, ktime_set(0, 10000), HRTIMER_MODE_REL); #if defined(CONFIG_MACH_RANT3) || defined(CONFIG_MACH_VINO) || defined(CONFIG_MACH_REALITY2) || defined(CONFIG_MACH_ROOKIE) || defined(CONFIG_MACH_ESCAPE) || defined(CONFIG_MACH_GIO) || defined(CONFIG_MACH_GIOS) early_suspend.suspend = keypad_early_suspend; early_suspend.resume = keypad_late_resume; register_early_suspend(&early_suspend); backlight_flag = 1; keypad_backlight_power(OFF); spin_lock_init(&keypad_led_lock); #endif return 0; } err = 0; kp = *data; if (kp->use_irq) for (i = mi->noutputs - 1; i >= 0; i--) free_irq(gpio_to_irq(mi->input_gpios[i]), kp); hrtimer_cancel(&kp->timer); wake_lock_destroy(&kp->wake_lock); for (i = mi->noutputs - 1; i >= 0; i--) { err_gpio_direction_input_failed: gpio_free(mi->input_gpios[i]); err_request_input_gpio_failed: ; } for (i = mi->noutputs - 1; i >= 0; i--) { err_output_gpio_configure_failed: gpio_free(mi->output_gpios[i]); err_request_output_gpio_failed: ; } err_bad_keymap: kfree(kp); err_kp_alloc_failed: err_invalid_platform_data: return err; }
int gpio_event_matrix_func(struct gpio_event_input_devs *input_devs, struct gpio_event_info *info, void **data, int func) { int i; int err; int key_count; int phone_call_status; int fm_radio_status; int irq; static int irq_status = 1; struct gpio_kp *kp; struct gpio_event_matrix_info *mi; mi = container_of(info, struct gpio_event_matrix_info, info); if (func == GPIO_EVENT_FUNC_SUSPEND || func == GPIO_EVENT_FUNC_RESUME) { /* TODO: disable scanning */ if (mi->detect_phone_status == 0) { if (func == GPIO_EVENT_FUNC_SUSPEND) irq_status = 0; else irq_status = 1; } else { phone_call_status = gpio_event_get_phone_call_status() & 0x01; fm_radio_status = gpio_event_get_fm_radio_status() & 0x01; KEY_LOGI("%s: mi->ninputs: %d, func&0x01 = %d, phone_call_status=%d, fm_radio_status=%d\n", __func__, mi->ninputs, func & 0x01, phone_call_status, fm_radio_status); if (irq_status != ((func & 0x01) | phone_call_status | fm_radio_status)) { irq_status = ((func & 0x01) | phone_call_status | fm_radio_status); KEY_LOGI("%s: irq_status %d \n", __func__, irq_status); } else { KEY_LOGI("%s: irq_status %d, did not change\n", __func__, irq_status); return 0; } } for (i = 0; i < mi->ninputs; i++) { irq = gpio_to_irq(mi->input_gpios[i]); err = irq_set_irq_wake(irq, irq_status); if (err) KEY_LOGE("gpiomatrix: set_irq_wake failed ,irq_status %d ,for input irq %d,%d\n", irq_status, i, irq); else KEY_LOGD("%s: set ok,irq_status %d, irq %d = %d\n", __func__, irq_status, i, irq); } return 0; } if (func == GPIO_EVENT_FUNC_INIT) { if (mi->keymap == NULL || mi->input_gpios == NULL || mi->output_gpios == NULL) { err = -ENODEV; KEY_LOGE("gpiomatrix: Incomplete pdata\n"); goto err_invalid_platform_data; } key_count = mi->ninputs * mi->noutputs; *data = kp = kzalloc(sizeof(*kp) + sizeof(kp->keys_pressed[0]) * BITS_TO_LONGS(key_count), GFP_KERNEL); if (kp == NULL) { err = -ENOMEM; KEY_LOGE("gpiomatrix: Failed to allocate private data\n"); goto err_kp_alloc_failed; } kp->input_devs = input_devs; kp->keypad_info = mi; for (i = 0; i < key_count; i++) { unsigned short keyentry = mi->keymap[i]; unsigned short keycode = keyentry & MATRIX_KEY_MASK; unsigned short dev = keyentry >> MATRIX_CODE_BITS; if (dev >= input_devs->count) { KEY_LOGE("gpiomatrix: bad device index %d >= " "%d for key code %d\n", dev, input_devs->count, keycode); err = -EINVAL; goto err_bad_keymap; } if (keycode && keycode <= KEY_MAX) input_set_capability(input_devs->dev[dev], EV_KEY, keycode); } #ifndef CONFIG_ARCH_MSM8X60 if (mi->setup_ninputs_gpio) mi->setup_ninputs_gpio(); #else if (mi->setup_matrix_gpio) mi->setup_matrix_gpio(); #endif for (i = 0; i < mi->noutputs; i++) { err = gpio_request(mi->output_gpios[i], "gpio_kp_out"); if (err) { KEY_LOGE("gpiomatrix: gpio_request failed for " "output %d\n", mi->output_gpios[i]); goto err_request_output_gpio_failed; } if (gpio_cansleep(mi->output_gpios[i])) { KEY_LOGE("gpiomatrix: unsupported output gpio %d," " can sleep\n", mi->output_gpios[i]); err = -EINVAL; goto err_output_gpio_configure_failed; } if (mi->flags & GPIOKPF_DRIVE_INACTIVE) err = gpio_direction_output(mi->output_gpios[i], !(mi->flags & GPIOKPF_ACTIVE_HIGH)); else err = gpio_direction_input(mi->output_gpios[i]); if (err) { KEY_LOGE("gpiomatrix: gpio_configure failed for " "output %d\n", mi->output_gpios[i]); goto err_output_gpio_configure_failed; } } for (i = 0; i < mi->ninputs; i++) { err = gpio_request(mi->input_gpios[i], "gpio_kp_in"); if (err) { KEY_LOGE("gpiomatrix: gpio_request failed for " "input %d\n", mi->input_gpios[i]); goto err_request_input_gpio_failed; } err = gpio_direction_input(mi->input_gpios[i]); if (err) { KEY_LOGE("gpiomatrix: gpio_direction_input failed" " for input %d\n", mi->input_gpios[i]); goto err_gpio_direction_input_failed; } } kp->current_output = mi->noutputs; kp->key_state_changed = 1; #ifndef CONFIG_ARCH_MSM8X60 hrtimer_init(&kp->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); kp->timer.function = gpio_keypad_timer_func; #else km_queue = create_singlethread_workqueue("km_queue"); INIT_WORK(&kp->work, gpio_keypad_timer_func); #endif wake_lock_init(&kp->wake_lock, WAKE_LOCK_SUSPEND, "gpio_kp"); err = gpio_keypad_request_irqs(kp); kp->use_irq = err == 0; #ifndef CONFIG_ARCH_MSM8X60 kp_use_irq = kp->use_irq; #endif KEY_LOGI("GPIO Matrix Keypad Driver: Start keypad matrix for " "%s%s in %s mode\n", input_devs->dev[0]->name, (input_devs->count > 1) ? "..." : "", kp->use_irq ? "interrupt" : "polling"); if (kp->use_irq) wake_lock(&kp->wake_lock); #ifndef CONFIG_ARCH_MSM8X60 hrtimer_start(&kp->timer, ktime_set(0, 0), HRTIMER_MODE_REL); #else queue_work(km_queue, &kp->work); #endif return 0; } err = 0; kp = *data; if (kp->use_irq) for (i = mi->noutputs - 1; i >= 0; i--) free_irq(gpio_to_irq(mi->input_gpios[i]), kp); #ifndef CONFIG_ARCH_MSM8X60 hrtimer_cancel(&kp->timer); #else cancel_work_sync(&kp->work); #endif wake_lock_destroy(&kp->wake_lock); for (i = mi->noutputs - 1; i >= 0; i--) { err_gpio_direction_input_failed: gpio_free(mi->input_gpios[i]); err_request_input_gpio_failed: ; } for (i = mi->noutputs - 1; i >= 0; i--) { err_output_gpio_configure_failed: gpio_free(mi->output_gpios[i]); err_request_output_gpio_failed: ; } err_bad_keymap: kfree(kp); err_kp_alloc_failed: err_invalid_platform_data: return err; }