summaryrefslogtreecommitdiff
path: root/drivers/media/i2c/ir-kbd-i2c.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/i2c/ir-kbd-i2c.c')
-rw-r--r--drivers/media/i2c/ir-kbd-i2c.c813
1 files changed, 659 insertions, 154 deletions
diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c
index 82bf5679da30..5588cdd7ec20 100644
--- a/drivers/media/i2c/ir-kbd-i2c.c
+++ b/drivers/media/i2c/ir-kbd-i2c.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
*
* keyboard input driver for i2c IR remote controls
@@ -18,23 +19,23 @@
* Brian Rogers <brian_rogers@comcast.net>
* modified for AVerMedia Cardbus by
* Oldrich Jedlicka <oldium.pro@seznam.cz>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
+ * Zilog Transmitter portions/ideas were derived from GPLv2+ sources:
+ * - drivers/char/pctv_zilogir.[ch] from Hauppauge Broadway product
+ * Copyright 2011 Hauppauge Computer works
+ * - drivers/staging/media/lirc/lirc_zilog.c
+ * Copyright (c) 2000 Gerd Knorr <kraxel@goldbach.in-berlin.de>
+ * Michal Kochanowicz <mkochano@pld.org.pl>
+ * Christoph Bartelmus <lirc@bartelmus.de>
+ * Ulrich Mueller <ulrich.mueller42@web.de>
+ * Stefan Jahn <stefan@lkcc.org>
+ * Jerome Brock <jbrock@users.sourceforge.net>
+ * Thomas Reitmayr (treitmayr@yahoo.com)
+ * Mark Weaver <mark@npsl.co.uk>
+ * Jarod Wilson <jarod@redhat.com>
+ * Copyright (C) 2011 Andy Walls <awalls@md.metrocast.net>
*/
+#include <linux/unaligned.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
@@ -47,78 +48,96 @@
#include <linux/workqueue.h>
#include <media/rc-core.h>
-#include <media/ir-kbd-i2c.h>
-
-/* ----------------------------------------------------------------------- */
-/* insmod parameters */
-
-static int debug;
-module_param(debug, int, 0644); /* debug level (0,1,2) */
+#include <media/i2c/ir-kbd-i2c.h>
+#define FLAG_TX 1
+#define FLAG_HDPVR 2
-#define MODULE_NAME "ir-kbd-i2c"
-#define dprintk(level, fmt, arg...) if (debug >= level) \
- printk(KERN_DEBUG MODULE_NAME ": " fmt , ## arg)
+static bool enable_hdpvr;
+module_param(enable_hdpvr, bool, 0644);
-/* ----------------------------------------------------------------------- */
-
-static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
- int size, int offset)
+static int get_key_haup_common(struct IR_i2c *ir, enum rc_proto *protocol,
+ u32 *scancode, u8 *ptoggle, int size)
{
unsigned char buf[6];
- int start, range, toggle, dev, code, ircode;
+ int start, range, toggle, dev, code, ircode, vendor;
/* poll IR chip */
if (size != i2c_master_recv(ir->c, buf, size))
return -EIO;
- /* split rc5 data block ... */
- start = (buf[offset] >> 7) & 1;
- range = (buf[offset] >> 6) & 1;
- toggle = (buf[offset] >> 5) & 1;
- dev = buf[offset] & 0x1f;
- code = (buf[offset+1] >> 2) & 0x3f;
+ if (buf[0] & 0x80) {
+ int offset = (size == 6) ? 3 : 0;
- /* rc5 has two start bits
- * the first bit must be one
- * the second bit defines the command range (1 = 0-63, 0 = 64 - 127)
- */
- if (!start)
- /* no key pressed */
- return 0;
- /*
- * Hauppauge remotes (black/silver) always use
- * specific device ids. If we do not filter the
- * device ids then messages destined for devices
- * such as TVs (id=0) will get through causing
- * mis-fired events.
- *
- * We also filter out invalid key presses which
- * produce annoying debug log entries.
- */
- ircode= (start << 12) | (toggle << 11) | (dev << 6) | code;
- if ((ircode & 0x1fff)==0x1fff)
- /* invalid key press */
- return 0;
+ /* split rc5 data block ... */
+ start = (buf[offset] >> 7) & 1;
+ range = (buf[offset] >> 6) & 1;
+ toggle = (buf[offset] >> 5) & 1;
+ dev = buf[offset] & 0x1f;
+ code = (buf[offset+1] >> 2) & 0x3f;
- if (!range)
- code += 64;
+ /* rc5 has two start bits
+ * the first bit must be one
+ * the second bit defines the command range:
+ * 1 = 0-63, 0 = 64 - 127
+ */
+ if (!start)
+ /* no key pressed */
+ return 0;
- dprintk(1,"ir hauppauge (rc5): s%d r%d t%d dev=%d code=%d\n",
- start, range, toggle, dev, code);
+ /* filter out invalid key presses */
+ ircode = (start << 12) | (toggle << 11) | (dev << 6) | code;
+ if ((ircode & 0x1fff) == 0x1fff)
+ return 0;
- /* return key */
- *ir_key = (dev << 8) | code;
- *ir_raw = ircode;
- return 1;
+ if (!range)
+ code += 64;
+
+ dev_dbg(&ir->rc->dev,
+ "ir hauppauge (rc5): s%d r%d t%d dev=%d code=%d\n",
+ start, range, toggle, dev, code);
+
+ *protocol = RC_PROTO_RC5;
+ *scancode = RC_SCANCODE_RC5(dev, code);
+ *ptoggle = toggle;
+
+ return 1;
+ } else if (size == 6 && (buf[0] & 0x40)) {
+ code = buf[4];
+ dev = buf[3];
+ vendor = get_unaligned_be16(buf + 1);
+
+ if (vendor == 0x800f) {
+ *ptoggle = (dev & 0x80) != 0;
+ *protocol = RC_PROTO_RC6_MCE;
+ dev &= 0x7f;
+ dev_dbg(&ir->rc->dev,
+ "ir hauppauge (rc6-mce): t%d vendor=%d dev=%d code=%d\n",
+ *ptoggle, vendor, dev, code);
+ } else {
+ *ptoggle = 0;
+ *protocol = RC_PROTO_RC6_6A_32;
+ dev_dbg(&ir->rc->dev,
+ "ir hauppauge (rc6-6a-32): vendor=%d dev=%d code=%d\n",
+ vendor, dev, code);
+ }
+
+ *scancode = RC_SCANCODE_RC6_6A(vendor, dev, code);
+
+ return 1;
+ }
+
+ return 0;
}
-static int get_key_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_haup(struct IR_i2c *ir, enum rc_proto *protocol,
+ u32 *scancode, u8 *toggle)
{
- return get_key_haup_common (ir, ir_key, ir_raw, 3, 0);
+ return get_key_haup_common(ir, protocol, scancode, toggle, 3);
}
-static int get_key_haup_xvr(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_haup_xvr(struct IR_i2c *ir, enum rc_proto *protocol,
+ u32 *scancode, u8 *toggle)
{
int ret;
unsigned char buf[1] = { 0 };
@@ -133,54 +152,70 @@ static int get_key_haup_xvr(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
if (ret != 1)
return (ret < 0) ? ret : -EINVAL;
- return get_key_haup_common (ir, ir_key, ir_raw, 6, 3);
+ return get_key_haup_common(ir, protocol, scancode, toggle, 6);
}
-static int get_key_pixelview(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_pixelview(struct IR_i2c *ir, enum rc_proto *protocol,
+ u32 *scancode, u8 *toggle)
{
+ int rc;
unsigned char b;
/* poll IR chip */
- if (1 != i2c_master_recv(ir->c, &b, 1)) {
- dprintk(1,"read error\n");
+ rc = i2c_master_recv(ir->c, &b, 1);
+ if (rc != 1) {
+ dev_dbg(&ir->rc->dev, "read error\n");
+ if (rc < 0)
+ return rc;
return -EIO;
}
- *ir_key = b;
- *ir_raw = b;
+
+ *protocol = RC_PROTO_OTHER;
+ *scancode = b;
+ *toggle = 0;
return 1;
}
-static int get_key_fusionhdtv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_fusionhdtv(struct IR_i2c *ir, enum rc_proto *protocol,
+ u32 *scancode, u8 *toggle)
{
+ int rc;
unsigned char buf[4];
/* poll IR chip */
- if (4 != i2c_master_recv(ir->c, buf, 4)) {
- dprintk(1,"read error\n");
+ rc = i2c_master_recv(ir->c, buf, 4);
+ if (rc != 4) {
+ dev_dbg(&ir->rc->dev, "read error\n");
+ if (rc < 0)
+ return rc;
return -EIO;
}
- if(buf[0] !=0 || buf[1] !=0 || buf[2] !=0 || buf[3] != 0)
- dprintk(2, "%s: 0x%2x 0x%2x 0x%2x 0x%2x\n", __func__,
- buf[0], buf[1], buf[2], buf[3]);
+ if (buf[0] != 0 || buf[1] != 0 || buf[2] != 0 || buf[3] != 0)
+ dev_dbg(&ir->rc->dev, "%s: %*ph\n", __func__, 4, buf);
/* no key pressed or signal from other ir remote */
if(buf[0] != 0x1 || buf[1] != 0xfe)
return 0;
- *ir_key = buf[2];
- *ir_raw = (buf[2] << 8) | buf[3];
-
+ *protocol = RC_PROTO_UNKNOWN;
+ *scancode = buf[2];
+ *toggle = 0;
return 1;
}
-static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_knc1(struct IR_i2c *ir, enum rc_proto *protocol,
+ u32 *scancode, u8 *toggle)
{
+ int rc;
unsigned char b;
/* poll IR chip */
- if (1 != i2c_master_recv(ir->c, &b, 1)) {
- dprintk(1,"read error\n");
+ rc = i2c_master_recv(ir->c, &b, 1);
+ if (rc != 1) {
+ dev_dbg(&ir->rc->dev, "read error\n");
+ if (rc < 0)
+ return rc;
return -EIO;
}
@@ -188,7 +223,7 @@ static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
down, while 0xff indicates that no button is hold
down. 0xfe sequences are sometimes interrupted by 0xFF */
- dprintk(2,"key %02x\n", b);
+ dev_dbg(&ir->rc->dev, "key %02x\n", b);
if (b == 0xff)
return 0;
@@ -197,13 +232,51 @@ static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
/* keep old data */
return 1;
- *ir_key = b;
- *ir_raw = b;
+ *protocol = RC_PROTO_UNKNOWN;
+ *scancode = b;
+ *toggle = 0;
+ return 1;
+}
+
+static int get_key_geniatech(struct IR_i2c *ir, enum rc_proto *protocol,
+ u32 *scancode, u8 *toggle)
+{
+ int i, rc;
+ unsigned char b;
+
+ /* poll IR chip */
+ for (i = 0; i < 4; i++) {
+ rc = i2c_master_recv(ir->c, &b, 1);
+ if (rc == 1)
+ break;
+ msleep(20);
+ }
+ if (rc != 1) {
+ dev_dbg(&ir->rc->dev, "read error\n");
+ if (rc < 0)
+ return rc;
+ return -EIO;
+ }
+
+ /* don't repeat the key */
+ if (ir->old == b)
+ return 0;
+ ir->old = b;
+
+ /* decode to RC5 */
+ b &= 0x7f;
+ b = (b - 1) / 2;
+
+ dev_dbg(&ir->rc->dev, "key %02x\n", b);
+
+ *protocol = RC_PROTO_RC5;
+ *scancode = b;
+ *toggle = ir->old >> 7;
return 1;
}
-static int get_key_avermedia_cardbus(struct IR_i2c *ir,
- u32 *ir_key, u32 *ir_raw)
+static int get_key_avermedia_cardbus(struct IR_i2c *ir, enum rc_proto *protocol,
+ u32 *scancode, u8 *toggle)
{
unsigned char subaddr, key, keygroup;
struct i2c_msg msg[] = { { .addr = ir->c->addr, .flags = 0,
@@ -212,7 +285,7 @@ static int get_key_avermedia_cardbus(struct IR_i2c *ir,
.buf = &key, .len = 1} };
subaddr = 0x0d;
if (2 != i2c_transfer(ir->c->adapter, msg, 2)) {
- dprintk(1, "read error\n");
+ dev_dbg(&ir->rc->dev, "read error\n");
return -EIO;
}
@@ -222,27 +295,25 @@ static int get_key_avermedia_cardbus(struct IR_i2c *ir,
subaddr = 0x0b;
msg[1].buf = &keygroup;
if (2 != i2c_transfer(ir->c->adapter, msg, 2)) {
- dprintk(1, "read error\n");
+ dev_dbg(&ir->rc->dev, "read error\n");
return -EIO;
}
if (keygroup == 0xff)
return 0;
- dprintk(1, "read key 0x%02x/0x%02x\n", key, keygroup);
+ dev_dbg(&ir->rc->dev, "read key 0x%02x/0x%02x\n", key, keygroup);
if (keygroup < 2 || keygroup > 4) {
- /* Only a warning */
- dprintk(1, "warning: invalid key group 0x%02x for key 0x%02x\n",
- keygroup, key);
+ dev_warn(&ir->rc->dev, "warning: invalid key group 0x%02x for key 0x%02x\n",
+ keygroup, key);
}
key |= (keygroup & 1) << 6;
- *ir_key = key;
- *ir_raw = key;
- if (!strcmp(ir->ir_codes, RC_MAP_AVERMEDIA_M733A_RM_K6)) {
- *ir_key |= keygroup << 8;
- *ir_raw |= keygroup << 8;
- }
+ *protocol = RC_PROTO_UNKNOWN;
+ *scancode = key;
+ if (ir->c->addr == 0x41) /* AVerMedia EM78P153 */
+ *scancode |= keygroup << 8;
+ *toggle = 0;
return 1;
}
@@ -250,19 +321,22 @@ static int get_key_avermedia_cardbus(struct IR_i2c *ir,
static int ir_key_poll(struct IR_i2c *ir)
{
- static u32 ir_key, ir_raw;
+ enum rc_proto protocol = 0;
+ u32 scancode = 0;
+ u8 toggle = 0;
int rc;
- dprintk(3, "%s\n", __func__);
- rc = ir->get_key(ir, &ir_key, &ir_raw);
+ dev_dbg(&ir->rc->dev, "%s\n", __func__);
+ rc = ir->get_key(ir, &protocol, &scancode, &toggle);
if (rc < 0) {
- dprintk(2,"error\n");
+ dev_warn(&ir->rc->dev, "error %d\n", rc);
return rc;
}
if (rc) {
- dprintk(1, "%s: keycode = 0x%04x\n", __func__, ir_key);
- rc_keydown(ir->rc, ir_key, 0);
+ dev_dbg(&ir->rc->dev, "%s: proto = 0x%04x, scancode = 0x%08x\n",
+ __func__, protocol, scancode);
+ rc_keydown(ir->rc, protocol, scancode, toggle);
}
return 0;
}
@@ -272,29 +346,435 @@ static void ir_work(struct work_struct *work)
int rc;
struct IR_i2c *ir = container_of(work, struct IR_i2c, work.work);
- rc = ir_key_poll(ir);
- if (rc == -ENODEV) {
- rc_unregister_device(ir->rc);
- ir->rc = NULL;
- return;
+ /*
+ * If the transmit code is holding the lock, skip polling for
+ * IR, we'll get it to it next time round
+ */
+ if (mutex_trylock(&ir->lock)) {
+ rc = ir_key_poll(ir);
+ mutex_unlock(&ir->lock);
+ if (rc == -ENODEV) {
+ rc_unregister_device(ir->rc);
+ ir->rc = NULL;
+ return;
+ }
}
schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling_interval));
}
-/* ----------------------------------------------------------------------- */
+static int ir_open(struct rc_dev *dev)
+{
+ struct IR_i2c *ir = dev->priv;
+
+ schedule_delayed_work(&ir->work, 0);
+
+ return 0;
+}
+
+static void ir_close(struct rc_dev *dev)
+{
+ struct IR_i2c *ir = dev->priv;
+
+ cancel_delayed_work_sync(&ir->work);
+}
+
+/* Zilog Transmit Interface */
+#define XTAL_FREQ 18432000
+
+#define ZILOG_SEND 0x80
+#define ZILOG_UIR_END 0x40
+#define ZILOG_INIT_END 0x20
+#define ZILOG_LIR_END 0x10
+
+#define ZILOG_STATUS_OK 0x80
+#define ZILOG_STATUS_TX 0x40
+#define ZILOG_STATUS_SET 0x20
+
+/*
+ * As you can see here, very few different lengths of pulse and space
+ * can be encoded. This means that the hardware does not work well with
+ * recorded IR. It's best to work with generated IR, like from ir-ctl or
+ * the in-kernel encoders.
+ */
+struct code_block {
+ u8 length;
+ u16 pulse[7]; /* not aligned */
+ u8 carrier_pulse;
+ u8 carrier_space;
+ u16 space[8]; /* not aligned */
+ u8 codes[61];
+ u8 csum[2];
+} __packed;
+
+static int send_data_block(struct IR_i2c *ir, int cmd,
+ struct code_block *code_block)
+{
+ int i, j, ret;
+ u8 buf[5], *p;
+
+ p = &code_block->length;
+ for (i = 0; p < code_block->csum; i++)
+ code_block->csum[i & 1] ^= *p++;
+
+ p = &code_block->length;
+
+ for (i = 0; i < sizeof(*code_block);) {
+ int tosend = sizeof(*code_block) - i;
+
+ if (tosend > 4)
+ tosend = 4;
+ buf[0] = i + 1;
+ for (j = 0; j < tosend; ++j)
+ buf[1 + j] = p[i + j];
+ dev_dbg(&ir->rc->dev, "%*ph", tosend + 1, buf);
+ ret = i2c_master_send(ir->tx_c, buf, tosend + 1);
+ if (ret != tosend + 1) {
+ dev_dbg(&ir->rc->dev,
+ "i2c_master_send failed with %d\n", ret);
+ return ret < 0 ? ret : -EIO;
+ }
+ i += tosend;
+ }
+
+ buf[0] = 0;
+ buf[1] = cmd;
+ ret = i2c_master_send(ir->tx_c, buf, 2);
+ if (ret != 2) {
+ dev_err(&ir->rc->dev, "i2c_master_send failed with %d\n", ret);
+ return ret < 0 ? ret : -EIO;
+ }
+
+ usleep_range(2000, 5000);
+
+ ret = i2c_master_send(ir->tx_c, buf, 1);
+ if (ret != 1) {
+ dev_err(&ir->rc->dev, "i2c_master_send failed with %d\n", ret);
+ return ret < 0 ? ret : -EIO;
+ }
+
+ return 0;
+}
+
+static int zilog_init(struct IR_i2c *ir)
+{
+ struct code_block code_block = { .length = sizeof(code_block) };
+ u8 buf[4];
+ int ret;
+
+ put_unaligned_be16(0x1000, &code_block.pulse[3]);
+
+ ret = send_data_block(ir, ZILOG_INIT_END, &code_block);
+ if (ret)
+ return ret;
+
+ ret = i2c_master_recv(ir->tx_c, buf, 4);
+ if (ret != 4) {
+ dev_err(&ir->c->dev, "failed to retrieve firmware version: %d\n",
+ ret);
+ return ret < 0 ? ret : -EIO;
+ }
+
+ dev_info(&ir->c->dev, "Zilog/Hauppauge IR blaster firmware version %d.%d.%d\n",
+ buf[1], buf[2], buf[3]);
+
+ return 0;
+}
+
+/*
+ * If the last slot for pulse is the same as the current slot for pulse,
+ * then use slot no 7.
+ */
+static void copy_codes(u8 *dst, u8 *src, unsigned int count)
+{
+ u8 c, last = 0xff;
+
+ while (count--) {
+ c = *src++;
+ if ((c & 0xf0) == last) {
+ *dst++ = 0x70 | (c & 0xf);
+ } else {
+ *dst++ = c;
+ last = c & 0xf0;
+ }
+ }
+}
-static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
+/*
+ * When looking for repeats, we don't care about the trailing space. This
+ * is set to the shortest possible anyway.
+ */
+static int cmp_no_trail(u8 *a, u8 *b, unsigned int count)
{
+ while (--count) {
+ if (*a++ != *b++)
+ return 1;
+ }
+
+ return (*a & 0xf0) - (*b & 0xf0);
+}
+
+static int find_slot(u16 *array, unsigned int size, u16 val)
+{
+ int i;
+
+ for (i = 0; i < size; i++) {
+ if (get_unaligned_be16(&array[i]) == val) {
+ return i;
+ } else if (!array[i]) {
+ put_unaligned_be16(val, &array[i]);
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+static int zilog_ir_format(struct rc_dev *rcdev, unsigned int *txbuf,
+ unsigned int count, struct code_block *code_block)
+{
+ struct IR_i2c *ir = rcdev->priv;
+ int rep, i, l, p = 0, s, c = 0;
+ bool repeating;
+ u8 codes[174];
+
+ code_block->carrier_pulse = DIV_ROUND_CLOSEST(
+ ir->duty_cycle * XTAL_FREQ / 1000, ir->carrier);
+ code_block->carrier_space = DIV_ROUND_CLOSEST(
+ (100 - ir->duty_cycle) * XTAL_FREQ / 1000, ir->carrier);
+
+ for (i = 0; i < count; i++) {
+ if (c >= ARRAY_SIZE(codes) - 1) {
+ dev_warn(&rcdev->dev, "IR too long, cannot transmit\n");
+ return -EINVAL;
+ }
+
+ /*
+ * Lengths more than 142220us cannot be encoded; also
+ * this checks for multiply overflow
+ */
+ if (txbuf[i] > 142220)
+ return -EINVAL;
+
+ l = DIV_ROUND_CLOSEST((XTAL_FREQ / 1000) * txbuf[i], 40000);
+
+ if (i & 1) {
+ s = find_slot(code_block->space,
+ ARRAY_SIZE(code_block->space), l);
+ if (s == -1) {
+ dev_warn(&rcdev->dev, "Too many different lengths spaces, cannot transmit");
+ return -EINVAL;
+ }
+
+ /* We have a pulse and space */
+ codes[c++] = (p << 4) | s;
+ } else {
+ p = find_slot(code_block->pulse,
+ ARRAY_SIZE(code_block->pulse), l);
+ if (p == -1) {
+ dev_warn(&rcdev->dev, "Too many different lengths pulses, cannot transmit");
+ return -EINVAL;
+ }
+ }
+ }
+
+ /* We have to encode the trailing pulse. Find the shortest space */
+ s = 0;
+ for (i = 1; i < ARRAY_SIZE(code_block->space); i++) {
+ u16 d = get_unaligned_be16(&code_block->space[i]);
+
+ if (get_unaligned_be16(&code_block->space[s]) > d)
+ s = i;
+ }
+
+ codes[c++] = (p << 4) | s;
+
+ dev_dbg(&rcdev->dev, "generated %d codes\n", c);
+
+ /*
+ * Are the last N codes (so pulse + space) repeating 3 times?
+ * if so we can shorten the codes list and use code 0xc0 to repeat
+ * them.
+ */
+ repeating = false;
+
+ for (rep = c / 3; rep >= 1; rep--) {
+ if (!memcmp(&codes[c - rep * 3], &codes[c - rep * 2], rep) &&
+ !cmp_no_trail(&codes[c - rep], &codes[c - rep * 2], rep)) {
+ repeating = true;
+ break;
+ }
+ }
+
+ if (repeating) {
+ /* first copy any leading non-repeating */
+ int leading = c - rep * 3;
+
+ if (leading >= ARRAY_SIZE(code_block->codes) - 3 - rep) {
+ dev_warn(&rcdev->dev, "IR too long, cannot transmit\n");
+ return -EINVAL;
+ }
+
+ dev_dbg(&rcdev->dev, "found trailing %d repeat\n", rep);
+ copy_codes(code_block->codes, codes, leading);
+ code_block->codes[leading] = 0x82;
+ copy_codes(code_block->codes + leading + 1, codes + leading,
+ rep);
+ c = leading + 1 + rep;
+ code_block->codes[c++] = 0xc0;
+ } else {
+ if (c >= ARRAY_SIZE(code_block->codes) - 3) {
+ dev_warn(&rcdev->dev, "IR too long, cannot transmit\n");
+ return -EINVAL;
+ }
+
+ dev_dbg(&rcdev->dev, "found no trailing repeat\n");
+ code_block->codes[0] = 0x82;
+ copy_codes(code_block->codes + 1, codes, c);
+ c++;
+ code_block->codes[c++] = 0xc4;
+ }
+
+ while (c < ARRAY_SIZE(code_block->codes))
+ code_block->codes[c++] = 0x83;
+
+ return 0;
+}
+
+static int zilog_tx(struct rc_dev *rcdev, unsigned int *txbuf,
+ unsigned int count)
+{
+ struct IR_i2c *ir = rcdev->priv;
+ struct code_block code_block = { .length = sizeof(code_block) };
+ u8 buf[2];
+ int ret, i;
+
+ ret = zilog_ir_format(rcdev, txbuf, count, &code_block);
+ if (ret)
+ return ret;
+
+ ret = mutex_lock_interruptible(&ir->lock);
+ if (ret)
+ return ret;
+
+ ret = send_data_block(ir, ZILOG_UIR_END, &code_block);
+ if (ret)
+ goto out_unlock;
+
+ ret = i2c_master_recv(ir->tx_c, buf, 1);
+ if (ret != 1) {
+ dev_err(&ir->rc->dev, "i2c_master_recv failed with %d\n", ret);
+ goto out_unlock;
+ }
+
+ dev_dbg(&ir->rc->dev, "code set status: %02x\n", buf[0]);
+
+ if (buf[0] != (ZILOG_STATUS_OK | ZILOG_STATUS_SET)) {
+ dev_err(&ir->rc->dev, "unexpected IR TX response %02x\n",
+ buf[0]);
+ ret = -EIO;
+ goto out_unlock;
+ }
+
+ buf[0] = 0x00;
+ buf[1] = ZILOG_SEND;
+
+ ret = i2c_master_send(ir->tx_c, buf, 2);
+ if (ret != 2) {
+ dev_err(&ir->rc->dev, "i2c_master_send failed with %d\n", ret);
+ if (ret >= 0)
+ ret = -EIO;
+ goto out_unlock;
+ }
+
+ dev_dbg(&ir->rc->dev, "send command sent\n");
+
+ /*
+ * This bit NAKs until the device is ready, so we retry it
+ * sleeping a bit each time. This seems to be what the windows
+ * driver does, approximately.
+ * Try for up to 1s.
+ */
+ for (i = 0; i < 20; ++i) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(msecs_to_jiffies(50));
+ ret = i2c_master_send(ir->tx_c, buf, 1);
+ if (ret == 1)
+ break;
+ dev_dbg(&ir->rc->dev,
+ "NAK expected: i2c_master_send failed with %d (try %d)\n",
+ ret, i + 1);
+ }
+
+ if (ret != 1) {
+ dev_err(&ir->rc->dev,
+ "IR TX chip never got ready: last i2c_master_send failed with %d\n",
+ ret);
+ if (ret >= 0)
+ ret = -EIO;
+ goto out_unlock;
+ }
+
+ ret = i2c_master_recv(ir->tx_c, buf, 1);
+ if (ret != 1) {
+ dev_err(&ir->rc->dev, "i2c_master_recv failed with %d\n", ret);
+ ret = -EIO;
+ goto out_unlock;
+ } else if (buf[0] != ZILOG_STATUS_OK) {
+ dev_err(&ir->rc->dev, "unexpected IR TX response #2: %02x\n",
+ buf[0]);
+ ret = -EIO;
+ goto out_unlock;
+ }
+ dev_dbg(&ir->rc->dev, "transmit complete\n");
+
+ /* Oh good, it worked */
+ ret = count;
+out_unlock:
+ mutex_unlock(&ir->lock);
+
+ return ret;
+}
+
+static int zilog_tx_carrier(struct rc_dev *dev, u32 carrier)
+{
+ struct IR_i2c *ir = dev->priv;
+
+ if (carrier > 500000 || carrier < 20000)
+ return -EINVAL;
+
+ ir->carrier = carrier;
+
+ return 0;
+}
+
+static int zilog_tx_duty_cycle(struct rc_dev *dev, u32 duty_cycle)
+{
+ struct IR_i2c *ir = dev->priv;
+
+ ir->duty_cycle = duty_cycle;
+
+ return 0;
+}
+
+static int ir_probe(struct i2c_client *client)
+{
+ const struct i2c_device_id *id = i2c_client_get_device_id(client);
char *ir_codes = NULL;
const char *name = NULL;
- u64 rc_type = RC_BIT_UNKNOWN;
+ u64 rc_proto = RC_PROTO_BIT_UNKNOWN;
struct IR_i2c *ir;
struct rc_dev *rc = NULL;
struct i2c_adapter *adap = client->adapter;
unsigned short addr = client->addr;
+ bool probe_tx = (id->driver_data & FLAG_TX) != 0;
int err;
+ if ((id->driver_data & FLAG_HDPVR) && !enable_hdpvr) {
+ dev_err(&client->dev, "IR for HDPVR is known to cause problems during recording, use enable_hdpvr modparam to enable\n");
+ return -ENODEV;
+ }
+
ir = devm_kzalloc(&client->dev, sizeof(*ir), GFP_KERNEL);
if (!ir)
return -ENOMEM;
@@ -307,7 +787,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
case 0x64:
name = "Pixelview";
ir->get_key = get_key_pixelview;
- rc_type = RC_BIT_OTHER;
+ rc_proto = RC_PROTO_BIT_OTHER;
ir_codes = RC_MAP_EMPTY;
break;
case 0x18:
@@ -315,39 +795,49 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
case 0x1a:
name = "Hauppauge";
ir->get_key = get_key_haup;
- rc_type = RC_BIT_RC5;
+ rc_proto = RC_PROTO_BIT_RC5;
ir_codes = RC_MAP_HAUPPAUGE;
break;
case 0x30:
name = "KNC One";
ir->get_key = get_key_knc1;
- rc_type = RC_BIT_OTHER;
+ rc_proto = RC_PROTO_BIT_OTHER;
ir_codes = RC_MAP_EMPTY;
break;
+ case 0x33:
+ name = "Geniatech";
+ ir->get_key = get_key_geniatech;
+ rc_proto = RC_PROTO_BIT_RC5;
+ ir_codes = RC_MAP_TOTAL_MEDIA_IN_HAND_02;
+ ir->old = 0xfc;
+ break;
case 0x6b:
name = "FusionHDTV";
ir->get_key = get_key_fusionhdtv;
- rc_type = RC_BIT_RC5;
+ rc_proto = RC_PROTO_BIT_UNKNOWN;
ir_codes = RC_MAP_FUSIONHDTV_MCE;
break;
case 0x40:
name = "AVerMedia Cardbus remote";
ir->get_key = get_key_avermedia_cardbus;
- rc_type = RC_BIT_OTHER;
+ rc_proto = RC_PROTO_BIT_OTHER;
ir_codes = RC_MAP_AVERMEDIA_CARDBUS;
break;
case 0x41:
name = "AVerMedia EM78P153";
ir->get_key = get_key_avermedia_cardbus;
- rc_type = RC_BIT_OTHER;
+ rc_proto = RC_PROTO_BIT_OTHER;
/* RM-KV remote, seems to be same as RM-K6 */
ir_codes = RC_MAP_AVERMEDIA_M733A_RM_K6;
break;
case 0x71:
name = "Hauppauge/Zilog Z8";
ir->get_key = get_key_haup_xvr;
- rc_type = RC_BIT_RC5;
+ rc_proto = RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC6_MCE |
+ RC_PROTO_BIT_RC6_6A_32;
ir_codes = RC_MAP_HAUPPAUGE;
+ ir->polling_interval = 125;
+ probe_tx = true;
break;
}
@@ -361,7 +851,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
name = init_data->name;
if (init_data->type)
- rc_type = init_data->type;
+ rc_proto = init_data->type;
if (init_data->polling_interval)
ir->polling_interval = init_data->polling_interval;
@@ -380,6 +870,9 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
case IR_KBD_GET_KEY_KNC1:
ir->get_key = get_key_knc1;
break;
+ case IR_KBD_GET_KEY_GENIATECH:
+ ir->get_key = get_key_geniatech;
+ break;
case IR_KBD_GET_KEY_FUSIONHDTV:
ir->get_key = get_key_fusionhdtv;
break;
@@ -394,29 +887,26 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
if (!rc) {
/*
- * If platform_data doesn't specify rc_dev, initilize it
+ * If platform_data doesn't specify rc_dev, initialize it
* internally
*/
- rc = rc_allocate_device();
+ rc = rc_allocate_device(RC_DRIVER_SCANCODE);
if (!rc)
return -ENOMEM;
}
ir->rc = rc;
/* Make sure we are all setup before going on */
- if (!name || !ir->get_key || !rc_type || !ir_codes) {
- dprintk(1, ": Unsupported device at address 0x%02x\n",
- addr);
+ if (!name || !ir->get_key || !rc_proto || !ir_codes) {
+ dev_warn(&client->dev, "Unsupported device at address 0x%02x\n",
+ addr);
err = -ENODEV;
goto err_out_free;
}
- /* Sets name */
- snprintf(ir->name, sizeof(ir->name), "i2c IR (%s)", name);
ir->ir_codes = ir_codes;
- snprintf(ir->phys, sizeof(ir->phys), "%s/%s/ir0",
- dev_name(&adap->dev),
+ snprintf(ir->phys, sizeof(ir->phys), "%s/%s", dev_name(&adap->dev),
dev_name(&client->dev));
/*
@@ -425,59 +915,74 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
*/
rc->input_id.bustype = BUS_I2C;
rc->input_phys = ir->phys;
- rc->input_name = ir->name;
+ rc->device_name = name;
+ rc->dev.parent = &client->dev;
+ rc->priv = ir;
+ rc->open = ir_open;
+ rc->close = ir_close;
/*
* Initialize the other fields of rc_dev
*/
rc->map_name = ir->ir_codes;
- rc->allowed_protos = rc_type;
- rc->enabled_protocols = rc_type;
+ rc->allowed_protocols = rc_proto;
if (!rc->driver_name)
- rc->driver_name = MODULE_NAME;
+ rc->driver_name = KBUILD_MODNAME;
+
+ mutex_init(&ir->lock);
+
+ INIT_DELAYED_WORK(&ir->work, ir_work);
+
+ if (probe_tx) {
+ ir->tx_c = i2c_new_dummy_device(client->adapter, 0x70);
+ if (IS_ERR(ir->tx_c)) {
+ dev_err(&client->dev, "failed to setup tx i2c address");
+ err = PTR_ERR(ir->tx_c);
+ goto err_out_free;
+ } else if (!zilog_init(ir)) {
+ ir->carrier = 38000;
+ ir->duty_cycle = 40;
+ rc->tx_ir = zilog_tx;
+ rc->s_tx_carrier = zilog_tx_carrier;
+ rc->s_tx_duty_cycle = zilog_tx_duty_cycle;
+ }
+ }
err = rc_register_device(rc);
if (err)
goto err_out_free;
- printk(MODULE_NAME ": %s detected at %s [%s]\n",
- ir->name, ir->phys, adap->name);
-
- /* start polling via eventd */
- INIT_DELAYED_WORK(&ir->work, ir_work);
- schedule_delayed_work(&ir->work, 0);
-
return 0;
err_out_free:
+ if (!IS_ERR(ir->tx_c))
+ i2c_unregister_device(ir->tx_c);
+
/* Only frees rc if it were allocated internally */
rc_free_device(rc);
return err;
}
-static int ir_remove(struct i2c_client *client)
+static void ir_remove(struct i2c_client *client)
{
struct IR_i2c *ir = i2c_get_clientdata(client);
- /* kill outstanding polls */
cancel_delayed_work_sync(&ir->work);
- /* unregister device */
- if (ir->rc)
- rc_unregister_device(ir->rc);
+ i2c_unregister_device(ir->tx_c);
- /* free memory */
- return 0;
+ rc_unregister_device(ir->rc);
}
static const struct i2c_device_id ir_kbd_id[] = {
/* Generic entry for any IR receiver */
{ "ir_video", 0 },
/* IR device specific entries should be added here */
- { "ir_rx_z8f0811_haup", 0 },
- { "ir_rx_z8f0811_hdpvr", 0 },
+ { "ir_z8f0811_haup", FLAG_TX },
+ { "ir_z8f0811_hdpvr", FLAG_TX | FLAG_HDPVR },
{ }
};
+MODULE_DEVICE_TABLE(i2c, ir_kbd_id);
static struct i2c_driver ir_kbd_driver = {
.driver = {