static void handle_only_power_key(unsigned int code, int value) { struct gpio_input_state *ds = gb_ddata; if (code == KEY_POWER && ds->disable_reset_flag != 0) { if (value) { queue_delayed_work(ds->disable_reset_wq, &ds->clear_hw_reset_work, msecs_to_jiffies(0)); #ifdef CONFIG_KPDPWR_S2_DVDD_RESET clear_kpdpwr_s2_rst_flag = 1; KEY_LOGD("%s: Enable kpdpwr s2 reset clear up [%d]\n", __func__, clear_kpdpwr_s2_rst_flag); hrtimer_start(&clr_kpd_reset_timer, ktime_set(0, KPDPWR_CLR_RESET_TIMER), HRTIMER_MODE_REL); #endif } else { __cancel_delayed_work(&ds->clear_hw_reset_work); #ifdef CONFIG_KPDPWR_S2_DVDD_RESET clear_kpdpwr_s2_rst_flag = 0; KEY_LOGD("%s: Disable kpdpwr s2 reset clear up [%d]\n", __func__, clear_kpdpwr_s2_rst_flag); if (hrtimer_is_queued(&clr_kpd_reset_timer)) hrtimer_cancel(&clr_kpd_reset_timer); if (hrtimer_is_queued(&enable_kpd_s2_timer)) hrtimer_cancel(&enable_kpd_s2_timer); #endif } } }
static irqreturn_t gpio_event_input_irq_handler(int irq, void *dev_id) { struct gpio_key_state *ks = dev_id; struct gpio_input_state *ds = ks->ds; int keymap_index = ks - ds->key_state; const struct gpio_event_direct_entry *key_entry; unsigned long irqflags; #ifndef CONFIG_MFD_MAX8957 int pressed; #endif KEY_LOGD("%s, irq=%d, use_irq=%d\n", __func__, irq, ds->use_irq); if (!ds->use_irq) return IRQ_HANDLED; key_entry = &ds->info->keymap[keymap_index]; if (ds->info->debounce_time.tv64) { spin_lock_irqsave(&ds->irq_lock, irqflags); if (ks->debounce & DEBOUNCE_WAIT_IRQ) { ks->debounce = DEBOUNCE_UNKNOWN; if (ds->debounce_count++ == 0) { wake_lock(&ds->wake_lock); #ifndef CONFIG_MFD_MAX8957 hrtimer_start( &ds->timer, ds->info->debounce_time, HRTIMER_MODE_REL); #endif } if (ds->info->flags & GPIOEDF_PRINT_KEY_DEBOUNCE) KEY_LOGD("gpio_event_input_irq_handler: " "key %x-%x, %d (%d) start debounce\n", ds->info->type, key_entry->code, keymap_index, key_entry->gpio); } else { disable_irq_nosync(irq); ks->debounce = DEBOUNCE_UNSTABLE; } spin_unlock_irqrestore(&ds->irq_lock, irqflags); } else { #ifdef CONFIG_MFD_MAX8957 queue_work(ki_queue, &ks->work); #else pressed = gpio_get_value(key_entry->gpio) ^ !(ds->info->flags & GPIOEDF_ACTIVE_HIGH); if (ds->info->flags & GPIOEDF_PRINT_KEYS) KEY_LOGD("gpio_event_input_irq_handler: key %x-%x, %d " "(%d) changed to %d\n", ds->info->type, key_entry->code, keymap_index, key_entry->gpio, pressed); input_event(ds->input_devs->dev[key_entry->dev], ds->info->type, key_entry->code, pressed); input_sync(ds->input_devs->dev[key_entry->dev]); #endif } return IRQ_HANDLED; }
static irqreturn_t gpio_event_input_irq_handler(int irq, void *dev_id) { struct gpio_key_state *ks = dev_id; struct gpio_input_state *ds = ks->ds; int keymap_index = ks - ds->key_state; const struct gpio_event_direct_entry *key_entry; unsigned long irqflags; int pressed; KEY_LOGD("%s, irq=%d, use_irq=%d\n", __func__, irq, ds->use_irq); if (!ds->use_irq) return IRQ_HANDLED; key_entry = &ds->info->keymap[keymap_index]; if (key_entry->code == KEY_POWER && power_key_intr_flag == 0) { irq_set_irq_type(irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING); power_key_intr_flag = 1; KEY_LOGD("%s, keycode = %d, first intr", __func__, key_entry->code); } if (ds->info->debounce_time.tv64) { spin_lock_irqsave(&ds->irq_lock, irqflags); if (ks->debounce & DEBOUNCE_WAIT_IRQ) { ks->debounce = DEBOUNCE_UNKNOWN; if (ds->debounce_count++ == 0) { wake_lock(&ds->wake_lock); hrtimer_start( &ds->timer, ds->info->debounce_time, HRTIMER_MODE_REL); } if (ds->info->flags & GPIOEDF_PRINT_KEY_DEBOUNCE) KEY_LOGD("gpio_event_input_irq_handler: " "key %x-%x, %d (%d) start debounce\n", ds->info->type, key_entry->code, keymap_index, key_entry->gpio); } else { disable_irq_nosync(irq); ks->debounce = DEBOUNCE_UNSTABLE; } spin_unlock_irqrestore(&ds->irq_lock, irqflags); } else { pressed = gpio_get_value_cansleep(key_entry->gpio) ^ !(ds->info->flags & GPIOEDF_ACTIVE_HIGH); if (ds->info->flags & GPIOEDF_PRINT_KEYS) KEY_LOGD("gpio_event_input_irq_handler: key %x-%x, %d " "(%d) changed to %d\n", ds->info->type, key_entry->code, keymap_index, key_entry->gpio, pressed); input_event(ds->input_devs->dev[key_entry->dev], ds->info->type, key_entry->code, pressed); input_sync(ds->input_devs->dev[key_entry->dev]); } return IRQ_HANDLED; }
void keypad_report_keycode(struct gpio_key_state *ks) { struct gpio_input_state *ds = ks->ds; int keymap_index; const struct gpio_event_direct_entry *key_entry; int pressed; if (ds == NULL) { KEY_LOGE("%s, (ds == NULL) failed\n", __func__); return; } keymap_index = ks - ds->key_state; key_entry = &ds->info->keymap[keymap_index]; if (key_entry == NULL) { KEY_LOGE("%s, (key_entry == NULL) failed\n", __func__); return; } pressed = gpio_get_value(key_entry->gpio) ^ !(ds->info->flags & GPIOEDF_ACTIVE_HIGH); if (key_entry->code == KEY_POWER) { if (pressed) wake_lock(&ds->key_pressed_wake_lock); else wake_unlock(&ds->key_pressed_wake_lock); } if (ds->info->flags & GPIOEDF_PRINT_KEYS) KEY_LOGD("%s: key %d-%d, %d " "(%d) changed to %d\n", __func__, ds->info->type, key_entry->code, keymap_index, key_entry->gpio, pressed); #ifdef CONFIG_POWER_KEY_LED handle_power_key_led(key_entry->code, pressed); #endif #ifdef CONFIG_POWER_KEY_CLR_RESET handle_power_key_reset(key_entry->code, pressed); #endif input_event(ds->input_devs->dev[key_entry->dev], ds->info->type, key_entry->code, pressed); input_sync(ds->input_devs->dev[key_entry->dev]); }
static inline void print_key_ds(struct gpio_input_state *ds) { int i; int nkeys = ds->info->keymap_size; const struct gpio_event_direct_entry *key_entry; struct gpio_key_state *key_state; key_entry = ds->info->keymap; key_state = ds->key_state; for (i = 0; i < nkeys; i++, key_entry++, key_state++) { KEY_LOGD("0x%X key state: ", key_entry->code); if (key_state->debounce & DEBOUNCE_UNSTABLE) KEY_LOGD(" | DEBOUNCE_UNSTABLE"); if (key_state->debounce & DEBOUNCE_PRESSED) KEY_LOGD(" | DEBOUNCE_PRESSED"); if (key_state->debounce & DEBOUNCE_NOTPRESSED) KEY_LOGD(" | DEBOUNCE_NOTPRESSED"); if (key_state->debounce & DEBOUNCE_WAIT_IRQ) KEY_LOGD(" | DEBOUNCE_WAIT_IRQ"); if (key_state->debounce & DEBOUNCE_POLL) KEY_LOGD(" | DEBOUNCE_POLL"); } }
static enum hrtimer_restart gpio_event_input_timer_func(struct hrtimer *timer) { int i; int pressed; struct gpio_input_state *ds = container_of(timer, struct gpio_input_state, timer); unsigned gpio_flags = ds->info->flags; unsigned npolarity; int nkeys = ds->info->keymap_size; const struct gpio_event_direct_entry *key_entry; struct gpio_key_state *key_state; unsigned long irqflags; uint8_t debounce; bool sync_needed; #if 0 key_entry = kp->keys_info->keymap; key_state = kp->key_state; for (i = 0; i < nkeys; i++, key_entry++, key_state++) pr_info("gpio_read_detect_status %d %d\n", key_entry->gpio, gpio_read_detect_status(key_entry->gpio)); #endif key_entry = ds->info->keymap; key_state = ds->key_state; sync_needed = false; spin_lock_irqsave(&ds->irq_lock, irqflags); for (i = 0; i < nkeys; i++, key_entry++, key_state++) { debounce = key_state->debounce; if (debounce & DEBOUNCE_WAIT_IRQ) continue; if (key_state->debounce & DEBOUNCE_UNSTABLE) { debounce = key_state->debounce = DEBOUNCE_UNKNOWN; enable_irq(gpio_to_irq(key_entry->gpio)); KEY_LOGD("gpio_keys_scan_keys: key %x-%x, %d " "(%d) continue debounce\n", ds->info->type, key_entry->code, i, key_entry->gpio); } npolarity = !(gpio_flags & GPIOEDF_ACTIVE_HIGH); pressed = gpio_get_value_cansleep(key_entry->gpio) ^ npolarity; if (debounce & DEBOUNCE_POLL) { if (pressed == !(debounce & DEBOUNCE_PRESSED)) { ds->debounce_count++; key_state->debounce = DEBOUNCE_UNKNOWN; if (gpio_flags & GPIOEDF_PRINT_KEY_DEBOUNCE) KEY_LOGD("gpio_keys_scan_keys: key %x-" "%x, %d (%d) start debounce\n", ds->info->type, key_entry->code, i, key_entry->gpio); } continue; } if (pressed && (debounce & DEBOUNCE_NOTPRESSED)) { if (gpio_flags & GPIOEDF_PRINT_KEY_DEBOUNCE) KEY_LOGD("gpio_keys_scan_keys: key %x-%x, %d " "(%d) debounce pressed 1\n", ds->info->type, key_entry->code, i, key_entry->gpio); key_state->debounce = DEBOUNCE_PRESSED; continue; } if (!pressed && (debounce & DEBOUNCE_PRESSED)) { if (gpio_flags & GPIOEDF_PRINT_KEY_DEBOUNCE) KEY_LOGD("gpio_keys_scan_keys: key %x-%x, %d " "(%d) debounce pressed 0\n", ds->info->type, key_entry->code, i, key_entry->gpio); key_state->debounce = DEBOUNCE_NOTPRESSED; continue; } /* key is stable */ ds->debounce_count--; if (ds->use_irq) key_state->debounce |= DEBOUNCE_WAIT_IRQ; else key_state->debounce |= DEBOUNCE_POLL; if (gpio_flags & GPIOEDF_PRINT_KEYS) KEY_LOGD("gpio_keys_scan_keys: key %x-%x, %d (%d) " "changed to %d\n", ds->info->type, key_entry->code, i, key_entry->gpio, pressed); #ifdef CONFIG_POWER_KEY_LED handle_power_key_led(key_entry->code, pressed); #endif input_event(ds->input_devs->dev[key_entry->dev], ds->info->type, key_entry->code, pressed); sync_needed = true; } if (sync_needed) { for (i = 0; i < ds->input_devs->count; i++) input_sync(ds->input_devs->dev[i]); } #if 0 key_entry = kp->keys_info->keymap; key_state = kp->key_state; for (i = 0; i < nkeys; i++, key_entry++, key_state++) { pr_info("gpio_read_detect_status %d %d\n", key_entry->gpio, gpio_read_detect_status(key_entry->gpio)); } #endif if (ds->debounce_count) hrtimer_start(timer, ds->info->debounce_time, HRTIMER_MODE_REL); else if (!ds->use_irq) hrtimer_start(timer, ds->info->poll_time, HRTIMER_MODE_REL); else wake_unlock(&ds->wake_lock); spin_unlock_irqrestore(&ds->irq_lock, irqflags); return HRTIMER_NORESTART; }
static void gpio_event_input_delayed_func(struct work_struct *key_work) { int i; int pressed; struct gpio_input_state *ds = container_of((struct delayed_work *)key_work, struct gpio_key_state, key_work)->ds; unsigned npolarity; unsigned gpio_flags = ds->info->flags; int nkeys = ds->info->keymap_size; const struct gpio_event_direct_entry *key_entry; struct gpio_key_state *key_state; unsigned long irqflags; uint8_t debounce; bool sync_needed; key_entry = ds->info->keymap; key_state = ds->key_state; npolarity = !(gpio_flags & GPIOEDF_ACTIVE_HIGH); for (i = 0; i < nkeys; i++, key_entry++, key_state++) { key_state->keyValue = gpio_get_value(key_entry->gpio) ^ npolarity; key_state->irq_enable_needed = 0; key_state->need_queue = 0; } #ifdef KEYPAD_DEBUG KEY_LOGD("Before process: \n"); print_key_ds(ds); #endif key_entry = ds->info->keymap; key_state = ds->key_state; sync_needed = false; spin_lock_irqsave(&ds->irq_lock, irqflags); for (i = 0; i < nkeys; i++, key_entry++, key_state++) { debounce = key_state->debounce; if (debounce & DEBOUNCE_WAIT_IRQ) continue; if (key_state->debounce & DEBOUNCE_UNSTABLE) { debounce = key_state->debounce = DEBOUNCE_UNKNOWN; key_state->irq_enable_needed = 1; if (gpio_flags & GPIOEDF_PRINT_KEY_UNSTABLE) KEY_LOGD("gpio_keys_scan_keys: key %x-%x, %d " "(%d) continue debounce," #ifdef KEYPAD_DEBUG " enable irq#%d\n" #endif , ds->info->type, key_entry->code, i, key_entry->gpio #ifdef KEYPAD_DEBUG , gpio_to_irq(key_entry->gpio) #endif ); } pressed = key_state->keyValue; if (debounce & DEBOUNCE_POLL) { if (pressed == !(debounce & DEBOUNCE_PRESSED)) { ds->debounce_count++; key_state->need_queue = 1; key_state->debounce = DEBOUNCE_UNKNOWN; if (gpio_flags & GPIOEDF_PRINT_KEY_DEBOUNCE) KEY_LOGD("gpio_keys_scan_keys: key %x-" "%x, %d (%d) start debounce\n", ds->info->type, key_entry->code, i, key_entry->gpio); } continue; } if (pressed && (debounce & DEBOUNCE_NOTPRESSED)) { if (gpio_flags & GPIOEDF_PRINT_KEY_DEBOUNCE) KEY_LOGD("gpio_keys_scan_keys: key %x-%x, %d " "(%d) debounce pressed 1\n", ds->info->type, key_entry->code, i, key_entry->gpio); key_state->debounce = DEBOUNCE_PRESSED; key_state->need_queue = 1; continue; } if (!pressed && (debounce & DEBOUNCE_PRESSED)) { if (gpio_flags & GPIOEDF_PRINT_KEY_DEBOUNCE) KEY_LOGD("gpio_keys_scan_keys: key %x-%x, %d " "(%d) debounce pressed 0\n", ds->info->type, key_entry->code, i, key_entry->gpio); key_state->debounce = DEBOUNCE_NOTPRESSED; key_state->need_queue = 1; continue; } /* key is stable */ ds->debounce_count--; if (ds->use_irq) key_state->debounce |= DEBOUNCE_WAIT_IRQ; else key_state->debounce |= DEBOUNCE_POLL; if (gpio_flags & GPIOEDF_PRINT_KEYS) KEY_LOGD("gpio_keys_scan_keys: key %x-%x, %d (%d) " "changed to %d\n", ds->info->type, key_entry->code, i, key_entry->gpio, pressed); #ifdef CONFIG_POWER_KEY_LED handle_power_key_led(key_entry->code, pressed); #endif input_event(ds->input_devs->dev[key_entry->dev], ds->info->type, key_entry->code, pressed); sync_needed = true; } if (sync_needed) { for (i = 0; i < ds->input_devs->count; i++) input_sync(ds->input_devs->dev[i]); } #if 0 key_entry = kp->keys_info->keymap; key_state = kp->key_state; for (i = 0; i < nkeys; i++, key_entry++, key_state++) { pr_info("gpio_read_detect_status %d %d\n", key_entry->gpio, gpio_read_detect_status(key_entry->gpio)); } #endif if (ds->debounce_count) { key_entry = ds->info->keymap; key_state = ds->key_state; for (i = 0; i < nkeys; i++, key_entry++, key_state++) { if (key_state->need_queue) if (!queue_delayed_work(ki_queue, &(key_state->key_work), KTIME_TO_JIFFIES(ds->info->debounce_time))) KEY_LOGI("Keycode: 0x%X has been queued already.\n", key_entry->code); } } else if (!ds->use_irq) { key_entry = ds->info->keymap; key_state = ds->key_state; for (i = 0; i < nkeys; i++, key_entry++, key_state++) { if (key_state->need_queue) if (!queue_delayed_work(ki_queue, &(key_state->key_work), KTIME_TO_JIFFIES(ds->info->poll_time))) KEY_LOGI("Keycode: 0x%X has been queued already.\n", key_entry->code); } } else wake_unlock(&ds->wake_lock); spin_unlock_irqrestore(&ds->irq_lock, irqflags); #if 0 key_entry = ds->info->keymap; key_state = ds->key_state; for (i = 0; i < nkeys; i++, key_entry++, key_state++) if (key_state->irq_enable_needed) enable_irq(gpio_to_irq(key_entry->gpio)); #endif #ifdef KEYPAD_DEBUG KEY_LOGD("After process:\n"); print_key_ds(ds); #endif }
static void handle_power_key_reset(unsigned int code, int value) { #ifdef CONFIG_POWER_VOLUP_RESET uint8_t i = 0, read_val = 0; struct gpio_event_input_info *aa = gis; if (code == KEY_POWER || code == KEY_VOLUMEUP) { if (!value && code == KEY_VOLUMEUP) { KEY_LOGI("[VUP] start count for power key led off\n"); schedule_delayed_work(&power_key_led_off_work, PWRKEYLEDOFF_DELAY); } for (i = 0; (i < aa->keymap_size && code != KEY_POWER); i++) { if (aa->keymap[i].code == KEY_POWER) { read_val = gpio_get_value(aa->keymap[i].gpio); KEY_LOGI("Idx[%d] GPIO_%d:PWR is %s\n", i, aa->keymap[i].gpio, (read_val ? "NOT pressed" : "PRESSED" )); if (read_val) { #ifdef CONFIG_KPDPWR_S2_DVDD_RESET clear_kpdpwr_s2_rst_flag = 0; KEY_LOGD("%s: Disable kpdpwr s2 reset clear up [%d]\n", __func__, clear_kpdpwr_s2_rst_flag); #endif return; } else { KEY_LOGI("[PWR+VUP] start count for power key led on\n"); schedule_delayed_work(&power_key_led_on_work, PWRKEYLEDON_DELAY); power_key_led_requested = 1; #ifdef CONFIG_KPDPWR_S2_DVDD_RESET clear_kpdpwr_s2_rst_flag = 1; KEY_LOGD("%s: Enable kpdpwr s2 reset clear up [%d]\n", __func__, clear_kpdpwr_s2_rst_flag); #endif break; } } } for (i = aa->keymap_size; (i > 0 && code != KEY_VOLUMEUP); i--) { if (aa->keymap[i-1].code == KEY_VOLUMEUP) { read_val = gpio_get_value(aa->keymap[i-1].gpio); KEY_LOGI("Idx[%d] GPIO_%d:VOL_UP is %s\n", i-1, aa->keymap[i-1].gpio, (read_val ? "NOT pressed" : "PRESSED" )); if (read_val) { goto KEY_PWR; } else { KEY_LOGI("[VUP+PWR] start count for power key led on\n"); schedule_delayed_work(&power_key_led_on_work, PWRKEYLEDON_DELAY); power_key_led_requested = 1; break; } } } KEY_PWR: #else if (code == KEY_POWER) { #endif if (value) { #ifdef CONFIG_KPDPWR_S2_DVDD_RESET clear_kpdpwr_s2_rst_flag = 1; KEY_LOGD("%s: Enable kpdpwr s2 reset clear up [%d]\n", __func__, clear_kpdpwr_s2_rst_flag); hrtimer_start(&clr_kpd_reset_timer, ktime_set(0, KPDPWR_CLR_RESET_TIMER), HRTIMER_MODE_REL); #endif #ifdef CONFIG_POWER_VOLUP_RESET wake_lock_timeout(&key_reset_clr_wake_lock, msecs_to_jiffies(2000)); KEY_LOGI("[PWR] start count for power key check reset\n"); if (!schedule_delayed_work(&power_key_check_reset_work, msecs_to_jiffies(1000))) #else wake_lock_timeout(&key_reset_clr_wake_lock, PWRKEYCHKRST_WAKELOCK_TIMEOUT); KEY_LOGI("[PWR] start count for power key check reset\n"); if (!schedule_delayed_work(&power_key_check_reset_work, PWRKEYCHKRST_DELAY)) #endif KEY_LOGI("[PWR] the reset work in already in the queue\n"); } else { KEY_LOGI("[PWR] start count for power key clear check\n"); if (!schedule_delayed_work(&power_key_clr_check_work, PWRKEYCLRCHK_DELAY)) KEY_LOGI("[PWR] the clear work in already in the queue\n"); #ifdef CONFIG_KPDPWR_S2_DVDD_RESET clear_kpdpwr_s2_rst_flag = 0; KEY_LOGD("%s: Disable kpdpwr s2 reset clear up [%d]\n", __func__, clear_kpdpwr_s2_rst_flag); if (hrtimer_is_queued(&clr_kpd_reset_timer)) hrtimer_cancel(&clr_kpd_reset_timer); if (hrtimer_is_queued(&enable_kpd_s2_timer)) hrtimer_cancel(&enable_kpd_s2_timer); #endif } } } #ifdef CONFIG_KPDPWR_S2_DVDD_RESET static enum hrtimer_restart clr_kpd_rst_timer_func(struct hrtimer *timer) { if (qpnp_get_reset_en(PON_KPDPWR) > 0) { qpnp_config_reset_enable(PON_KPDPWR, 0); qpnp_config_reset_enable(PON_KPDPWR, 1); hrtimer_start(&enable_kpd_s2_timer, ktime_set(0, 0), HRTIMER_MODE_REL); } return HRTIMER_NORESTART; } static enum hrtimer_restart enable_kpd_s2_timer_func(struct hrtimer *timer) { qpnp_config_reset_enable(PON_KPDPWR, 1); if (clear_kpdpwr_s2_rst_flag) { hrtimer_start(&clr_kpd_reset_timer, ktime_set(0, KPDPWR_CLR_RESET_TIMER), HRTIMER_MODE_REL); } else { if (hrtimer_is_queued(&clr_kpd_reset_timer)) hrtimer_cancel(&clr_kpd_reset_timer); if (hrtimer_is_queued(&enable_kpd_s2_timer)) hrtimer_cancel(&enable_kpd_s2_timer); } return HRTIMER_NORESTART; }
static void power_key_check_reset_work_func(struct work_struct *dummy) { struct gpio_event_input_info *aa = gis; #ifdef CONFIG_POWER_VOLUP_RESET uint8_t val = 0, i = 0; #else int pocket_mode = 0; #endif KEY_LOGI("[PWR] %s\n", __func__); #ifdef CONFIG_OF if ((aa->dt_clear_hw_reset)) { if (aa->info.rrm1_mode) { KEY_LOGI(" Power key check in Lab Test RRM1 mode.\n"); aa->dt_clear_hw_reset(aa->clr_gpio); #else if ((aa->clear_hw_reset)) { if (aa->info.rrm1_mode) { printk(KERN_INFO "[KEY] Power key check in Lab Test RRM1 mode.\n"); aa->clear_hw_reset(); #endif #ifndef CONFIG_POWER_VOLUP_RESET } else if (board_mfg_mode() == MFG_MODE_NORMAL) { pocket_mode = power_key_check_in_pocket(); if (pocket_mode) { printk(KERN_INFO "[KEY] power_key_check_in_pocket = %d\n", pocket_mode); #ifdef CONFIG_OF aa->dt_clear_hw_reset(aa->clr_gpio); #else aa->clear_hw_reset(); #endif } } else printk(KERN_INFO "[KEY] Not in normal OS mode, mode=%d\n", board_mfg_mode()); #else } else { printk(KERN_INFO "[KEY] OS Mode=%d\n", board_mfg_mode()); for (i = 0; i < aa->keymap_size; i++) { if (aa->keymap[i].code == KEY_VOLUMEUP) { val = gpio_get_value(aa->keymap[i].gpio); break; } } if (!val) { KEY_LOGI("HW RESET continue"); } else { #ifdef CONFIG_OF aa->dt_clear_hw_reset(aa->clr_gpio); #else aa->clear_hw_reset(); #endif } } #endif } else { KEY_LOGI("[PWR] No reset clear function\n"); } handle_power_key_reset(KEY_POWER, 1); } static DECLARE_DELAYED_WORK(power_key_check_reset_work, power_key_check_reset_work_func); static void power_key_clr_check_work_func(struct work_struct *dummy) { #ifdef CONFIG_POWER_VOLUP_RESET uint8_t i = 0, val = 0, pwr_idx = 0; struct gpio_event_input_info *aa = gis; for (i = 0; i < aa->keymap_size; i++) { if (aa->keymap[i].code == KEY_VOLUMEUP) { val = gpio_get_value(aa->keymap[i].gpio); if (val) { KEY_LOGI("volUP clear"); #ifdef CONFIG_OF aa->dt_clear_hw_reset(aa->clr_gpio); #else aa->clear_hw_reset(); #endif } break; } if (aa->keymap[i].code == KEY_POWER) pwr_idx = i; } val = gpio_get_value(aa->keymap[pwr_idx].gpio); if (val) { #endif if (cancel_delayed_work_sync(&power_key_check_reset_work)) KEY_LOGI("[PWR] cancel power key check reset work successfully\n"); else KEY_LOGI("[PWR] cancel power key check reset work unsuccessfully\n"); #ifdef CONFIG_KPDPWR_S2_DVDD_RESET clear_kpdpwr_s2_rst_flag = 0; KEY_LOGD("%s: Disable kpdpwr s2 reset clear up [%d]\n", __func__, clear_kpdpwr_s2_rst_flag); if (hrtimer_is_queued(&clr_kpd_reset_timer)) hrtimer_cancel(&clr_kpd_reset_timer); if (hrtimer_is_queued(&enable_kpd_s2_timer)) hrtimer_cancel(&enable_kpd_s2_timer); #endif #ifdef CONFIG_POWER_VOLUP_RESET } #endif wake_unlock(&key_reset_clr_wake_lock); }
int __init chacha_init_keypad(void) { char *get_cid; char *get_carrier; char *get_keycaps; uint8_t cid_len; KEY_LOGD("%s\n", __func__); board_get_cid_tag(&get_cid); board_get_carrier_tag(&get_carrier); board_get_keycaps_tag(&get_keycaps); KEY_LOGI("%s: get CID: %s\n\tCarrier: %s, Keycaps: %s\n", __func__, get_cid, get_carrier, get_keycaps); cid_len = strlen(get_cid); if (cid_len) { if (strstr(SKU_BOPOMO, get_cid) != NULL) { chacha_keypad_data.name = "chacha-keypad-bopomo"; } else if (strstr(SKU_FRA, get_cid) != NULL) { chacha_keymap[KEYMAP_INDEX(0, 3)] = KEY_W; chacha_keymap[KEYMAP_INDEX(3, 0)] = KEY_Z; chacha_keymap[KEYMAP_INDEX(3, 4)] = KEY_A; chacha_keypad_nav_map[1].code = KEY_Q; chacha_keypad_data.name = "chacha-keypad-fra"; } else if (strstr(SKU_ITA, get_cid) != NULL) { chacha_keymap[KEYMAP_INDEX(4, 3)] = KEY_F15; chacha_keypad_data.name = "chacha-keypad-ita"; } else if (strstr(SKU_TUR, get_cid) != NULL) { chacha_keypad_data.name = "chacha-keypad-tur"; } else if (strstr(SKU_ELL, get_cid) != NULL) { chacha_keymap[KEYMAP_INDEX(4, 3)] = KEY_F15; chacha_keypad_data.name = "chacha-keypad-ell"; } else if (strstr(SKU_GER, get_cid) != NULL) { chacha_keymap[KEYMAP_INDEX(0, 3)] = KEY_Y; chacha_keymap[KEYMAP_INDEX(5, 4)] = KEY_Z; chacha_keypad_data.name = "chacha-keypad-ger"; } else if (strstr(SKU_ARA, get_cid) != NULL) { chacha_keymap[KEYMAP_INDEX(4, 3)] = KEY_F15; chacha_keypad_data.name = "chacha-keypad-ara"; } else if (strstr(SKU_ESN, get_cid) != NULL) { chacha_keypad_data.name = "chacha-keypad-esn"; } else if (strstr(SKU_NOR, get_cid) != NULL) { chacha_keypad_data.name = "chacha-keypad-nor"; } else if (strstr(SKU_RUS, get_cid) != NULL) { chacha_keymap[KEYMAP_INDEX(4, 3)] = KEY_F15; chacha_keymap[KEYMAP_INDEX(3, 5)] = KEY_F16; chacha_keypad_data.name = "chacha-keypad-rus"; } else if (strstr(SKU_HK, get_cid) != NULL) { chacha_keymap[KEYMAP_INDEX(4, 3)] = KEY_F15; chacha_keypad_data.name = "chacha-keypad-hk"; } else if (strstr(SKU_CN, get_cid) != NULL) { chacha_keymap[KEYMAP_INDEX(4, 3)] = KEY_F15; chacha_keypad_data.name = "chacha-keypad-cn"; } else if (strstr(SKU_AW, get_cid) != NULL) { chacha_keymap[KEYMAP_INDEX(4, 3)] = KEY_F15; chacha_keypad_data.name = "chacha-keypad-aw"; } else if (strstr(SKU_THAI, get_cid) != NULL) { chacha_keymap[KEYMAP_INDEX(4, 3)] = KEY_F15; chacha_keypad_data.name = "chacha-keypad-tai"; } else if (strstr(SKU_STROKE_ENG, get_cid) != NULL) { chacha_keypad_data.name = "chacha-keypad-steng"; } else { if (strstr(SKU_WWE, get_cid) == NULL) KEY_LOGI("%s: CID not matched\n", __func__); } } if (platform_device_register(&chacha_reset_keys_device)) KEY_LOGE("%s: register reset key fail\n", __func__); return platform_device_register(&chacha_keypad_device); }
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; }
int get_kp_irq_mode(void) { KEY_LOGD("%s: kp_use_irq=%d\n", __func__, kp_use_irq); return kp_use_irq; }
int __init express_init_keypad(void) { KEY_LOGD("%s\n", __func__); return platform_device_register(&express_keypad_input_device); }