Patch: Add Kworld ATSC110 HDTV CARD Remote Functionality

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Been testing this patch for a couple of weeks.   Functionality works great.  A lot of people have been requesting
this patch.

Patch contents:
- Add ir remote functionality for the Kworld ATSC110 HDTV tuner card.

Signed-off-by: Dwaine P. Garden <DwaineGarden@xxxxxxxxxx>
diff -U 3 -H -d -r -N -- a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c
--- a/linux/drivers/media/common/ir-keymaps.c	2007-01-01 03:10:56.000000000 -0500
+++ b/linux/drivers/media/common/ir-keymaps.c	2007-01-01 05:59:58.000000000 -0500
@@ -1789,3 +1789,58 @@
 };
 
 EXPORT_SYMBOL_GPL(ir_codes_encore_enltv);
+
+IR_KEYTAB_TYPE ir_codes_kworld_atsc110[IR_KEYTAB_SIZE] = {
+        [ 0x0 ] = KEY_1,
+        [ 0x1 ] = KEY_2,
+        [ 0x2 ] = KEY_3,
+        [ 0x3 ] = KEY_4,
+        [ 0x4 ] = KEY_5,
+        [ 0x5 ] = KEY_6,
+        [ 0x6 ] = KEY_7,
+        [ 0x7 ] = KEY_8,
+        [ 0x8 ] = KEY_9,
+        [ 0xa ] = KEY_0,
+        [ 0x9 ] = KEY_ESC,              /* UP ARROW */
+        [ 0xc ] = KEY_POWER,            /* POWER */
+        [ 0x0a ] = KEY_MUTE,            /* MUTE */
+        [ 0x0b ] = KEY_SEARCH,          /* SEARCH */
+        [ 0x0d ] = KEY_EPG,             /* GUIDE */
+        [ 0x1b ] = KEY_RECORD,          /* RECORD */
+        [ 0x16 ] = KEY_PAUSE,           /* PAUSE */
+        [ 0x1a ] = KEY_STOP,            /* STOP */
+        [ 0x1d ] = KEY_VOLUMEDOWN,      /* VOLUME- */
+        [ 0x1c ] = KEY_VOLUMEUP,        /* VOLUME+ */
+        [ 0x1f ] = KEY_CHANNELDOWN,     /* CHANNEL/PAGE- */
+        [ 0x1e ] = KEY_CHANNELUP,       /* CHANNEL/PAGE+ */
+        [ 0x10 ] = KEY_UP,              /* KEY_SCROLLUP */
+        [ 0x12 ] = KEY_LEFT,            /* KEY_BACK */
+        [ 0xe  ] = KEY_ENTER,           /* KEY_ENTER */
+        [ 0x13 ] = KEY_RIGHT,           /* KEY_FORWARD */
+        [ 0x11 ] = KEY_DOWN,            /* KEY_SCROLLDOWN */
+        [ 0x14 ] = KEY_MUTE,            /* MUTE */
+        [ 0x15 ] = KEY_AUDIO,           /* STEREO */
+        [ 0x16 ] = KEY_VIDEO,           /* SOURCE */
+        [ 0x17 ] = KEY_ZOOM,            /* ZOOM */
+        [ 0x18 ] = KEY_PRINT,           /* SHUTDOWN */
+        [ 0X19 ] = KEY_T,               /* TIMESHIFT */
+        [ 0x44 ] = KEY_PLAYPAUSE,       /* PAUSE/PLAY */
+        [ 0x45 ] = KEY_STOP,            /* STOP */
+        [ 0x40 ] = KEY_REWIND,          /* REWIND */
+        [ 0x41 ] = KEY_FORWARD,         /* FASTFORWARD */
+        [ 0x42 ] = KEY_PREVIOUSSONG,    /* PREVIOUS */
+        [ 0x43 ] = KEY_NEXTSONG,        /* NEXT */
+
+        /* buttons a-h */
+        [ 0x48 ] = KEY_A, 
+        [ 0x49 ] = KEY_B,
+        [ 0x4a ] = KEY_C,
+        [ 0x4b ] = KEY_D,
+        [ 0x4c ] = KEY_E,
+        [ 0x4d ] = KEY_F,
+        [ 0x4e ] = KEY_G,
+        [ 0x4f ] = KEY_H
+};
+
+EXPORT_SYMBOL_GPL(ir_codes_kworld_atsc110);
+
diff -U 3 -H -d -r -N -- a/linux/drivers/media/video/ir-kbd-i2c.c b/linux/drivers/media/video/ir-kbd-i2c.c
--- a/linux/drivers/media/video/ir-kbd-i2c.c	2007-01-01 03:10:56.000000000 -0500
+++ b/linux/drivers/media/video/ir-kbd-i2c.c	2007-01-01 03:45:41.000000000 -0500
@@ -55,6 +55,11 @@
 module_param(hauppauge, int, 0644);    /* Choose Hauppauge remote */
 MODULE_PARM_DESC(hauppauge, "Specify Hauppauge remote: 0=black, 1=grey (defaults to 0)");
 
+static int kworldatsc110 = 0;
+module_param(kworldatsc110, int, 0644);    /* Choose a Kworld ATSC110 remote */
+MODULE_PARM_DESC(hauppauge, "Specify a Kworld HDTV ATSC110 remote: 0=No, 1=Yes (defaults to 0)");
+
+
 
 #define DEVNAME "ir-kbd-i2c"
 #define dprintk(level, fmt, arg...)	if (debug >= level) \
@@ -207,6 +212,30 @@
 	return 1;
 }
 
+static int get_key_kworld_atsc110(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+	unsigned char b;
+
+	if (1 != i2c_master_recv(&ir->c,&b,1)) {
+		dprintk(1,"read error\n");
+		return -EIO;
+	}
+
+	dprintk(2,"key %02x\n", b);
+
+	/* No button press */
+	if (b == 0xFF)
+		return 0;
+		
+        /* repeating */
+        if (b & 0x80)
+                return 1;
+
+	*ir_key = b;
+	*ir_raw = b;
+	return 1;
+}
+
 /* The grey pinnacle PCTV remote
  *
  *  There are one issue with this remote:
@@ -364,10 +393,17 @@
 		}
 		break;
 	case 0x30:
-		name        = "KNC One";
-		ir->get_key = get_key_knc1;
-		ir_type     = IR_TYPE_OTHER;
-		ir_codes    = ir_codes_empty;
+		if (kworldatsc110 == 1) {
+			name        = "Kworld ATSC110";
+			ir->get_key = get_key_kworld_atsc110;
+			ir_type     = IR_TYPE_OTHER;
+			ir_codes    = ir_codes_kworld_atsc110;
+		} else {
+			name        = "KNC One";
+			ir->get_key = get_key_knc1;
+			ir_type     = IR_TYPE_OTHER;
+			ir_codes    = ir_codes_empty;
+		}
 		break;
 	case 0x7a:
 	case 0x47:
@@ -470,7 +506,7 @@
 	*/
 
 	static const int probe_bttv[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1};
-	static const int probe_saa7134[] = { 0x7a, 0x47, 0x71, -1 };
+	static const int probe_saa7134[] = { 0x7a, 0x47, 0x30, -1 };
 	static const int probe_em28XX[] = { 0x30, 0x47, -1 };
 	const int *probe = NULL;
 	struct i2c_client c;
@@ -499,6 +535,36 @@
 	for (i = 0; -1 != probe[i]; i++) {
 		c.addr = probe[i];
 		rc = i2c_master_recv(&c,&buf,0);
+
+		/* Special case for Kworld ATSC110 remote */
+		if (c.adapter->id == I2C_HW_SAA7134 && probe[i] == 0x30)
+		{
+			struct i2c_client c2;
+			
+			dprintk(1,"Attempting special probe at 0x%x\n", probe[i]);
+
+			memset (&c2, 0, sizeof(c2));
+			c2.adapter = c.adapter;
+				
+			/* Find a device that responds. If none found, oh well. */
+			for (c2.addr=127; c2.addr > 0; c2.addr--)
+			{
+				if (0 == i2c_master_recv(&c2,&buf,0)) {
+					dprintk(1,"found another device, at addr 0x%02x\n", c2.addr);
+					break;
+				}
+			}
+
+			/* Now do the probe. The controller does not respond
+			   to 0-byte reads, so we use a 1-byte read instead. */
+			rc = i2c_master_recv(&c,&buf,1);
+			rc--;
+		}
+		else
+		{
+			rc = i2c_master_recv(&c,&buf,0);
+		}
+
 		dprintk(1,"probe 0x%02x @ %s: %s\n",
 			probe[i], adap->name,
 			(0 == rc) ? "yes" : "no");
diff -U 3 -H -d -r -N -- a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c
--- a/linux/drivers/media/video/saa7134/saa7134-cards.c	2007-01-01 03:10:56.000000000 -0500
+++ b/linux/drivers/media/video/saa7134/saa7134-cards.c	2007-01-01 04:09:05.000000000 -0500
@@ -4173,6 +4173,7 @@
 		dev->has_remote = SAA7134_REMOTE_I2C;
 		break;
 	case SAA7134_BOARD_AVERMEDIA_A169_B:
+	case SAA7134_BOARD_KWORLD_ATSC110:
 	case SAA7134_BOARD_MD7134_BRIDGE_2:
 		printk("%s: %s: dual saa713x broadcast decoders\n"
 		       "%s: Sorry, none of the inputs to this chip are supported yet.\n"
diff -U 3 -H -d -r -N -- a/linux/drivers/media/video/saa7134/saa7134-i2c.c b/linux/drivers/media/video/saa7134/saa7134-i2c.c
--- a/linux/drivers/media/video/saa7134/saa7134-i2c.c	2007-01-01 03:10:56.000000000 -0500
+++ b/linux/drivers/media/video/saa7134/saa7134-i2c.c	2007-01-01 03:35:04.000000000 -0500
@@ -352,6 +352,8 @@
 		case 0x7a:
 		case 0x47:
 		case 0x71:
+		case 0xc2:
+		case 0x30:
 		{
 			struct IR_i2c *ir = i2c_get_clientdata(client);
 			d1printk("%s i2c IR detected (%s).\n",
diff -U 3 -H -d -r -N -- a/linux/drivers/media/video/saa7134/saa7134-input.c b/linux/drivers/media/video/saa7134/saa7134-input.c
--- a/linux/drivers/media/video/saa7134/saa7134-input.c	2007-01-01 03:10:56.000000000 -0500
+++ b/linux/drivers/media/video/saa7134/saa7134-input.c	2007-01-01 03:40:47.000000000 -0500
@@ -142,6 +142,49 @@
 	return 1;
 }
 
+static int get_key_kworld_atsc110(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+	unsigned char b;
+	int rc;
+	int gpio;
+
+
+	/* We need this to access GPIO. Used by the saa_readl macro. */
+	struct saa7134_dev *dev = ir->c.adapter->algo_data;
+	if (dev == NULL) {
+		dprintk ("ir->c.adapter->algo_data is NULL!\n");
+		return -EIO;
+	}
+	
+	/* rising SAA7134_GPIO_GPRESCAN reads the status */
+	saa_clearb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN);
+	saa_setb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN);
+
+	gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2);
+	
+	if (gpio & 0x100) 
+		return 0;	/* No button press */
+
+
+	/* GPIO says there is a button press. Get it. */
+	if (1 != (rc=i2c_master_recv(&ir->c,&b,1))) {
+		dprintk("read error %d\n", rc);
+		return -EIO;
+	}
+
+	/* No button press */
+	if (b == 0xFF)
+		return 0;
+		
+        /* repeating */
+        if (b & 0x80)
+                return 1;
+
+	*ir_key = b;
+	*ir_raw = b;
+	return 1;
+}
+
 void saa7134_input_irq(struct saa7134_dev *dev)
 {
 	struct card_ir *ir = dev->remote;
@@ -334,6 +377,12 @@
 		mask_keyup   = 0x040000;
 		polling      = 50; // ms
 		break;
+	case SAA7134_BOARD_KWORLD_ATSC110:
+                ir_codes     = ir_codes_kworld_atsc110;
+                mask_keycode = 0x0;
+                mask_keydown = 0x0;
+		polling      = 50; // ms
+                break;
 	}
 	if (NULL == ir_codes) {
 		printk("%s: Oops: IR config error [card=%d]\n",
@@ -442,6 +491,11 @@
 		ir->get_key   = get_key_hvr1110;
 		ir->ir_codes  = ir_codes_hauppauge_new;
 		break;
+	case SAA7134_BOARD_KWORLD_ATSC110:
+		snprintf(ir->c.name, sizeof(ir->c.name), "Kworld ATSC110");
+                ir->get_key   = get_key_kworld_atsc110;
+                ir->ir_codes  = ir_codes_kworld_atsc110;
+                break;
 	default:
 		dprintk("Shouldn't get here: Unknown board %x for I2C IR?\n",dev->board);
 		break;
diff -U 3 -H -d -r -N -- a/linux/include/media/ir-common.h b/linux/include/media/ir-common.h
--- a/linux/include/media/ir-common.h	2007-01-01 03:10:56.000000000 -0500
+++ b/linux/include/media/ir-common.h	2007-01-01 03:41:36.000000000 -0500
@@ -139,7 +139,7 @@
 extern IR_KEYTAB_TYPE ir_codes_budget_ci_old[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_asus_pc39[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE];
-
+extern IR_KEYTAB_TYPE ir_codes_kworld_atsc110[IR_KEYTAB_SIZE];
 #endif
 
 /*
_______________________________________________
linux-dvb mailing list
linux-dvb@xxxxxxxxxxx
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb

[Index of Archives]     [Linux Media]     [Video 4 Linux]     [Asterisk]     [Samba]     [Xorg]     [Xfree86]     [Linux USB]

  Powered by Linux