/** * 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; }
/** * 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; }
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; }
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; }