From f39fac3e409322d23261e89374a7d9daecfd6acb Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 4 Jun 2013 09:17:03 -0300 Subject: [media] rtl28xxu: reimplement rtl2832u remote controller Thanks to Rodrigo for original implementation! Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index e592662..4167011 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -1114,17 +1114,6 @@ static int rtl2832u_power_ctrl(struct dvb_usb_device *d, int onoff) if (ret) goto err; } else { - /* demod_ctl_1 */ - ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL1, &val); - if (ret) - goto err; - - val |= 0x0c; - - ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL1, val); - if (ret) - goto err; - /* set output values */ ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &val); if (ret) @@ -1249,72 +1238,44 @@ static int rtl2831u_get_rc_config(struct dvb_usb_device *d, #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; + int ret, i, len; struct rtl28xxu_priv *priv = d->priv; + struct ir_raw_event ev; u8 buf[128]; - int len; - 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_RX_IE, 0xff }, - { IR_MAX_DURATION0, 0xd0 }, - { IR_MAX_DURATION1, 0x07 }, - { IR_IDLE_LEN0, 0xc0 }, - { IR_IDLE_LEN1, 0x00 }, - { IR_GLITCH_LEN, 0x03 }, - { IR_RX_CLK, 0x09 }, - { IR_RX_CFG, 0x1c }, - { 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 + 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) { - 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); + 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; } @@ -1323,57 +1284,56 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d) goto err; if (buf[0] != 0x83) - goto err; + goto exit; ret = rtl28xx_rd_reg(d, IR_RX_BC, &buf[0]); if (ret) goto err; len = buf[0]; - ret = rtl2831_rd_regs(d, IR_RX_BUF, buf, len); - /* 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); + /* read raw code from hw */ + ret = rtl2831_rd_regs(d, IR_RX_BUF, buf, len); + if (ret) + goto err; - 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); + /* 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: - 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; + /* load empty to enable rc */ + if (!rc->map_name) + rc->map_name = RC_MAP_EMPTY; rc->allowed_protos = RC_BIT_ALL; + rc->driver_type = RC_DRIVER_IR_RAW; rc->query = rtl2832u_rc_query; rc->interval = 400; - rc->driver_type = RC_DRIVER_IR_RAW; return 0; } diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h index 0177b38..729b354 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h @@ -97,14 +97,9 @@ struct rtl28xxu_reg_val { u8 val; }; -enum OP{ - OP_AND =0, - OP_OR -}; - -struct rtl28xxu_xreg_val { +struct rtl28xxu_reg_val_mask { u16 reg; - u8 op; + u8 val; u8 mask; }; -- cgit v0.10.2