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