Пример #1
0
/*
 * Tasklet handler
 */
static void retu_tasklet_handler(unsigned long data)
{
	struct retu_irq_handler_desc *hnd;
	u16 id;
	u16 im;
	int i;

	for (;;) {
		id = retu_read_reg(RETU_REG_IDR);
		im = ~retu_read_reg(RETU_REG_IMR);
		id &= im;

		if (!id)
			break;

		for (i = 0; id != 0; i++, id >>= 1) {
			if (!(id & 1))
				continue;
			hnd = &retu_irq_handlers[i];
			if (hnd->func == NULL) {
                               /* Spurious retu interrupt - disable and ack it */
				printk(KERN_INFO "Spurious Retu interrupt "
						 "(id %d)\n", i);
				retu_disable_irq(i);
				retu_ack_irq(i);
				continue;
			}
			hnd->func(hnd->arg);
			/*
			 * Don't acknowledge the interrupt here
			 * It must be done explicitly
			 */
		}
	}
}
Пример #2
0
/*
 * Unregister the handler for a given RETU interrupt source.
 */
void retu_free_irq(int id)
{
	struct retu_irq_handler_desc *hnd;

	if (id >= MAX_RETU_IRQ_HANDLERS) {
		printk(KERN_ERR PFX "Invalid argument to %s\n",
		       __FUNCTION__);
		return;
	}
	hnd = &retu_irq_handlers[id];
	if (hnd->func == NULL) {
		printk(KERN_ERR PFX "IRQ %d already freed\n", id);
		return;
	}

	retu_disable_irq(id);
	hnd->func = NULL;
}
Пример #3
0
static void retu_headset_det_disable(struct retu_headset *hs)
{
	unsigned long flags;

	mutex_lock(&hs->mutex);
	if (hs->detection_enabled) {
		hs->detection_enabled = 0;
		retu_disable_irq(RETU_INT_HOOK);
		del_timer_sync(&hs->enable_timer);
		del_timer_sync(&hs->detect_timer);
		spin_lock_irqsave(&hs->lock, flags);
		if (hs->pressed)
			input_report_key(hs->idev, RETU_HEADSET_KEY, 0);
		spin_unlock_irqrestore(&hs->lock, flags);
		retu_set_clear_reg_bits(RETU_REG_CC1, 0, (1 << 10) | (1 << 8));
	}
	mutex_unlock(&hs->mutex);
}
Пример #4
0
static int __init retu_headset_probe(struct platform_device *pdev)
{
	struct retu_headset *hs;
	int r;

	hs = kzalloc(sizeof(*hs), GFP_KERNEL);
	if (hs == NULL)
		return -ENOMEM;

	hs->pdev = pdev;

	hs->idev = input_allocate_device();
	if (hs->idev == NULL) {
		r = -ENOMEM;
		goto err1;
	}
	hs->idev->name = "retu-headset";
	hs->idev->dev.parent = &pdev->dev;
	set_bit(EV_KEY, hs->idev->evbit);
	set_bit(RETU_HEADSET_KEY, hs->idev->keybit);
	r = input_register_device(hs->idev);
	if (r < 0)
		goto err2;

	r = device_create_file(&pdev->dev, &dev_attr_hookdet);
	if (r < 0)
		goto err3;
	r = device_create_file(&pdev->dev, &dev_attr_enable);
	if (r < 0)
		goto err4;
	r = device_create_file(&pdev->dev, &dev_attr_enable_det);
	if (r < 0)
		goto err5;
	platform_set_drvdata(pdev, hs);

	spin_lock_init(&hs->lock);
	mutex_init(&hs->mutex);
	setup_timer(&hs->enable_timer, retu_headset_enable_timer,
		    (unsigned long) hs);
	setup_timer(&hs->detect_timer, retu_headset_detect_timer,
		    (unsigned long) hs);

	r = retu_request_irq(RETU_INT_HOOK, retu_headset_hook_interrupt,
			     (unsigned long) hs, "hookdet");
	if (r != 0) {
		dev_err(&pdev->dev, "hookdet IRQ not available\n");
		goto err6;
	}
	retu_disable_irq(RETU_INT_HOOK);
	return 0;
err6:
	device_remove_file(&pdev->dev, &dev_attr_enable_det);
err5:
	device_remove_file(&pdev->dev, &dev_attr_enable);
err4:
	device_remove_file(&pdev->dev, &dev_attr_hookdet);
err3:
	input_unregister_device(hs->idev);
err2:
	input_free_device(hs->idev);
err1:
	kfree(hs);
	return r;
}