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;
}
Beispiel #3
0
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]);
}
Beispiel #5
0
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");
	}
}
Beispiel #6
0
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;
}
Beispiel #7
0
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);
}
Beispiel #11
0
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;
}
Beispiel #12
0
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);
}