[media] rtl2832u: restore ir remote control support

Hi,
This patch uses the driver from openpli[1] as a template to restore the remote control support.
I had to divert from the original to use the in kernel rc protocol decoder. The key repetition does,
not seem to work but I cant find the problem in the driver. As a raw rc provider, no key table is
hardcoded.
Rodrigo.
[1]: https://aur.archlinux.org/packages/dvb-usb-rtl2832u-openpli/?comments=all

Signed-off-by: Rodrigo Tartajo <rtarty@gmail.com>
Signed-off-by: Antti Palosaari <crope@iki.fi>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Rodrigo Tartajo 2013-04-20 20:02:12 -03:00 committed by Mauro Carvalho Chehab
parent 1bddf1b3ac
commit 1e41413f98
3 changed files with 83 additions and 13 deletions

View File

@ -140,7 +140,7 @@ struct dvb_usb_rc {
int (*change_protocol)(struct rc_dev *dev, u64 *rc_type); int (*change_protocol)(struct rc_dev *dev, u64 *rc_type);
int (*query) (struct dvb_usb_device *d); int (*query) (struct dvb_usb_device *d);
unsigned int interval; unsigned int interval;
const enum rc_driver_type driver_type; enum rc_driver_type driver_type;
bool bulk_mode; bool bulk_mode;
}; };

View File

@ -1249,11 +1249,21 @@ static int rtl2831u_get_rc_config(struct dvb_usb_device *d,
#if IS_ENABLED(CONFIG_RC_CORE) #if IS_ENABLED(CONFIG_RC_CORE)
static int rtl2832u_rc_query(struct dvb_usb_device *d) static int rtl2832u_rc_query(struct dvb_usb_device *d)
{ {
#define TICSAT38KHZTONS(x) ((x) * (1000000000/38000))
int ret, i; int ret, i;
struct rtl28xxu_priv *priv = d->priv; struct rtl28xxu_priv *priv = d->priv;
u8 buf[128]; u8 buf[128];
int len; 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_CTRL, 0x20 },
{ IR_RX_BUF_CTRL, 0x80 }, { IR_RX_BUF_CTRL, 0x80 },
{ IR_RX_IF, 0xff }, { IR_RX_IF, 0xff },
@ -1268,13 +1278,40 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d)
{ IR_MAX_H_TOL_LEN, 0x1e }, { IR_MAX_H_TOL_LEN, 0x1e },
{ IR_MAX_L_TOL_LEN, 0x1e }, { IR_MAX_L_TOL_LEN, 0x1e },
{ IR_RX_CTRL, 0x80 }, { 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 */ /* init remote controller */
if (!priv->rc_active) { if (!priv->rc_active) {
for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) { for (i = 0; i < ARRAY_SIZE(rc_sys_init_tab); i++) {
ret = rtl28xx_wr_reg(d, rc_nec_tab[i].reg, ret = rtl28xx_rd_reg(d, rc_sys_init_tab[i].reg, &buf[0]);
rc_nec_tab[i].val); 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) if (ret)
goto err; goto err;
} }
@ -1286,7 +1323,7 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d)
goto err; goto err;
if (buf[0] != 0x83) if (buf[0] != 0x83)
goto exit; goto err;
ret = rtl28xx_rd_reg(d, IR_RX_BC, &buf[0]); ret = rtl28xx_rd_reg(d, IR_RX_BC, &buf[0]);
if (ret) if (ret)
@ -1295,26 +1332,48 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d)
len = buf[0]; len = buf[0];
ret = rtl2831_rd_regs(d, IR_RX_BUF, buf, len); 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); for (i = 0; i < ARRAY_SIZE(rc_clear_tab); i++) {
ret = rtl28xx_wr_reg(d, IR_RX_BUF_CTRL, 0x80); ret = rtl28xx_wr_reg(d, rc_clear_tab[i].reg,
ret = rtl28xx_wr_reg(d, IR_RX_CTRL, 0x80); rc_clear_tab[i].val);
if (ret)
goto err;
}
exit:
return ret; return ret;
err: 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); dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
return ret; return ret;
#undef TICSAT38KHZTONS
} }
static int rtl2832u_get_rc_config(struct dvb_usb_device *d, static int rtl2832u_get_rc_config(struct dvb_usb_device *d,
struct dvb_usb_rc *rc) struct dvb_usb_rc *rc)
{ {
rc->map_name = RC_MAP_EMPTY; rc->map_name = RC_MAP_EMPTY;
rc->allowed_protos = RC_BIT_NEC; rc->allowed_protos = RC_BIT_ALL;
rc->query = rtl2832u_rc_query; rc->query = rtl2832u_rc_query;
rc->interval = 400; rc->interval = 400;
rc->driver_type = RC_DRIVER_IR_RAW;
return 0; return 0;
} }

View File

@ -97,6 +97,17 @@ struct rtl28xxu_reg_val {
u8 val; u8 val;
}; };
enum OP{
OP_AND =0,
OP_OR
};
struct rtl28xxu_xreg_val {
u16 reg;
u8 op;
u8 mask;
};
/* /*
* memory map * memory map
* *