diff options
author | Holger Waechtler <devnull@localhost> | 2003-02-14 14:39:29 +0000 |
---|---|---|
committer | Holger Waechtler <devnull@localhost> | 2003-02-14 14:39:29 +0000 |
commit | 50b063d2db9c9df8cb5c22caade41de829021d61 (patch) | |
tree | 212872cf2b5c2fffef5478c8dbaccc3035c36edd /linux/drivers/media | |
parent | 2a205e6a6e1a42bac744aaa6e6acb104f6429dc7 (diff) | |
download | mediapointer-dvb-s2-50b063d2db9c9df8cb5c22caade41de829021d61.tar.gz mediapointer-dvb-s2-50b063d2db9c9df8cb5c22caade41de829021d61.tar.bz2 |
created a new budget_ci.o module, add msp430 IR support
Diffstat (limited to 'linux/drivers/media')
-rw-r--r-- | linux/drivers/media/dvb/ttpci-budget/Kconfig | 16 | ||||
-rw-r--r-- | linux/drivers/media/dvb/ttpci-budget/Makefile | 2 | ||||
-rw-r--r-- | linux/drivers/media/dvb/ttpci-budget/budget-av.c | 302 | ||||
-rw-r--r-- | linux/drivers/media/dvb/ttpci-budget/budget-ci.c | 437 | ||||
-rw-r--r-- | linux/drivers/media/dvb/ttpci-budget/budget-core.c | 309 | ||||
-rw-r--r-- | linux/drivers/media/dvb/ttpci-budget/budget.c | 198 | ||||
-rw-r--r-- | linux/drivers/media/dvb/ttpci-budget/budget.h | 18 |
7 files changed, 894 insertions, 388 deletions
diff --git a/linux/drivers/media/dvb/ttpci-budget/Kconfig b/linux/drivers/media/dvb/ttpci-budget/Kconfig index 5ee103260..c40dad9f5 100644 --- a/linux/drivers/media/dvb/ttpci-budget/Kconfig +++ b/linux/drivers/media/dvb/ttpci-budget/Kconfig @@ -14,6 +14,22 @@ config DVB_BUDGET If you want to compile it as a module, say M here and read <file:Documentation/modules.txt>. +config DVB_BUDGET_CI + tristate "Budget cards with onboard CI connector" + depends on VIDEO_DEV && DVB_CORE && DVB_BUDGET + help + Support for simple SAA7146 based DVB cards + (so called Budget- or Nova-PCI cards) without onboard + MPEG2 decoder, but with onboard Common Interface connector. + + Say Y if you own such a card and want to use it. + + This driver is available as a module called + dvb-ttpci-budget-av.o ( = code which can be inserted in + and removed from the running kernel whenever you want). + If you want to compile it as a module, say M + here and read <file:Documentation/modules.txt>. + config DVB_BUDGET_AV tristate "Budget cards with analog video inputs" depends on VIDEO_DEV && DVB_CORE && DVB_BUDGET diff --git a/linux/drivers/media/dvb/ttpci-budget/Makefile b/linux/drivers/media/dvb/ttpci-budget/Makefile index a5a8c7e8f..6fab02cda 100644 --- a/linux/drivers/media/dvb/ttpci-budget/Makefile +++ b/linux/drivers/media/dvb/ttpci-budget/Makefile @@ -4,8 +4,10 @@ dvb-ttpci-budget-objs := budget.o dvb-ttpci-budget-av-objs := budget-av.o +dvb-ttpci-budget-ci-objs := budget-ci.o obj-$(CONFIG_DVB_BUDGET) += budget-core.o dvb-ttpci-budget.o +obj-$(CONFIG_DVB_BUDGET_CI) += budget-core.o dvb-ttpci-budget-ci.o obj-$(CONFIG_DVB_BUDGET_AV) += budget-core.o dvb-ttpci-budget-av.o EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -I$(src)/../../common/ -I$(src)/../../common/saa7146 diff --git a/linux/drivers/media/dvb/ttpci-budget/budget-av.c b/linux/drivers/media/dvb/ttpci-budget/budget-av.c index 78c977900..66173a760 100644 --- a/linux/drivers/media/dvb/ttpci-budget/budget-av.c +++ b/linux/drivers/media/dvb/ttpci-budget/budget-av.c @@ -37,23 +37,10 @@ #define KBUILD_MODNAME budget_av #endif -static struct saa7146_extension budget_extension; - -MAKE_BUDGET_INFO(knc1, "KNC1 DVB-S", BUDGET_KNC1); -static -struct pci_device_id devices[] = { - MAKE_EXTENSION_PCI(knc1, 0x1131, 0x4f56), - { - .vendor = 0, - } -}; - -struct budget_av_data -{ +struct budget_av { + struct budget budget; struct video_device vd; - int registered; - int cur_input; }; @@ -61,32 +48,36 @@ struct budget_av_data * INITIALIZATION ****************************************************************************/ -static inline void ddelay(int i) +static inline +void ddelay(int i) { current->state=TASK_INTERRUPTIBLE; schedule_timeout((HZ*i)/100); } -static inline u8 -i2c_readreg(struct dvb_i2c_bus *i2c, u8 id, u8 reg) + +static +u8 i2c_readreg (struct dvb_i2c_bus *i2c, u8 id, u8 reg) { - u8 mm1[] = {0x00}; - u8 mm2[] = {0x00}; - struct i2c_msg msgs[2]; - - msgs[0].flags=0; - msgs[1].flags=I2C_M_RD; - msgs[0].addr=msgs[1].addr=id/2; - mm1[0]=reg; - msgs[0].len=1; msgs[1].len=1; - msgs[0].buf=mm1; msgs[1].buf=mm2; - i2c->xfer(i2c, msgs, 2); - - return mm2[0]; + u8 mm1[] = {0x00}; + u8 mm2[] = {0x00}; + struct i2c_msg msgs[2]; + + msgs[0].flags = 0; + msgs[1].flags = I2C_M_RD; + msgs[0].addr = msgs[1].addr=id/2; + mm1[0] = reg; + msgs[0].len = 1; msgs[1].len = 1; + msgs[0].buf = mm1; msgs[1].buf = mm2; + + i2c->xfer(i2c, msgs, 2); + + return mm2[0]; } -static inline int -i2c_writereg(struct dvb_i2c_bus *i2c, u8 id, u8 reg, u8 val) + +static +int i2c_writereg (struct dvb_i2c_bus *i2c, u8 id, u8 reg, u8 val) { u8 msg[2]={ reg, val }; struct i2c_msg msgs; @@ -98,7 +89,9 @@ i2c_writereg(struct dvb_i2c_bus *i2c, u8 id, u8 reg, u8 val) return i2c->xfer (i2c, &msgs, 1); } -static const u8 saa7113_tab[] = { + +static const +u8 saa7113_tab[] = { 0x01, 0x08, 0x02, 0xc0, 0x03, 0x33, @@ -127,109 +120,128 @@ static const u8 saa7113_tab[] = { 0xff }; -static int -init_saa7113(struct budget_s *budget) + +static +int saa7113_init (struct budget_av *budget_av) { - const u8 *data=saa7113_tab; + struct budget *budget = &budget_av->budget; + const u8 *data = saa7113_tab; - if (i2c_writereg(budget->i2c_bus, 0x4a, 0x01, 0x08)!=1) { + if (i2c_writereg (budget->i2c_bus, 0x4a, 0x01, 0x08) != 1) { DEB_D(("saa7113: not found on KNC card\n")); - return -1; + return -ENODEV; } + INFO(("saa7113: detected and initializing\n")); - while (*data!=0xff) { + + while (*data != 0xff) { i2c_writereg(budget->i2c_bus, 0x4a, *data, *(data+1)); - data+=2; + data += 2; } - DEB_D(("saa7113: status=%02x\n", i2c_readreg(budget->i2c_bus, 0x4a, 0x1f))); + + DEB_D(("saa7113: status=%02x\n", + i2c_readreg(budget->i2c_bus, 0x4a, 0x1f))); + + return 0; +} + + +static +int saa7113_setinput (struct budget_av *budget_av, int input) +{ + struct budget *budget = &budget_av->budget; + + if (input == 1) { + i2c_writereg(budget->i2c_bus, 0x4a, 0x02, 0xc7); + i2c_writereg(budget->i2c_bus, 0x4a, 0x09, 0x80); + } else if (input == 0) { + i2c_writereg(budget->i2c_bus, 0x4a, 0x02, 0xc0); + i2c_writereg(budget->i2c_bus, 0x4a, 0x09, 0x00); + } else + return -EINVAL; + + budget_av->cur_input = input; return 0; } + static -int av_detach(struct saa7146_dev* dev) +int budget_av_detach (struct saa7146_dev *dev) { - struct budget_s *budget = (struct budget_s*)dev->ext_priv; - struct budget_av_data *data = budget->priv; + struct budget_av *budget_av = (struct budget_av*) dev->ext_priv; + int err; DEB_EE(("dev: %p\n",dev)); + saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO); + ddelay(20); - if( 0 != data->registered ) { - saa7146_unregister_device(&data->vd,dev); - data->registered = 0; - } - if( NULL != budget->priv ) { - kfree(data); - budget->priv = NULL; - - } - - return budget_detach(dev); -} + saa7146_unregister_device (&budget_av->vd, dev); -void knc1_setinput(struct budget_s *budget, int i) -{ - if (i) { - i2c_writereg(budget->i2c_bus, 0x4a, 0x02, 0xc7); - i2c_writereg(budget->i2c_bus, 0x4a, 0x09, 0x80); - } else { - i2c_writereg(budget->i2c_bus, 0x4a, 0x02, 0xc0); - i2c_writereg(budget->i2c_bus, 0x4a, 0x09, 0x00); - } + err = ttpci_budget_deinit (&budget_av->budget); + + kfree (budget_av); + + return err; } + static -int av_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info) +int budget_av_attach (struct saa7146_dev* dev, + struct saa7146_pci_extension_data *info) { - struct budget_s *budget = NULL; - struct budget_av_data *data = NULL; + struct budget_av *budget_av; struct budget_info *bi = info->ext_priv; - + int err; + DEB_EE(("dev: %p\n",dev)); - if (bi->type != BUDGET_KNC1) { - return -1; + + if (bi->type != BUDGET_KNC1) { + return -ENODEV; } - data = kmalloc(sizeof(struct budget_av_data), GFP_KERNEL); - if( NULL == data ) { + if (!(budget_av = kmalloc(sizeof(struct budget_av), GFP_KERNEL))) return -ENOMEM; + + memset(budget_av, 0, sizeof(struct budget_av)); + + if ((err = ttpci_budget_init(&budget_av->budget, dev, info))) { + kfree(budget_av); + return err; } - memset(data,0,sizeof(*data)); - - if( 0 != budget_attach(dev,info)) { - kfree(data); - return -1; - } - budget = (struct budget_s*)dev->ext_priv; - budget->priv = data; - + + dev->ext_priv = budget_av; + /* knc1 initialization */ saa7146_write(dev, DD1_STREAM_B, 0x04000000); saa7146_write(dev, DD1_INIT, 0x07000600); - saa7146_write(dev, MC2, - MASK_09 | MASK_25 | MASK_10 | MASK_26); + saa7146_write(dev, MC2, MASK_09 | MASK_25 | MASK_10 | MASK_26); //test_knc_ci(av7110); saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTHI); ddelay(50); - if( 0 != init_saa7113(budget)) { - av_detach(dev); - return -1; + + if ((err = saa7113_init (budget_av))) { + budget_av_detach(dev); + return err; } - + saa7146_vv_init(dev); - if( 0 != saa7146_register_device(&data->vd, dev, "knc1", VFL_TYPE_GRABBER)) { + if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1", + VFL_TYPE_GRABBER))) + { ERR(("cannot register capture v4l2 device.\n")); - av_detach(dev); - return -1; + budget_av_detach(dev); + return err; } - data->registered = 1; - + /* beware: this modifies dev->vv ... */ - saa7146_set_hps_source_and_sync(dev, SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A); - knc1_setinput(budget, 0); + saa7146_set_hps_source_and_sync(dev, SAA7146_HPS_SOURCE_PORT_A, + SAA7146_HPS_SYNC_PORT_A); + + saa7113_setinput (budget_av, 0); /* what is this? since we don't support open()/close() notifications, we simply put this into the release handler... */ @@ -239,30 +251,31 @@ int av_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info) /* fixme: find some sane values here... */ saa7146_write(dev, PCI_BT_V1, 0x1c00101f); - // FIXME: cope with error here! - budget_register(budget); - printk(KERN_INFO "budget-av: found budget card w/ video-in '%s'.\n",budget->card->name); - return 0; } + + #define KNC1_INPUTS 2 static struct v4l2_input knc1_inputs[KNC1_INPUTS] = { - { 0, "Composite", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { 1, "S-Video", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, + { 0, "Composite", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, + { 1, "S-Video", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, }; -static struct saa7146_extension_ioctls ioctls[] = { + +static +struct saa7146_extension_ioctls ioctls[] = { { VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE }, { VIDIOC_G_INPUT, SAA7146_EXCLUSIVE }, { VIDIOC_S_INPUT, SAA7146_EXCLUSIVE }, { 0, 0 } }; -static int av_ioctl(struct saa7146_dev *dev, unsigned int cmd, void *arg) + +static +int av_ioctl(struct saa7146_dev *dev, unsigned int cmd, void *arg) { - struct budget_s *budget = (struct budget_s*)dev->ext_priv; - struct budget_av_data *data = budget->priv; + struct budget_av *budget_av = (struct budget_av*) dev->ext_priv; /* struct saa7146_vv *vv = dev->vv_data; */ @@ -275,18 +288,14 @@ static int av_ioctl(struct saa7146_dev *dev, unsigned int cmd, void *arg) if( i->index < 0 || i->index >= KNC1_INPUTS) { return -EINVAL; } - if( BUDGET_KNC1 == budget->card->type ) { - memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input)); - } else { - return -EINVAL; - } - + memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input)); return 0; } case VIDIOC_G_INPUT: { int *input = (int *)arg; - *input = data->cur_input; + + *input = budget_av->cur_input; DEB_EE(("VIDIOC_G_INPUT %d.\n",*input)); return 0; @@ -294,22 +303,8 @@ static int av_ioctl(struct saa7146_dev *dev, unsigned int cmd, void *arg) case VIDIOC_S_INPUT: { int input = *(int *)arg; - - DEB_EE(("VIDIOC_S_INPUT %d.\n",input)); - - if (input < 0 || input > 1) { - return -EINVAL; - } - - if( BUDGET_KNC1 == budget->card->type ) { - knc1_setinput(budget, input); - } else { - return -EINVAL; - } - - data->cur_input = input; - - return 0; + DEB_EE(("VIDIOC_S_INPUT %d.\n", input)); + return saa7113_setinput (budget_av, input); } default: /* @@ -320,11 +315,13 @@ static int av_ioctl(struct saa7146_dev *dev, unsigned int cmd, void *arg) return 0; } -static struct saa7146_standard standard[] = { +static +struct saa7146_standard standard[] = { { "PAL", V4L2_STD_PAL, SAA7146_PAL_VALUES }, { "NTSC", V4L2_STD_NTSC, SAA7146_NTSC_VALUES }, }; + static struct saa7146_ext_vv vv_data = { .inputs = 2, @@ -336,21 +333,41 @@ struct saa7146_ext_vv vv_data = { .ioctl = av_ioctl, }; + + +static struct saa7146_extension budget_extension; + + +MAKE_BUDGET_INFO(knc1, "KNC1 DVB-S", BUDGET_KNC1); + +static +struct pci_device_id pci_tbl [] = { + MAKE_EXTENSION_PCI(knc1, 0x1131, 0x4f56), + { + .vendor = 0, + } +}; + + + static struct saa7146_extension budget_extension = { .name = "budget dvb /w video in\0", - .pci_tbl = &devices[0], + .pci_tbl = pci_tbl, + .module = THIS_MODULE, + .attach = budget_av_attach, + .detach = budget_av_detach, + .ext_vv_data = &vv_data, - .attach = av_attach, - .detach = av_detach, - .irq_mask = MASK_07, - .irq_func = budget_irq, + + .irq_mask = MASK_10, + .irq_func = ttpci_budget_irq10_handler, }; static -int __init budget_init(void) +int __init budget_av_init(void) { DEB_EE((".\n")); @@ -362,16 +379,17 @@ int __init budget_init(void) static -void __exit budget_exit(void) +void __exit budget_av_exit(void) { DEB_EE((".\n")); saa7146_unregister_extension(&budget_extension); } -module_init(budget_init); -module_exit(budget_exit); +module_init(budget_av_init); +module_exit(budget_av_exit); -MODULE_DESCRIPTION("driver for the SAA7146 based so-called budget PCI DVB cards by " - "Siemens, Technotrend, Hauppauge"); -MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, others"); MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others"); +MODULE_DESCRIPTION("driver for the SAA7146 based so-called " + "budget PCI DVB w/ analog input (e.g. the KNC cards)"); + diff --git a/linux/drivers/media/dvb/ttpci-budget/budget-ci.c b/linux/drivers/media/dvb/ttpci-budget/budget-ci.c new file mode 100644 index 000000000..d072e9b69 --- /dev/null +++ b/linux/drivers/media/dvb/ttpci-budget/budget-ci.c @@ -0,0 +1,437 @@ +/* + * budget-ci.c: driver for the SAA7146 based Budget DVB cards + * + * Compiled from various sources by Michael Hunold <michael@mihu.de> + * + * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de> + * + * Copyright (C) 1999-2002 Ralph Metzler + * & Marcus Metzler for convergence integrated media GmbH + * + * msp430 IR support contributed by Jack Thomasson <jkt@Helius.COM> + * + * 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. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + * + * + * the project's page is at http://www.linuxtv.org/dvb/ + */ + +#include "budget.h" +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) + #define KBUILD_MODNAME budget +#endif + + +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/interrupt.h> +#include <linux/input.h> + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) +#include "input_fake.h" +#endif + + + +struct budget_ci { + struct budget budget; + struct input_dev input_dev; + struct tasklet_struct msp430_irq_tasklet; +}; + + + +#ifndef BORROWED_FROM_AV7110_H_BUT_REALLY_BELONGS_IN_SAA7146_DEFS_H + +#define DEBINOSWAP 0x000e0000 +#define GPIO_IRQHI 0x10 +#define GPIO_INPUT 0x00 + +void gpio_set(struct saa7146_dev* saa, u8 pin, u8 data) +{ + u32 value = 0; + + /* sanity check */ + if(pin > 3) + return; + + /* read old register contents */ + value = saa7146_read(saa, GPIO_CTRL ); + + value &= ~(0xff << (8*pin)); + value |= (data << (8*pin)); + + saa7146_write(saa, GPIO_CTRL, value); +} + + + +static +int wait_for_debi_done(struct saa7146_dev *saa) +{ + int start = jiffies; + + /* wait for registers to be programmed */ + while (1) { + if (saa7146_read(saa, MC2) & 2) + break; + if (jiffies - start > HZ / 20) { + printk ("DVB (%s): timed out while waiting" + " for registers getting programmed\n", + __FUNCTION__); + return -ETIMEDOUT; + } + } + + /* wait for transfer to complete */ + start = jiffies; + while (1) { + if (!(saa7146_read(saa, PSR) & SPCI_DEBI_S)) + break; + saa7146_read(saa, MC2); + if (jiffies - start > HZ / 4) { + printk ("DVB (%s): timed out while waiting" + " for transfer completion\n", + __FUNCTION__); + return -ETIMEDOUT; + } + } + + return 0; +} + + +static +u32 debiread (struct saa7146_dev *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, DEBI_COMMAND, + (count << 17) | 0x10000 | (addr & 0xffff)); + + saa7146_write(saa, DEBI_CONFIG, config); + saa7146_write(saa, MC2, (2 << 16) | 2); + + wait_for_debi_done(saa); + + result = saa7146_read(saa, DEBI_AD); + result &= (0xffffffffUL >> ((4 - count) * 8)); + + return result; +} + + + +/* DEBI during interrupt */ +static inline +u32 irdebi(struct saa7146_dev *saa, u32 config, int addr, u32 val, int count) +{ + u32 res; + res = debiread(saa, config, addr, count); + return res; +} +#endif + + + + +/* 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, +}; + + +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); + 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 (unsigned long data) +{ + struct budget_ci *budget_ci = (struct budget_ci*) data; + struct saa7146_dev *saa = budget_ci->budget.dev; + struct input_dev *dev = &budget_ci->input_dev; + unsigned int code = irdebi(saa, DEBINOSWAP, 0x1234, 0, 2) >> 8; + + if (code & 0x40) { + 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); + } + + if (!key_map[code]) { + printk ("DVB (%s): no key for %02x!\n", + __FUNCTION__, code); + return; + } + + /* initialize debounce and repeat */ + dev->repeat_key = code; + /* Zenith remote _always_ sends 2 sequences */ + dev->rep[0] = ~0; + /* 350 milliseconds */ + dev->timer.expires = jiffies + HZ * 350 / 1000; + /* MAKE */ + input_event(dev, EV_KEY, key_map[code], !0); + } +} + + +static +int msp430_ir_init (struct budget_ci *budget_ci) +{ + struct saa7146_dev *saa = budget_ci->budget.dev; + int i; + + memset(&budget_ci->input_dev, 0, sizeof(struct input_dev)); + + budget_ci->input_dev.name = saa->name; + + set_bit(EV_KEY, budget_ci->input_dev.evbit); + + for (i=0; i<sizeof(key_map)/sizeof(*key_map); i++) + if (key_map[i]) + set_bit(key_map[i], budget_ci->input_dev.keybit); + + input_register_device(&budget_ci->input_dev); + + budget_ci->input_dev.timer.function = msp430_ir_debounce; + + saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_06); + + gpio_set(saa, 3, GPIO_IRQHI); + + return 0; +} + + +static +void msp430_ir_deinit (struct budget_ci *budget_ci) +{ + struct saa7146_dev *saa = budget_ci->budget.dev; + struct input_dev *dev = &budget_ci->input_dev; + + saa7146_write(saa, IER, saa7146_read(saa, 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); + + input_unregister_device(dev); +} + + +static +void budget_ci_irq (struct saa7146_dev *dev, u32 *isr) +{ + struct budget_ci *budget_ci = (struct budget_ci*) dev->ext_priv; + + DEB_EE(("dev: %p, budget_ci: %p\n", dev, budget_ci)); + + if (*isr & MASK_06) + tasklet_schedule (&budget_ci->msp430_irq_tasklet); + + if (*isr & MASK_10) + ttpci_budget_irq10_handler (dev, isr); +} + + + +static +int budget_ci_attach (struct saa7146_dev* dev, + struct saa7146_pci_extension_data *info) +{ + struct budget_ci *budget_ci; + int err; + + DEB_EE(("budget_ci: %p\n", budget_ci)); + + if (!(budget_ci = kmalloc (sizeof(struct budget_ci), GFP_KERNEL))) + return -ENOMEM; + + if ((err = ttpci_budget_init (&budget_ci->budget, dev, info))) { + kfree (budget_ci); + return err; + } + + dev->ext_priv = budget_ci; + + tasklet_init (&budget_ci->msp430_irq_tasklet, msp430_ir_interrupt, + (unsigned long) budget_ci); + + msp430_ir_init (budget_ci); + + return 0; +} + + + +static +int budget_ci_detach (struct saa7146_dev* dev) +{ + struct budget_ci *budget_ci = (struct budget_ci*) dev->ext_priv; + int err; + + err = ttpci_budget_deinit (&budget_ci->budget); + + tasklet_kill (&budget_ci->msp430_irq_tasklet); + + msp430_ir_deinit (budget_ci); + + kfree (budget_ci); + + return err; +} + + + +static struct saa7146_extension budget_extension; + +MAKE_BUDGET_INFO(ttbci, "TT-Budget/WinTV-NOVA-CI PCI", BUDGET_TT_HW_DISEQC); + +static +struct pci_device_id pci_tbl[] = { + MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c), + MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100f), + { + .vendor = 0, + } +}; + + + +static +struct saa7146_extension budget_extension = { + .name = "budget_ci dvb\0", + .flags = 0, + .ext_vv_data = NULL, + + .module = THIS_MODULE, + .pci_tbl = &pci_tbl[0], + .attach = budget_ci_attach, + .detach = budget_ci_detach, + + .irq_mask = MASK_06 | MASK_10, + .irq_func = budget_ci_irq, +}; + + +static +int __init budget_ci_init(void) +{ + if (saa7146_register_extension(&budget_extension)) + return -ENODEV; + + return 0; +} + + +static +void __exit budget_ci_exit(void) +{ + DEB_EE((".\n")); + saa7146_unregister_extension(&budget_extension); +} + +module_init(budget_ci_init); +module_exit(budget_ci_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, others"); +MODULE_DESCRIPTION("driver for the SAA7146 based so-called " + "budget PCI DVB cards w/ CI-module produced by " + "Siemens, Technotrend, Hauppauge"); + diff --git a/linux/drivers/media/dvb/ttpci-budget/budget-core.c b/linux/drivers/media/dvb/ttpci-budget/budget-core.c index c656bd561..abb1b9f39 100644 --- a/linux/drivers/media/dvb/ttpci-budget/budget-core.c +++ b/linux/drivers/media/dvb/ttpci-budget/budget-core.c @@ -11,8 +11,8 @@ int budget_patch = 0; ****************************************************************************/ /* this is videobuf_vmalloc_to_sg() from video-buf.c */ -struct scatterlist* -vmalloc_to_sg(unsigned char *virt, int nr_pages) +static +struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages) { struct scatterlist *sglist; struct page *pg; @@ -49,8 +49,8 @@ static inline void ddelay(int i) * TT budget / WinTV Nova ****************************************************************************/ -static int -TTBStop(struct budget_s *budget) +static +int stop_ts_capture(struct budget *budget) { DEB_EE(("budget: %p\n",budget)); @@ -62,8 +62,9 @@ TTBStop(struct budget_s *budget) return 0; } -static int -TTBStart(struct budget_s *budget) + +static +int start_ts_capture (struct budget *budget) { struct saa7146_dev *dev=budget->dev; @@ -103,10 +104,12 @@ TTBStart(struct budget_s *budget) return ++budget->feeding; } -static void vpeirq (unsigned long data) + +static +void vpeirq (unsigned long data) { - struct budget_s *budget = (struct budget_s*) data; - u8 *mem=(u8 *)(budget->grabbing); + struct budget *budget = (struct budget*) data; + u8 *mem = (u8 *)(budget->grabbing); u32 olddma = budget->ttbp; u32 newdma = saa7146_read(budget->dev, PCI_VDP3); @@ -135,151 +138,39 @@ static void vpeirq (unsigned long data) } } -inline static void -Set22K(struct budget_s *budget, int state) -{ - struct saa7146_dev *dev=budget->dev; - DEB_EE(("budget: %p\n",budget)); - saa7146_setgpio(dev, 3, (state ? SAA7146_GPIO_OUTHI : SAA7146_GPIO_OUTLO)); -} - - -/* Diseqc functions only for TT Budget card */ -/* taken from the Skyvision DVB driver by - Ralph Metzler <rjkm@metzlerbros.de> */ - -inline static void -DiseqcSendBit(struct budget_s *budget, int data) -{ - struct saa7146_dev *dev=budget->dev; - DEB_EE(("budget: %p\n",budget)); - - saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); - udelay(data ? 500 : 1000); - saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); - udelay(data ? 1000 : 500); -} - -static void -DiseqcSendByte(struct budget_s *budget, int data) -{ - int i, par=1, d; - - DEB_EE(("budget: %p\n",budget)); - - for (i=7; i>=0; i--) - { - d=(data>>i)&1; - par^=d; - DiseqcSendBit(budget, d); - } - DiseqcSendBit(budget, par); -} - -inline static int -SendDiSEqCMsg(struct budget_s *budget, int len, u8 *msg, int burst) -{ - struct saa7146_dev *dev=budget->dev; - int i; - - DEB_EE(("budget: %p\n",budget)); - - saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); - mdelay(16); - - for (i=0; i<len; i++) - DiseqcSendByte(budget, msg[i]); - - mdelay(16); - - if (burst!=-1) { - if (burst) - DiseqcSendByte(budget, 0xff); - else { - saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); - udelay(12500); - saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); - } - ddelay(2); - } - - return 0; -} /**************************************************************************** * DVB API SECTION ****************************************************************************/ -static int -budget_start_feed(struct dvb_demux_feed *feed) +static +int budget_start_feed(struct dvb_demux_feed *feed) { struct dvb_demux *demux = feed->demux; - struct budget_s *budget = (struct budget_s *) demux->priv; + struct budget *budget = (struct budget*) demux->priv; DEB_EE(("budget: %p\n",budget)); if (!demux->dmx.frontend) return -EINVAL; - return TTBStart(budget); + return start_ts_capture (budget); } -static int -budget_stop_feed(struct dvb_demux_feed *feed) +static +int budget_stop_feed(struct dvb_demux_feed *feed) { struct dvb_demux *demux = feed->demux; - struct budget_s *budget = (struct budget_s *) demux->priv; + struct budget *budget = (struct budget *) demux->priv; DEB_EE(("budget: %p\n",budget)); - return TTBStop(budget); + return stop_ts_capture (budget); } -/****************************************************************************** - * SEC device file operations - ******************************************************************************/ static -int budget_diseqc_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) -{ - struct budget_s *budget = fe->before_after_data; - - DEB_EE(("budget: %p\n",budget)); - - switch (cmd) { - case FE_SET_TONE: - switch ((fe_sec_tone_mode_t) arg) { - case SEC_TONE_ON: - Set22K (budget, 1); - break; - case SEC_TONE_OFF: - Set22K (budget, 0); - break; - default: - return -EINVAL; - }; - break; - - case FE_DISEQC_SEND_MASTER_CMD: - { - struct dvb_diseqc_master_cmd *cmd = arg; - - SendDiSEqCMsg (budget, cmd->msg_len, cmd->msg, 0); - break; - } - - case FE_DISEQC_SEND_BURST: - SendDiSEqCMsg (budget, 0, NULL, (int) arg); - break; - - default: - return -EOPNOTSUPP; - }; - - return 0; -} - -int budget_register(struct budget_s *budget) +int budget_register(struct budget *budget) { int ret; dmx_frontend_t *dvbfront=&budget->hw_frontend; @@ -287,81 +178,68 @@ int budget_register(struct budget_s *budget) DEB_EE(("budget: %p\n",budget)); - if (budget->registered) - return -1; - - budget->registered=1; - - /* init DiSEqC stuff if necessary */ - if(budget->card->type == BUDGET_TT) - dvb_add_frontend_ioctls (budget->dvb_adapter, budget_diseqc_ioctl, NULL, budget); - memcpy(budget->demux_id, "demux0_0", 9); budget->demux_id[5] = budget->dvb_adapter->num + '0'; dvbdemux->priv = (void *) budget; - dvbdemux->filternum=256; - dvbdemux->feednum=256; - dvbdemux->start_feed=budget_start_feed; - dvbdemux->stop_feed=budget_stop_feed; - dvbdemux->write_to_decoder=NULL; + dvbdemux->filternum = 256; + dvbdemux->feednum = 256; + dvbdemux->start_feed = budget_start_feed; + dvbdemux->stop_feed = budget_stop_feed; + dvbdemux->write_to_decoder = NULL; - dvbdemux->dmx.vendor="CIM"; - dvbdemux->dmx.model="sw"; - dvbdemux->dmx.id=budget->demux_id; - dvbdemux->dmx.capabilities=(DMX_TS_FILTERING| - DMX_SECTION_FILTERING| - DMX_MEMORY_BASED_FILTERING); + dvbdemux->dmx.vendor = "CIM"; + dvbdemux->dmx.model = "sw"; + dvbdemux->dmx.id = budget->demux_id; + dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING | + DMX_MEMORY_BASED_FILTERING); dvb_dmx_init(&budget->demux); - dvbfront->id="hw_frontend"; - dvbfront->vendor="VLSI"; - dvbfront->model="DVB Frontend"; - dvbfront->source=DMX_FRONTEND_0; + dvbfront->id = "hw_frontend"; + dvbfront->vendor = "VLSI"; + dvbfront->model = "DVB Frontend"; + dvbfront->source = DMX_FRONTEND_0; - budget->dmxdev.filternum=256; - budget->dmxdev.demux=&dvbdemux->dmx; - budget->dmxdev.capabilities=0; + budget->dmxdev.filternum = 256; + budget->dmxdev.demux = &dvbdemux->dmx; + budget->dmxdev.capabilities = 0; dvb_dmxdev_init(&budget->dmxdev, budget->dvb_adapter); - ret=dvbdemux->dmx.add_frontend(&dvbdemux->dmx, + ret=dvbdemux->dmx.add_frontend (&dvbdemux->dmx, &budget->hw_frontend); - if (ret<0) + if (ret < 0) return ret; - budget->mem_frontend.id="mem_frontend"; - budget->mem_frontend.vendor="memory"; - budget->mem_frontend.model="sw"; - budget->mem_frontend.source=DMX_MEMORY_FE; - ret=dvbdemux->dmx.add_frontend(&dvbdemux->dmx, + budget->mem_frontend.id = "mem_frontend"; + budget->mem_frontend.vendor = "memory"; + budget->mem_frontend.model = "sw"; + budget->mem_frontend.source = DMX_MEMORY_FE; + ret=dvbdemux->dmx.add_frontend (&dvbdemux->dmx, &budget->mem_frontend); if (ret<0) return ret; - ret=dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, + ret=dvbdemux->dmx.connect_frontend (&dvbdemux->dmx, &budget->hw_frontend); - if (ret<0) + if (ret < 0) return ret; - budget->dvb_net.card_num=budget->dvb_adapter->num; + budget->dvb_net.card_num = budget->dvb_adapter->num; dvb_net_init(budget->dvb_adapter, &budget->dvb_net, &dvbdemux->dmx); return 0; } -static void -dvb_unregister(struct budget_s *budget) +static +void budget_unregister(struct budget *budget) { struct dvb_demux *dvbdemux=&budget->demux; DEB_EE(("budget: %p\n",budget)); - if (!budget->registered) - return; - dvb_net_release(&budget->dvb_net); dvbdemux->dmx.close(&dvbdemux->dmx); @@ -370,10 +248,9 @@ dvb_unregister(struct budget_s *budget) dvb_dmxdev_release(&budget->dmxdev); dvb_dmx_release(&budget->demux); - if(budget->card->type == BUDGET_TT) - dvb_remove_frontend_ioctls (budget->dvb_adapter, budget_diseqc_ioctl, NULL); } + static int master_xfer (struct dvb_i2c_bus *i2c, const struct i2c_msg msgs[], int num) { @@ -381,9 +258,11 @@ int master_xfer (struct dvb_i2c_bus *i2c, const struct i2c_msg msgs[], int num) return saa7146_i2c_transfer(dev, msgs, num, 6); } -int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info) + +int ttpci_budget_init (struct budget *budget, + struct saa7146_dev* dev, + struct saa7146_pci_extension_data *info) { - struct budget_s *budget = NULL; struct scatterlist *slist = NULL; int slen = 0; int length = TS_WIDTH*TS_HEIGHT; @@ -394,17 +273,12 @@ int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *i if (bi->type == BUDGET_PATCH && budget_patch <= 0) return -EOPNOTSUPP; - if (!(budget = kmalloc (sizeof (struct budget_s), GFP_KERNEL))) { - printk ("%s: out of memory!\n", __FUNCTION__); - return -ENOMEM; - } - memset(budget, 0, sizeof(struct budget_s)); + memset(budget, 0, sizeof(struct budget)); - DEB_EE(("dev: %p, budget: %p\n",dev,budget)); + DEB_EE(("dev: %p, budget: %p\n", dev, budget)); budget->card = bi; - budget->dev=(struct saa7146_dev *)dev; - (struct budget_s*)dev->ext_priv = budget; + budget->dev = (struct saa7146_dev *) dev; dvb_register_adapter(&budget->dvb_adapter, budget->card->name); @@ -464,17 +338,17 @@ int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *i saa7146_write(dev, MC1, (MASK_13 | MASK_29)); } - budget->i2c_bus = dvb_register_i2c_bus (master_xfer, dev, budget->dvb_adapter, 0); + budget->i2c_bus = dvb_register_i2c_bus (master_xfer, dev, + budget->dvb_adapter, 0); if (!budget->i2c_bus) { dvb_unregister_adapter (budget->dvb_adapter); - kfree(budget); return -ENOMEM; } - + budget->grabbing = vmalloc(length); if (!budget->grabbing) { - printk(KERN_ERR "dvb: vmalloc() failed.\n"); + printk(KERN_ERR "dvb: vmalloc() failed.\n"); ret = -ENOMEM; goto err; } @@ -501,44 +375,52 @@ int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *i tasklet_init (&budget->vpe_tasklet, vpeirq, (unsigned long) budget); saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI); /* frontend power on */ - return 0; + + if (budget_register(budget) == 0) + return 0; err: - if( NULL != budget->grabbing ) { - vfree(budget->grabbing); - } - if( NULL != slist ) { + if (slist) kfree(slist); - } - dvb_unregister_i2c_bus (master_xfer,budget->i2c_bus->adapter, budget->i2c_bus->id); + + if (budget->grabbing) + vfree(budget->grabbing); + + dvb_unregister_i2c_bus (master_xfer,budget->i2c_bus->adapter, + budget->i2c_bus->id); + dvb_unregister_adapter (budget->dvb_adapter); - if( NULL != budget ) { - kfree(budget); - } + return ret; } -int budget_detach (struct saa7146_dev* saa) + +int ttpci_budget_deinit (struct budget *budget) { - struct budget_s *budget = (struct budget_s*)saa->ext_priv; - DEB_EE(("budget: %p\n",budget)); + struct saa7146_dev *dev = budget->dev; + + DEB_EE(("budget: %p\n", budget)); + + budget_unregister (budget); + + dvb_unregister_i2c_bus (master_xfer, budget->i2c_bus->adapter, + budget->i2c_bus->id); - dvb_unregister(budget); - dvb_unregister_i2c_bus (master_xfer,budget->i2c_bus->adapter, budget->i2c_bus->id); dvb_unregister_adapter (budget->dvb_adapter); - saa7146_pgtable_free(saa->pci, &budget->pt); - vfree(budget->grabbing); + tasklet_kill (&budget->vpe_tasklet); + + saa7146_pgtable_free (dev->pci, &budget->pt); + + vfree (budget->grabbing); kfree (budget); - saa->ext_priv = NULL; - return 0; } -void budget_irq(struct saa7146_dev* dev, u32 *isr) +void ttpci_budget_irq10_handler (struct saa7146_dev* dev, u32 *isr) { - struct budget_s *budget = (struct budget_s*)dev->ext_priv; + struct budget *budget = (struct budget*)dev->ext_priv; DEB_EE(("dev: %p, budget: %p\n",dev,budget)); @@ -546,13 +428,14 @@ void budget_irq(struct saa7146_dev* dev, u32 *isr) tasklet_schedule (&budget->vpe_tasklet); } -EXPORT_SYMBOL_GPL(budget_register); -EXPORT_SYMBOL_GPL(budget_irq); -EXPORT_SYMBOL_GPL(budget_attach); -EXPORT_SYMBOL_GPL(budget_detach); + +EXPORT_SYMBOL_GPL(ttpci_budget_init); +EXPORT_SYMBOL_GPL(ttpci_budget_deinit); +EXPORT_SYMBOL_GPL(ttpci_budget_irq10_handler); EXPORT_SYMBOL_GPL(budget_debug); MODULE_PARM(budget_debug,"i"); MODULE_PARM(budget_patch,"i"); MODULE_LICENSE("GPL"); + diff --git a/linux/drivers/media/dvb/ttpci-budget/budget.c b/linux/drivers/media/dvb/ttpci-budget/budget.c index 699dae456..545101f44 100644 --- a/linux/drivers/media/dvb/ttpci-budget/budget.c +++ b/linux/drivers/media/dvb/ttpci-budget/budget.c @@ -34,12 +34,177 @@ #define KBUILD_MODNAME budget #endif + + +static inline void ddelay(int i) +{ + current->state=TASK_INTERRUPTIBLE; + schedule_timeout((HZ*i)/100); +} + + +static +void Set22K (struct budget *budget, int state) +{ + struct saa7146_dev *dev=budget->dev; + DEB_EE(("budget: %p\n",budget)); + saa7146_setgpio(dev, 3, (state ? SAA7146_GPIO_OUTHI : SAA7146_GPIO_OUTLO)); +} + + +/* Diseqc functions only for TT Budget card */ +/* taken from the Skyvision DVB driver by + Ralph Metzler <rjkm@metzlerbros.de> */ + +static +void DiseqcSendBit (struct budget *budget, int data) +{ + struct saa7146_dev *dev=budget->dev; + DEB_EE(("budget: %p\n",budget)); + + saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); + udelay(data ? 500 : 1000); + saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); + udelay(data ? 1000 : 500); +} + + +static +void DiseqcSendByte (struct budget *budget, int data) +{ + int i, par=1, d; + + DEB_EE(("budget: %p\n",budget)); + + for (i=7; i>=0; i--) { + d = (data>>i)&1; + par ^= d; + DiseqcSendBit(budget, d); + } + + DiseqcSendBit(budget, par); +} + + +static +int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, int burst) +{ + struct saa7146_dev *dev=budget->dev; + int i; + + DEB_EE(("budget: %p\n",budget)); + + saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); + mdelay(16); + + for (i=0; i<len; i++) + DiseqcSendByte(budget, msg[i]); + + mdelay(16); + + if (burst!=-1) { + if (burst) + DiseqcSendByte(budget, 0xff); + else { + saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); + udelay(12500); + saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); + } + ddelay(2); + } + + return 0; +} + + +int budget_diseqc_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) +{ + struct budget *budget = fe->before_after_data; + + DEB_EE(("budget: %p\n",budget)); + + switch (cmd) { + case FE_SET_TONE: + switch ((fe_sec_tone_mode_t) arg) { + case SEC_TONE_ON: + Set22K (budget, 1); + break; + case SEC_TONE_OFF: + Set22K (budget, 0); + break; + default: + return -EINVAL; + }; + break; + + case FE_DISEQC_SEND_MASTER_CMD: + { + struct dvb_diseqc_master_cmd *cmd = arg; + + SendDiSEqCMsg (budget, cmd->msg_len, cmd->msg, 0); + break; + } + + case FE_DISEQC_SEND_BURST: + SendDiSEqCMsg (budget, 0, NULL, (int) arg); + break; + + default: + return -EOPNOTSUPP; + }; + + return 0; +} + + +static +int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info) +{ + struct budget *budget; + int err; + + if (!(budget = kmalloc (sizeof(struct budget), GFP_KERNEL))) + return -ENOMEM; + + DEB_EE(("budget: %p\n",budget)); + + if ((err = ttpci_budget_init (budget, dev, info))) { + kfree (budget); + return err; + } + + dvb_add_frontend_ioctls (budget->dvb_adapter, + budget_diseqc_ioctl, NULL, budget); + + dev->ext_priv = budget; + + return 0; +} + + +static +int budget_detach (struct saa7146_dev* dev) +{ + struct budget *budget = (struct budget*) dev->ext_priv; + int err; + + dvb_remove_frontend_ioctls (budget->dvb_adapter, + budget_diseqc_ioctl, NULL); + + err = ttpci_budget_deinit (budget); + + kfree (budget); + + return err; +} + + + static struct saa7146_extension budget_extension; MAKE_BUDGET_INFO(ttbs, "TT-Budget/WinTV-NOVA-S PCI", BUDGET_TT); MAKE_BUDGET_INFO(ttbc, "TT-Budget/WinTV-NOVA-C PCI", BUDGET_TT); MAKE_BUDGET_INFO(ttbt, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT); -MAKE_BUDGET_INFO(ttbci, "TT-Budget/WinTV-NOVA-CI PCI", BUDGET_TT_HW_DISEQC); MAKE_BUDGET_INFO(satel, "SATELCO Multimedia PCI", BUDGET_TT_HW_DISEQC); /* Uncomment for Budget Patch */ /*MAKE_BUDGET_INFO(fs_1_3,"Siemens/Technotrend/Hauppauge PCI rev1.3+Budget_Patch", BUDGET_PATCH);*/ @@ -51,31 +216,13 @@ struct pci_device_id pci_tbl[] = { MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1003), MAKE_EXTENSION_PCI(ttbc, 0x13c2, 0x1004), MAKE_EXTENSION_PCI(ttbt, 0x13c2, 0x1005), - MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c), - MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100f), MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013), { .vendor = 0, } }; -static -int this_budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info) -{ - struct budget_s *budget = NULL; - DEB_EE(("budget: %p\n",budget)); - if( 0 != budget_attach(dev,info)) { - return -1; - } - budget = (struct budget_s*)dev->ext_priv; - - // FIXME: cope with error here! - budget_register(budget); - printk(KERN_INFO "budget: found budget card '%s'.\n",budget->card->name); - - return 0; -} static struct saa7146_extension budget_extension = { @@ -84,12 +231,12 @@ struct saa7146_extension budget_extension = { .ext_vv_data = NULL, .module = THIS_MODULE, - .pci_tbl = &pci_tbl[0], - .attach = this_budget_attach, + .pci_tbl = pci_tbl, + .attach = budget_attach, .detach = budget_detach, .irq_mask = MASK_10, - .irq_func = budget_irq, + .irq_func = ttpci_budget_irq10_handler, }; @@ -113,7 +260,8 @@ void __exit budget_exit(void) module_init(budget_init); module_exit(budget_exit); -MODULE_DESCRIPTION("driver for the SAA7146 based so-called budget PCI DVB cards by " - "Siemens, Technotrend, Hauppauge"); -MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, others"); MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others"); +MODULE_DESCRIPTION("driver for the SAA7146 based so-called " + "budget PCI DVB cards by Siemens, Technotrend, Hauppauge"); + diff --git a/linux/drivers/media/dvb/ttpci-budget/budget.h b/linux/drivers/media/dvb/ttpci-budget/budget.h index 825ed4581..09dbb2735 100644 --- a/linux/drivers/media/dvb/ttpci-budget/budget.h +++ b/linux/drivers/media/dvb/ttpci-budget/budget.h @@ -20,7 +20,7 @@ struct budget_info { }; /* place to store all the necessary device information */ -struct budget_s { +struct budget { /* devices */ struct dvb_device dvb_dev; @@ -51,12 +51,12 @@ struct budget_s { u32 ttbp; int feeding; - int registered; - struct dvb_adapter *dvb_adapter; void *priv; }; + + #define MAKE_BUDGET_INFO(x_var,x_name,x_type) \ static struct budget_info x_var ## _info = { \ .name=x_name, \ @@ -75,10 +75,12 @@ static struct saa7146_pci_extension_data x_var = { \ #define BUDGET_KNC1 2 #define BUDGET_PATCH 3 -int budget_probe(struct saa7146_dev *, unsigned int subvendor, unsigned int subdevice); -void budget_irq(struct saa7146_dev *, u32 *isr); -int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info); -int budget_detach (struct saa7146_dev *); -int budget_register(struct budget_s *budget); + +extern int ttpci_budget_init (struct budget *budget, + struct saa7146_dev* dev, + struct saa7146_pci_extension_data *info); +extern int ttpci_budget_deinit (struct budget *budget); +extern void ttpci_budget_irq10_handler (struct saa7146_dev* dev, u32 *isr); #endif + |