#if IS_ENABLED(CONFIG_RC_CORE)
static int rtl2832u_rc_query(struct dvb_usb_device *d)
{
+#define TICSAT38KHZTONS(x) ((x) * (1000000000/38000))
int ret, i;
struct rtl28xxu_priv *priv = d->priv;
u8 buf[128];
int len;
- struct rtl28xxu_reg_val rc_nec_tab[] = {
+ struct ir_raw_event ev; //encode single ir event (pulse or space)
+ struct rtl28xxu_xreg_val rc_sys_init_tab[] = {
+ { SYS_DEMOD_CTL1, OP_AND, 0xfb },
+ { SYS_DEMOD_CTL1, OP_AND, 0xf7 },
+ { USB_CTRL, OP_OR , 0x20 },
+ { SYS_SYS1, OP_AND, 0xf7 },
+ { SYS_GPIO_OUT_EN, OP_OR , 0x08 },
+ { SYS_GPIO_OUT_VAL, OP_OR , 0x08 },
+ }; // system hard init
+ struct rtl28xxu_reg_val rc_init_tab[] = {
{ IR_RX_CTRL, 0x20 },
{ IR_RX_BUF_CTRL, 0x80 },
{ IR_RX_IF, 0xff },
{ IR_MAX_H_TOL_LEN, 0x1e },
{ IR_MAX_L_TOL_LEN, 0x1e },
{ IR_RX_CTRL, 0x80 },
- };
+ }; // hard init
+ struct rtl28xxu_reg_val rc_reinit_tab[] = {
+ { IR_RX_CTRL, 0x20 },
+ { IR_RX_BUF_CTRL, 0x80 },
+ { IR_RX_IF, 0xff },
+ { IR_RX_IE, 0xff },
+ { IR_RX_CTRL, 0x80 },
+ }; // reinit IR
+ struct rtl28xxu_reg_val rc_clear_tab[] = {
+ { IR_RX_IF, 0x03 },
+ { IR_RX_BUF_CTRL, 0x80 },
+ { IR_RX_CTRL, 0x80 },
+ }; // clear reception
/* init remote controller */
if (!priv->rc_active) {
- for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) {
- ret = rtl28xx_wr_reg(d, rc_nec_tab[i].reg,
- rc_nec_tab[i].val);
+ for (i = 0; i < ARRAY_SIZE(rc_sys_init_tab); i++) {
+ ret = rtl28xx_rd_reg(d, rc_sys_init_tab[i].reg, &buf[0]);
+ if (ret)
+ goto err;
+ if (rc_sys_init_tab[i].op == OP_AND) {
+ buf[0] &= rc_sys_init_tab[i].mask;
+ }
+ else {//OP_OR
+ buf[0] |= rc_sys_init_tab[i].mask;
+ }
+ ret = rtl28xx_wr_reg(d, rc_sys_init_tab[i].reg,
+ buf[0]);
+ if (ret)
+ goto err;
+ }
+ for (i = 0; i < ARRAY_SIZE(rc_init_tab); i++) {
+ ret = rtl28xx_wr_reg(d, rc_init_tab[i].reg,
+ rc_init_tab[i].val);
if (ret)
goto err;
}
goto err;
if (buf[0] != 0x83)
- goto exit;
+ goto err;
ret = rtl28xx_rd_reg(d, IR_RX_BC, &buf[0]);
if (ret)
len = buf[0];
ret = rtl2831_rd_regs(d, IR_RX_BUF, buf, len);
- /* TODO: pass raw IR to Kernel IR decoder */
+ /* pass raw IR to Kernel IR decoder */
+ init_ir_raw_event(&ev);
+ ir_raw_event_reset(d->rc_dev);
+ ev.pulse=1;
+ for(i=0; true; ++i) { // conver count to time
+ if (i >= len || !(buf[i] & 0x80) != !(ev.pulse)) {//end or transition pulse/space: flush
+ ir_raw_event_store(d->rc_dev, &ev);
+ ev.duration = 0;
+ }
+ if (i >= len)
+ break;
+ ev.pulse = buf[i] >> 7;
+ ev.duration += TICSAT38KHZTONS(((u32)(buf[i] & 0x7F)) << 1);
+ }
+ ir_raw_event_handle(d->rc_dev);
- ret = rtl28xx_wr_reg(d, IR_RX_IF, 0x03);
- ret = rtl28xx_wr_reg(d, IR_RX_BUF_CTRL, 0x80);
- ret = rtl28xx_wr_reg(d, IR_RX_CTRL, 0x80);
+ for (i = 0; i < ARRAY_SIZE(rc_clear_tab); i++) {
+ ret = rtl28xx_wr_reg(d, rc_clear_tab[i].reg,
+ rc_clear_tab[i].val);
+ if (ret)
+ goto err;
+ }
-exit:
return ret;
err:
+ for (i = 0; i < ARRAY_SIZE(rc_reinit_tab); i++) {
+ ret = rtl28xx_wr_reg(d, rc_reinit_tab[i].reg,
+ rc_reinit_tab[i].val);
+ }
dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
return ret;
+#undef TICSAT38KHZTONS
}
static int rtl2832u_get_rc_config(struct dvb_usb_device *d,
struct dvb_usb_rc *rc)
{
rc->map_name = RC_MAP_EMPTY;
- rc->allowed_protos = RC_BIT_NEC;
+ rc->allowed_protos = RC_BIT_ALL;
rc->query = rtl2832u_rc_query;
rc->interval = 400;
+ rc->driver_type = RC_DRIVER_IR_RAW;
return 0;
}