Exemplo n.º 1
0
Arquivo: ir-raw.c Projeto: 7799/linux
/**
 * ir_raw_event_store_with_filter() - pass next pulse/space to decoders with some processing
 * @dev:	the struct rc_dev device descriptor
 * @type:	the type of the event that has occurred
 *
 * This routine (which may be called from an interrupt context) works
 * in similar manner to ir_raw_event_store_edge.
 * This routine is intended for devices with limited internal buffer
 * It automerges samples of same type, and handles timeouts. Returns non-zero
 * if the event was added, and zero if the event was ignored due to idle
 * processing.
 */
int ir_raw_event_store_with_filter(struct rc_dev *dev, struct ir_raw_event *ev)
{
	if (!dev->raw)
		return -EINVAL;

	/* Ignore spaces in idle mode */
	if (dev->idle && !ev->pulse)
		return 0;
	else if (dev->idle)
		ir_raw_event_set_idle(dev, false);

	if (!dev->raw->this_ev.duration)
		dev->raw->this_ev = *ev;
	else if (ev->pulse == dev->raw->this_ev.pulse)
		dev->raw->this_ev.duration += ev->duration;
	else {
		ir_raw_event_store(dev, &dev->raw->this_ev);
		dev->raw->this_ev = *ev;
	}

	/* Enter idle mode if nessesary */
	if (!ev->pulse && dev->timeout &&
	    dev->raw->this_ev.duration >= dev->timeout)
		ir_raw_event_set_idle(dev, true);

	return 1;
}
Exemplo n.º 2
0
/**
 * ir_raw_event_store_with_filter() - pass next pulse/space to decoders with some processing
 * @input_dev:	the struct input_dev device descriptor
 * @type:	the type of the event that has occurred
 *
 * This routine (which may be called from an interrupt context) works
 * in similiar manner to ir_raw_event_store_edge.
 * This routine is intended for devices with limited internal buffer
 * It automerges samples of same type, and handles timeouts
 */
int ir_raw_event_store_with_filter(struct input_dev *input_dev,
						struct ir_raw_event *ev)
{
	struct ir_input_dev *ir = input_get_drvdata(input_dev);
	struct ir_raw_event_ctrl *raw = ir->raw;

	if (!raw || !ir->props)
		return -EINVAL;

	/* Ignore spaces in idle mode */
	if (ir->idle && !ev->pulse)
		return 0;
	else if (ir->idle)
		ir_raw_event_set_idle(input_dev, 0);

	if (!raw->this_ev.duration) {
		raw->this_ev = *ev;
	} else if (ev->pulse == raw->this_ev.pulse) {
		raw->this_ev.duration += ev->duration;
	} else {
		ir_raw_event_store(input_dev, &raw->this_ev);
		raw->this_ev = *ev;
	}

	/* Enter idle mode if nessesary */
	if (!ev->pulse && ir->props->timeout &&
		raw->this_ev.duration >= ir->props->timeout)
		ir_raw_event_set_idle(input_dev, 1);
	return 0;
}
Exemplo n.º 3
0
static irqreturn_t sunxi_ir_irq(int irqno, void *dev_id)
{
    unsigned long status;
    unsigned char dt;
    unsigned int cnt, rc;
    struct sunxi_ir *ir = dev_id;
    DEFINE_IR_RAW_EVENT(rawir);

    spin_lock(&ir->ir_lock);

    status = readl(ir->base + SUNXI_IR_RXSTA_REG);

    /* clean all pending statuses */
    writel(status | REG_RXSTA_CLEARALL, ir->base + SUNXI_IR_RXSTA_REG);

    if (status & (REG_RXINT_RAI_EN | REG_RXINT_RPEI_EN)) {
        /* How many messages in fifo */
        rc  = REG_RXSTA_GET_AC(status);
        /* Sanity check */
        rc = rc > ir->fifo_size ? ir->fifo_size : rc;
        /* If we have data */
        for (cnt = 0; cnt < rc; cnt++) {
            /* for each bit in fifo */
            dt = readb(ir->base + SUNXI_IR_RXFIFO_REG);
            rawir.pulse = (dt & 0x80) != 0;
            rawir.duration = ((dt & 0x7f) + 1) * SUNXI_IR_SAMPLE;
            ir_raw_event_store_with_filter(ir->rc, &rawir);
        }
    }

    if (status & REG_RXINT_ROI_EN) {
        ir_raw_event_reset(ir->rc);
    } else if (status & REG_RXINT_RPEI_EN) {
        ir_raw_event_set_idle(ir->rc, true);
        ir_raw_event_handle(ir->rc);
    }

    spin_unlock(&ir->ir_lock);

    return IRQ_HANDLED;
}
Exemplo n.º 4
0
static int rtl2832u_rc_query(struct dvb_usb_device *d)
{
	int ret, i, len;
	struct rtl28xxu_priv *priv = d->priv;
	struct ir_raw_event ev;
	u8 buf[128];
	static const struct rtl28xxu_reg_val_mask refresh_tab[] = {
		{IR_RX_IF,               0x03, 0xff},
		{IR_RX_BUF_CTRL,         0x80, 0xff},
		{IR_RX_CTRL,             0x80, 0xff},
	};

	/* init remote controller */
	if (!priv->rc_active) {
		static const struct rtl28xxu_reg_val_mask init_tab[] = {
			{SYS_DEMOD_CTL1,         0x00, 0x04},
			{SYS_DEMOD_CTL1,         0x00, 0x08},
			{USB_CTRL,               0x20, 0x20},
			{SYS_GPIO_DIR,           0x00, 0x08},
			{SYS_GPIO_OUT_EN,        0x08, 0x08},
			{SYS_GPIO_OUT_VAL,       0x08, 0x08},
			{IR_MAX_DURATION0,       0xd0, 0xff},
			{IR_MAX_DURATION1,       0x07, 0xff},
			{IR_IDLE_LEN0,           0xc0, 0xff},
			{IR_IDLE_LEN1,           0x00, 0xff},
			{IR_GLITCH_LEN,          0x03, 0xff},
			{IR_RX_CLK,              0x09, 0xff},
			{IR_RX_CFG,              0x1c, 0xff},
			{IR_MAX_H_TOL_LEN,       0x1e, 0xff},
			{IR_MAX_L_TOL_LEN,       0x1e, 0xff},
			{IR_RX_CTRL,             0x80, 0xff},
		};

		for (i = 0; i < ARRAY_SIZE(init_tab); i++) {
			ret = rtl28xx_wr_reg_mask(d, init_tab[i].reg,
					init_tab[i].val, init_tab[i].mask);
			if (ret)
				goto err;
		}

		priv->rc_active = true;
	}

	ret = rtl28xx_rd_reg(d, IR_RX_IF, &buf[0]);
	if (ret)
		goto err;

	if (buf[0] != 0x83)
		goto exit;

	ret = rtl28xx_rd_reg(d, IR_RX_BC, &buf[0]);
	if (ret)
		goto err;

	len = buf[0];

	/* read raw code from hw */
	ret = rtl2831_rd_regs(d, IR_RX_BUF, buf, len);
	if (ret)
		goto err;

	/* let hw receive new code */
	for (i = 0; i < ARRAY_SIZE(refresh_tab); i++) {
		ret = rtl28xx_wr_reg_mask(d, refresh_tab[i].reg,
				refresh_tab[i].val, refresh_tab[i].mask);
		if (ret)
			goto err;
	}

	/* pass data to Kernel IR decoder */
	init_ir_raw_event(&ev);

	for (i = 0; i < len; i++) {
		ev.pulse = buf[i] >> 7;
		ev.duration = 50800 * (buf[i] & 0x7f);
		ir_raw_event_store_with_filter(d->rc_dev, &ev);
	}

	/* 'flush' ir_raw_event_store_with_filter() */
	ir_raw_event_set_idle(d->rc_dev, true);
	ir_raw_event_handle(d->rc_dev);
exit:
	return ret;
err:
	dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
	return ret;
}