All of lore.kernel.org
 help / color / mirror / Atom feed
From: Rodrigo Tartajo <rtarty@gmail.com>
To: linux-media@vger.kernel.org
Subject: [PATCH] [media] rtl2832u: restore ir remote control support.
Date: Sun, 21 Apr 2013 02:02:12 +0200	[thread overview]
Message-ID: <51732C84.1080806@gmail.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 5737 bytes --]

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>
---
 drivers/media/usb/dvb-usb-v2/dvb_usb.h  |  2 +-
 drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 83 ++++++++++++++++++++++++++++-----
 drivers/media/usb/dvb-usb-v2/rtl28xxu.h | 11 +++++
 3 files changed, 83 insertions(+), 13 deletions(-)

diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb.h b/drivers/media/usb/dvb-usb-v2/dvb_usb.h
index 658c6d4..399916b 100644
--- a/drivers/media/usb/dvb-usb-v2/dvb_usb.h
+++ b/drivers/media/usb/dvb-usb-v2/dvb_usb.h
@@ -140,7 +140,7 @@ struct dvb_usb_rc {
 	int (*change_protocol)(struct rc_dev *dev, u64 *rc_type);
 	int (*query) (struct dvb_usb_device *d);
 	unsigned int interval;
-	const enum rc_driver_type driver_type;
+	enum rc_driver_type driver_type;
 	bool bulk_mode;
 };
 
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index 3d128a5..f74bff2 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -1215,11 +1215,21 @@ 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;
 	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 },
@@ -1234,13 +1244,40 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d)
 		{ 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;
 		}
@@ -1252,7 +1289,7 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d)
 		goto err;
 
 	if (buf[0] != 0x83)
-		goto exit;
+		goto err;
 
 	ret = rtl28xx_rd_reg(d, IR_RX_BC, &buf[0]);
 	if (ret)
@@ -1261,26 +1298,48 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d)
 	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;
 }
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
index 2f3af2d..ac2c2d6 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
@@ -96,6 +96,17 @@ struct rtl28xxu_reg_val {
 	u8 val;
 };
 
+enum OP{
+	OP_AND	=0,
+	OP_OR
+};
+
+struct rtl28xxu_xreg_val {
+	u16 reg;
+	u8 op;
+	u8 mask;
+};
+
 /*
  * memory map
  *
-- 
1.8.1.5


[-- Attachment #2: Parte del mensaje adjunto --]
[-- Type: text/plain, Size: 0 bytes --]



                 reply	other threads:[~2013-04-21  0:02 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=51732C84.1080806@gmail.com \
    --to=rtarty@gmail.com \
    --cc=linux-media@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.