示例#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;
}
示例#2
0
static int __devexit mxskbd_remove(struct platform_device *pdev)
{
	int i;
	struct mxskbd_data *d = platform_get_drvdata(pdev);

#ifdef CONFIG_HAS_WAKELOCK
	wake_lock_destroy(&key_wake_lock);
#endif

	for (i = 0; i < MAX_CH; i++)
		hw_lradc_unuse_channel(d->chan[i]);

	input_unregister_device(GET_INPUT_DEV(d));
	if (d->btn_irq1 > 0)
		free_irq(d->btn_irq1, pdev);
	mxskbd_data_free(d);

	platform_set_drvdata(pdev, NULL);

#ifdef ENABLE_BACKLIGHT_GPIO_CONTROL
	_keypad_set_backlight(0);
#endif

	return 0;
}
示例#3
0
static void jack_process(struct mxskbd_data *d)
{
	int pin;
	int in;
	int jack;
	static int amp_on_cnt;
	static int amp;

	pin = !!mxs_audio_jack_gpio_get();
	if (pin)
		amp_on_cnt = 10;
	else if (amp_on_cnt > 0)
		amp_on_cnt--;

	if (amp_on_cnt > 0) {
		if (!amp) {
			mxs_audio_headset_mic_detect_amp_gpio_set(1);
			amp = 1;
		}
	} else {
		if (amp) {
			mxs_audio_headset_mic_detect_amp_gpio_set(0);
			amp = 0;
		}
	}

	if (!!d->jack_last == pin) {
		d->jack_cnt = 0;
		return;
	}

	if (++d->jack_cnt <= 6)
		return;

	if (pin == 0) {		/* eject */
		in = 0;
		jack = d->jack_last;
		d->jack_last = 0;
	} else {		/* insert */
		int i = __raw_readl(d->base + HW_LRADC_CHn(d->chan[MAX_CH-1])) &
			BM_LRADC_CHn_VALUE;

		d->jack_last = (i > MIC_DET_THRESHOLD) ?
			SW_MICROPHONE_INSERT : SW_HEADPHONE_INSERT;

		in = 1;
		jack = d->jack_last;
	}
	input_report_switch(GET_INPUT_DEV(d), jack, in);
}
示例#4
0
static int __devexit mxskbd_remove(struct platform_device *pdev)
{
	struct mxskbd_data *d = platform_get_drvdata(pdev);

	hw_lradc_unuse_channel(d->chan);
	input_unregister_device(GET_INPUT_DEV(d));
	free_irq(d->irq, pdev);
	if (d->btn_irq > 0)
		free_irq(d->btn_irq, pdev);
	mxskbd_data_free(d);

	platform_set_drvdata(pdev, NULL);

	return 0;
}
示例#5
0
static int __devinit mxskbd_probe(struct platform_device *pdev)
{
	int err = 0;
	struct resource *res;
	struct mxskbd_data *d;
	struct mxs_kbd_plat_data *plat_data;

	plat_data = (struct mxs_kbd_plat_data *)pdev->dev.platform_data;
	if (plat_data == NULL)
		return -ENODEV;

	/* Create and register the input driver. */
	d = mxskbd_data_alloc(pdev, plat_data->keypair);
	if (!d) {
		dev_err(&pdev->dev, "Cannot allocate driver structures\n");
		err = -ENOMEM;
		goto err_out;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		err = -ENODEV;
		goto err_out;
	}
	d->base = (unsigned int)IO_ADDRESS(res->start);
	d->chan = plat_data->channel;
	d->irq = platform_get_irq(pdev, 0);
	d->btn_irq = platform_get_irq(pdev, 1);
	d->btn_enable = plat_data->btn_enable;
	d->btn_irq_stat = plat_data->btn_irq_stat;
	d->btn_irq_ctrl = plat_data->btn_irq_ctrl;

	platform_set_drvdata(pdev, d);

	err = request_irq(d->irq, mxskbd_irq_handler,
			  IRQF_DISABLED, pdev->name, pdev);
	if (err) {
		dev_err(&pdev->dev, "Cannot request keypad IRQ\n");
		goto err_free_dev;
	}

	if (d->btn_irq > 0) {
		err = request_irq(d->btn_irq, mxskbd_irq_handler,
			  IRQF_DISABLED, pdev->name, pdev);
		if (err) {
			dev_err(&pdev->dev,
				"Cannot request keybad detect IRQ\n");
			goto err_free_irq;
		}
	}

	/* Register the input device */
	err = input_register_device(GET_INPUT_DEV(d));
	if (err)
		goto err_free_irq2;

	/* these two have to be set after registering the input device */
	d->input->rep[REP_DELAY] = delay1;
	d->input->rep[REP_PERIOD] = delay2;

	hw_lradc_use_channel(d->chan);
	mxskbd_hwinit(pdev);

	return 0;

err_free_irq2:
	platform_set_drvdata(pdev, NULL);
	if (d->btn_irq > 0)
		free_irq(d->btn_irq, pdev);
err_free_irq:
	free_irq(d->irq, pdev);
err_free_dev:
	mxskbd_data_free(d);
err_out:
	return err;
}
示例#6
0
static int __devinit mxskbd_probe(struct platform_device *pdev)
{
	int i;
	int err = 0;
	struct resource *res;
	struct mxskbd_data *d;
	struct mxs_kbd_plat_data *plat_data;

	plat_data = (struct mxs_kbd_plat_data *)pdev->dev.platform_data;
	if (plat_data == NULL)
		return -ENODEV;

#ifdef CONFIG_HAS_WAKELOCK
	wake_lock_init(&key_wake_lock, WAKE_LOCK_SUSPEND, "mxs-keypad");
#endif

	/* Create and register the input driver. */
	d = mxskbd_data_alloc(pdev, plat_data->keypair,
			plat_data->keypair_offset);
	if (!d) {
		dev_err(&pdev->dev, "Cannot allocate driver structures\n");
		err = -ENOMEM;
		goto err_out;
	}

	_devdata = d;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		err = -ENODEV;
		goto err_out;
	}
	d->base = (unsigned int)IO_ADDRESS(res->start);
	for (i = 0; i < MAX_CH; i++)
		d->chan[i] = plat_data->channel[i];
	d->btn_irq1 = platform_get_irq(pdev, 0);

	platform_set_drvdata(pdev, d);

	if (d->btn_irq1 > 0) {
		err = request_irq(d->btn_irq1, mxskbd_irq_handler,
				IRQF_DISABLED, pdev->name, pdev);
		if (err) {
			dev_err(&pdev->dev, "Cannot request keypad IRQ\n");
			goto err_free_dev;
		}
	}

	/* Register the input device */
	err = input_register_device(GET_INPUT_DEV(d));
	if (err)
		goto err_free_dev;

	/* these two have to be set after registering the input device */
	d->input->rep[REP_DELAY] = delay1;
	d->input->rep[REP_PERIOD] = delay2;

	for (i = 0; i < MAX_CH; i++)
		hw_lradc_use_channel(d->chan[i]);
	mxskbd_hwinit(pdev);

#ifdef ENABLE_BACKLIGHT_GPIO_CONTROL
	init_timer(&_bl_timer);
	_bl_timer.function = _keypad_bl_timer_handler;
#endif

	return 0;

err_free_dev:
	if (d->btn_irq1 > 0)
		free_irq(d->btn_irq1, pdev);

	mxskbd_data_free(d);
err_out:
#ifdef CONFIG_HAS_WAKELOCK
		wake_lock_destroy(&key_wake_lock);
#endif
	return err;
}
示例#7
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;
}