Exemplo n.º 1
0
static irqreturn_t mxskbd_irq_handler(int irq, void *dev_id)
{
	struct platform_device *pdev = dev_id;
	struct mxskbd_data *devdata = platform_get_drvdata(pdev);
	u16 raw_button, normalized_button, vddio;
	unsigned btn;

	if (devdata->btn_irq == irq) {
		__raw_writel(devdata->btn_irq_stat,
			     devdata->base + HW_LRADC_CTRL1_CLR);
		__raw_writel(BM_LRADC_CTRL1_LRADC0_IRQ << devdata->chan,
			     devdata->base + HW_LRADC_CTRL1_CLR);
		__raw_writel(BM_LRADC_CTRL1_LRADC0_IRQ_EN << devdata->chan,
			     devdata->base + HW_LRADC_CTRL1_SET);
		return IRQ_HANDLED;
	}

	raw_button = __raw_readl(devdata->base + HW_LRADC_CHn(devdata->chan)) &
				 BM_LRADC_CHn_VALUE;
	vddio = hw_lradc_vddio();
	BUG_ON(vddio == 0);

	normalized_button = (raw_button * TARGET_VDDIO_LRADC_VALUE) /
		vddio;

	if (normalized_button < BUTTON_PRESS_THRESHOLD &&
	    devdata->last_button < 0) {
		btn = mxskbd_decode_button(devdata->keycodes,
					   normalized_button);
		if (btn < KEY_MAX) {
			devdata->last_button = btn;
			input_report_key(GET_INPUT_DEV(devdata),
					 devdata->last_button, !0);
		} else
			dev_err(&pdev->dev, "Invalid button: raw = %d, "
				"normalized = %d, vddio = %d\n",
				raw_button, normalized_button, vddio);
	} else if (devdata->last_button > 0 &&
		   normalized_button >= BUTTON_PRESS_THRESHOLD) {
		input_report_key(GET_INPUT_DEV(devdata),
				 devdata->last_button, 0);
		devdata->last_button = -1;
		if (devdata->btn_irq > 0)
			__raw_writel(BM_LRADC_CTRL1_LRADC0_IRQ_EN <<
					devdata->chan,
				     devdata->base + HW_LRADC_CTRL1_CLR);
	}

	__raw_writel(BM_LRADC_CTRL1_LRADC0_IRQ << devdata->chan,
		     devdata->base + HW_LRADC_CTRL1_CLR);
	return IRQ_HANDLED;
}
Exemplo n.º 2
0
static irqreturn_t mxskbd_irq_handler(int irq, void *dev_id)
{
	struct platform_device *pdev = dev_id;
	struct mxskbd_data *d = platform_get_drvdata(pdev);
	int i, key, f_key = -1;
	u32 vddio;

	jack_process(d);

	/* end key process */
	i = (__raw_readl(REGS_POWER_BASE + HW_POWER_STS) &
		   BF_POWER_STS_PSWITCH(0x1)) ? KEY_END : -1;

	if (i == KEY_END) {
		if (i == d->last_button)
			goto _end;

		f_key = i;
	}

	if (f_key < 0 && d->jack_cnt == 0 &&
	    d->jack_last == SW_MICROPHONE_INSERT) {
		i = __raw_readl(d->base + HW_LRADC_CHn(d->chan[MAX_CH-1])) &
			BM_LRADC_CHn_VALUE;

		if (i <= MIC_DET_THRESHOLD) {
			if (d->last_button == KEY_KPENTER) {
				d->jack_push_cnt = 0;
				goto _end;
			}

			if (++d->jack_push_cnt > 4)
				f_key = KEY_KPENTER;
		} else
			d->jack_push_cnt = 0;
	} else
		d->jack_push_cnt = 0;

	/* adc key process */
	vddio = __raw_readl(d->base + HW_LRADC_CHn(VDDIO_VOLTAGE_CH)) &
		BM_LRADC_CHn_VALUE;
	BUG_ON(vddio == 0);

#ifdef DUMP_KEY_ADC
	static int val[MAX_CH];
	printk("KEY=0x%03x(%4d), 0x%03x(%4d), 0x%03x(%4d), 0x%03x(%4d)\n",
	       val[0], val[0], val[1], val[1],
	       val[2], val[2], val[3], val[3]);
#endif

	for (i = 0; i < MAX_CH-1; i++) {
		int raw, norm;
		raw = __raw_readl(d->base + HW_LRADC_CHn(d->chan[i])) &
			BM_LRADC_CHn_VALUE;
		norm = (raw * TARGET_VDDIO_LRADC_VALUE) / vddio;

		key = mxskbd_decode_button(d->keycodes +
					   d->keycodes_offset*i, norm);
		key = unjitter_key(i, key);

#ifdef DUMP_KEY_ADC
		val[i] = raw;
#endif
		if (key >= 0) {
			if (key == d->last_button)
				goto _end;

			if (f_key < 0)
				f_key = key;
		}
	}

	key = volume_key_process(d);
	if (key > 0) {
		if (key == d->last_button)
			goto _end;

		if (f_key < 0)
			f_key = key;
	}

	if (d->last_button >= 0) {
		input_report_key(GET_INPUT_DEV(d), d->last_button, 0);
		d->last_button = -1;
	}

	if (f_key >= 0 && f_key != d->last_button) {
		input_report_key(GET_INPUT_DEV(d), f_key, !0);
#ifdef ENABLE_BACKLIGHT_GPIO_CONTROL
		_keypad_set_backlight(1);
#endif
#ifdef CONFIG_HAS_WAKELOCK
		wake_lock_timeout(&key_wake_lock, 5*HZ);
#endif
		d->last_button = f_key;
	}

_end:
	__raw_writel((BM_LRADC_CTRL1_LRADC0_IRQ << d->chan[0]) +
		     (BM_LRADC_CTRL1_LRADC0_IRQ << d->chan[1]) +
		     (BM_LRADC_CTRL1_LRADC0_IRQ << d->chan[2]) +
		     (BM_LRADC_CTRL1_LRADC0_IRQ << d->chan[3]) +
		     (BM_LRADC_CTRL1_LRADC0_IRQ << VDDIO_VOLTAGE_CH),
		     d->base + HW_LRADC_CTRL1_CLR);
	return IRQ_HANDLED;
}