Mailing List archive

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

[linux-dvb] Re: TT budget / NOVA IR support



reset MSP430 was not a good idea as it also took out the tuner, oh, well. here's the fixed version.

Holger Waechtler wrote:

I'd like to apply your patch, but please modify it in order to follow the Linux kernel coding style rules in /usr/src/linux/Documentation/CodingStyle.
now butt-ugly courtesy of indent.

And please prepare 2 patches, one against the DVB/-Tree and one against dvb-kernel/.
dvb-kernel looks like 2.5.x stuff, with which i can't afford to play.

:{)}
jkt> cvs -f diff -pu DVB-current/driver/av7110/Makefile 
Index: DVB-current/driver/av7110/Makefile
===================================================================
RCS file: /cvs/linuxtv/DVB/driver/av7110/Makefile,v
retrieving revision 1.7
diff -p -u -r1.7 Makefile
--- DVB-current/driver/av7110/Makefile	8 Nov 2002 15:28:08 -0000	1.7
+++ DVB-current/driver/av7110/Makefile	21 Jan 2003 21:18:09 -0000
@@ -23,6 +23,7 @@ ifdef DVB_PACK 
 else
   obj-$(CONFIG_AV7110_DVB) += dvb-ttpci.o
 endif
+obj-m += msp430_ir.o
 
 # Extract lists of the multi-part drivers. 
 # The 'int-*' lists are the intermediate files used to build the multi's. 

jkt> diff -pu --unidirectional-new-file DVB-current/driver/av7110/msp430_ir.c{~,}
--- DVB-current/driver/av7110/msp430_ir.c~	1969-12-31 17:00:00.000000000 -0700
+++ DVB-current/driver/av7110/msp430_ir.c	2003-01-21 14:15:12.000000000 -0700
@@ -0,0 +1,305 @@
+/* Copyright (c) 2003 Helius, Inc.  All Rights Reserved. */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+#include "input_fake.h"
+#endif
+
+#include "saa7146_defs.h"
+#include "saa7146_core.h"
+
+MODULE_AUTHOR("Helius, Inc.");
+MODULE_DESCRIPTION
+    ("input event module for those TechnoTrend TT-PCline budget/Hauppauge WinTV-Nova IR receivers using MSP430 microcontrollers");
+MODULE_LICENSE("GPL");
+EXPORT_NO_SYMBOLS;
+
+/* from reading the following remotes:
+   Zenith Universal 7 / TV Mode 807 / VCR Mode 837
+   Hauppauge (from NOVA-CI-s box product)
+   i've taken a "middle of the road" approach and note the differences
+*/
+static u16 key_map[64] = {
+	/* 0x0X */
+	KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8,
+	KEY_9,
+	KEY_ENTER,
+	0,
+	KEY_POWER,		/* RADIO on Hauppauge */
+	KEY_MUTE,
+	0,
+	KEY_A,			/* TV on Hauppauge */
+	/* 0x1X */
+	KEY_VOLUMEUP, KEY_VOLUMEDOWN,
+	0, 0,
+	KEY_B,
+	0, 0, 0, 0, 0, 0, 0,
+	KEY_UP, KEY_DOWN,
+	KEY_OPTION,		/* RESERVED on Hauppauge */
+	0,
+	/* 0x2X */
+	KEY_CHANNELUP, KEY_CHANNELDOWN,
+	KEY_PREVIOUS,		/* Prev. Ch on Zenith, SOURCE on Hauppauge */
+	0, 0, 0,
+	KEY_CYCLEWINDOWS,	/* MINIMIZE on Hauppauge */
+	0,
+	KEY_ENTER,		/* VCR mode on Zenith */
+	KEY_PAUSE,
+	0,
+	KEY_RIGHT, KEY_LEFT,
+	0,
+	KEY_MENU,		/* FULL SCREEN on Hauppauge */
+	0,
+	/* 0x3X */
+	0,
+	KEY_PREVIOUS,		/* VCR mode on Zenith */
+	KEY_REWIND,
+	0,
+	KEY_FASTFORWARD,
+	KEY_PLAY, KEY_STOP,
+	KEY_RECORD,
+	KEY_TUNER,		/* TV/VCR on Zenith */
+	0,
+	KEY_C,
+	0,
+	KEY_EXIT,
+	0,
+	KEY_TUNER,		/* VCR mode on Zenith */
+	0,
+};
+
+
+#define __COMPILE_SAA7146_STUFF__
+#include "saa7146.c"
+
+#ifndef BORROWED_FROM_AV7110_H_BUT_REALLY_BELONGS_IN_SAA7146_DEFS_H
+/* DEBI transfer mode defs */
+
+#define DEBINOSWAP 0x000e0000
+#define DEBISWAB   0x001e0000
+#define DEBISWAP   0x002e0000
+
+typedef enum GPIO_MODE {
+	GPIO_INPUT = 0x00,
+	GPIO_IRQHI = 0x10,
+	GPIO_IRQLO = 0x20,
+	GPIO_IRQHL = 0x30,
+	GPIO_OUTLO = 0x40,
+	GPIO_OUTHI = 0x50
+} GPIO_MODE;
+#endif
+
+
+#ifndef BORROWED_FROM_AV7110_C_BUT_REALLY_BELONGS_IN_SAA7146_CORE_C
+/* This DEBI code is based on the Stradis driver 
+   by Nathan Laredo <laredo@gnu.org> */
+
+static
+int wait_for_debi_done(struct saa7146 *saa)
+{
+	int start = jiffies;
+
+	/* wait for registers to be programmed */
+	while (1) {
+		if (saa7146_read(saa->mem, MC2) & 2)
+			break;
+		if (jiffies - start > HZ / 20) {
+			printk(KERN_WARNING __FUNCTION__
+			       ": timed out while waiting"
+			       " for registers getting programmed\n");
+			return -ETIMEDOUT;
+		}
+	}
+
+	/* wait for transfer to complete */
+	start = jiffies;
+	while (1) {
+		if (!(saa7146_read(saa->mem, PSR) & SPCI_DEBI_S))
+			break;
+		saa7146_read(saa->mem, MC2);
+		if (jiffies - start > HZ / 4) {
+			printk(KERN_WARNING __FUNCTION__
+			       ": timed out while waiting"
+			       " for transfer completion\n");
+			return -ETIMEDOUT;
+		}
+	}
+
+	return 0;
+}
+
+static inline u32 debiread(struct saa7146 *saa, u32 config, int addr,
+			   int count)
+{
+	u32 result = 0;
+
+	if (count > 4 || count <= 0)
+		return 0;
+	if (wait_for_debi_done(saa) < 0)
+		return 0;
+	saa7146_write(saa->mem, DEBI_COMMAND,
+		      (count << 17) | 0x10000 | (addr & 0xffff));
+	saa7146_write(saa->mem, DEBI_CONFIG, config);
+	saa7146_write(saa->mem, MC2, (2 << 16) | 2);
+	wait_for_debi_done(saa);
+	result = saa7146_read(saa->mem, DEBI_AD);
+	result &= (0xffffffffUL >> ((4 - count) * 8));
+	return result;
+}
+
+/* DEBI during interrupt */
+
+static inline u32
+irdebi(struct saa7146 *saa, u32 config, int addr, u32 val, int count)
+{
+	u32 res;
+	res = debiread(saa, config, addr, count);
+	return res;
+}
+#endif
+
+
+static void msp430_ir_debounce(unsigned long data)
+{
+	struct input_dev *dev = (struct input_dev *) data;
+	if (dev->rep[0] == 0 || dev->rep[0] == ~0) {
+		input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0);	/* BREAK */
+		return;
+	}
+	dev->rep[0] = 0;
+	dev->timer.expires = jiffies + HZ * 350 / 1000;
+	add_timer(&dev->timer);
+	input_event(dev, EV_KEY, key_map[dev->repeat_key], 2);	/* REPEAT */
+}
+
+
+static void msp430_ir_interrupt(struct saa7146 *saa, u32 isr, void *data)
+{
+	unsigned int code = irdebi(saa, DEBINOSWAP, 0x1234, 0, 2) >> 8;
+	if (code & 0x40) {
+		struct input_dev *dev = (struct input_dev *) data;
+		code &= 0x3f;
+		if (timer_pending(&dev->timer)) {
+			if (code == dev->repeat_key) {
+				++dev->rep[0];
+				return;
+			}
+			del_timer(&dev->timer);
+			input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0);	/* BREAK */
+		}
+		if (!key_map[code]) {
+			printk(KERN_ERR __FUNCTION__
+			       ": no key for %02x!\n", code);
+			return;
+		}
+		/* initialize debounce and repeat */
+		dev->repeat_key = code;
+		dev->rep[0] = ~0;	/* Zenith remote _always_ sends 2 sequences */
+		dev->timer.expires = jiffies + HZ * 350 / 1000;	/* 350 milliseconds */
+		add_timer(&dev->timer);
+		input_event(dev, EV_KEY, key_map[code], !0);	/* MAKE */
+	}
+}
+
+
+static int msp430_ir_attach(struct saa7146 *saa, void **priv_ptr)
+{
+	struct input_dev *dev;
+	int n;
+
+	if (saa->card_type != DVB_CARD_TT_BUDGET_CI) {
+		printk(KERN_ERR __FUNCTION__ ": rejected %s type=%d\n",
+		       saa->name, saa->card_type);
+		return -ENOENT;
+	}
+
+	if ((dev =
+	     (struct input_dev *) kmalloc(sizeof(struct input_dev),
+					  GFP_KERNEL)) == 0) {
+		printk(KERN_ERR __FUNCTION__ ": OOM!\n");
+		return -ENOMEM;
+	}
+	memset(dev, 0, sizeof(*dev));
+	dev->name = saa->name;
+	set_bit(EV_KEY, dev->evbit);
+	for (n = sizeof(key_map) / sizeof(*key_map); --n >= 0;)
+		if (key_map[n])
+			set_bit(key_map[n], dev->keybit);
+	input_register_device(dev);
+	/* input_dev timer and repeat stuff used only if EV_REP, initialized above, reuse */
+	dev->timer.function = msp430_ir_debounce;
+	*priv_ptr = dev;
+
+	saa7146_write(saa->mem, IER,
+		      saa7146_read(saa->mem, IER) | MASK_06);
+	gpio_set(saa, 3, GPIO_IRQHI);
+
+	printk(KERN_INFO "msp430_ir: attached %s\n", saa->name);
+	return 0;
+}
+
+
+static int msp430_ir_detach(struct saa7146 *saa, void **priv_ptr)
+{
+	struct input_dev *dev = (struct input_dev *) *priv_ptr;
+	saa7146_write(saa->mem, IER,
+		      saa7146_read(saa->mem, IER) & ~MASK_06);
+	gpio_set(saa, 3, GPIO_INPUT);
+	gpio_set(saa, 2, GPIO_INPUT);
+	if (del_timer(&dev->timer))
+		input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0);	/* BREAK */
+	input_unregister_device(dev);
+	return 0;
+}
+
+
+static void msp430_ir_inc_use(struct saa7146 *saa)
+{
+	MOD_INC_USE_COUNT;
+}
+
+
+static void msp430_ir_dec_use(struct saa7146 *saa)
+{
+	MOD_DEC_USE_COUNT;
+}
+
+
+static struct saa7146_extension msp430_ir_extension = {
+	name:"msp430_ir",
+	handles_irqs:MASK_06,
+	irq_handler:msp430_ir_interrupt,
+	attach:msp430_ir_attach,
+	detach:msp430_ir_detach,
+	inc_use:msp430_ir_inc_use,
+	dec_use:msp430_ir_dec_use,
+};
+
+
+static int __init msp430_ir_init(void)
+{
+	int ret;
+	printk(KERN_INFO
+	       "msp430_ir: Copyright (c) 2003 Helius, Inc.  All Rights Reserved.\n");
+
+	if ((ret = saa7146_add_extension(&msp430_ir_extension)))
+		printk(KERN_ERR
+		       "msp430_ir: add_extension failed with %d\n", ret);
+	return ret;
+}
+
+
+static void __exit msp430_ir_exit(void)
+{
+	int ret;
+	if ((ret = saa7146_del_extension(&msp430_ir_extension)))
+		printk(KERN_ERR
+		       "msp430_ir: del_extension failed with %d\n", ret);
+}
+
+module_init(msp430_ir_init);
+module_exit(msp430_ir_exit);

Home | Main Index | Thread Index