diff options
| author | Andrew de Quincy <devnull@localhost> | 2004-04-05 12:17:33 +0000 |
|---|---|---|
| committer | Andrew de Quincy <devnull@localhost> | 2004-04-05 12:17:33 +0000 |
| commit | 65a6213f98192e62d653b6035502414c63053613 (patch) | |
| tree | 226d419d5868894c3eefab1528bdaa8ba5cde5c4 /linux/drivers/media/dvb/ttpci | |
| parent | 752cadb89bc935db0ec866d49cae06d79fc54487 (diff) | |
| download | mediapointer-dvb-s2-65a6213f98192e62d653b6035502414c63053613.tar.gz mediapointer-dvb-s2-65a6213f98192e62d653b6035502414c63053613.tar.bz2 | |
First commmit for budget-ci CI interface code
Diffstat (limited to 'linux/drivers/media/dvb/ttpci')
| -rw-r--r-- | linux/drivers/media/dvb/ttpci/budget-ci.c | 382 | ||||
| -rw-r--r-- | linux/drivers/media/dvb/ttpci/budget-core.c | 229 | ||||
| -rw-r--r-- | linux/drivers/media/dvb/ttpci/budget.h | 3 |
3 files changed, 389 insertions, 225 deletions
diff --git a/linux/drivers/media/dvb/ttpci/budget-ci.c b/linux/drivers/media/dvb/ttpci/budget-ci.c index db16c44e1..955ae3ffb 100644 --- a/linux/drivers/media/dvb/ttpci/budget-ci.c +++ b/linux/drivers/media/dvb/ttpci/budget-ci.c @@ -1,30 +1,30 @@ /* - * budget-ci.c: driver for the SAA7146 based Budget DVB cards + * budget-ci.c: driver for the SAA7146 based Budget DVB cards * - * Compiled from various sources by Michael Hunold <michael@mihu.de> + * Compiled from various sources by Michael Hunold <michael@mihu.de> * * msp430 IR support contributed by Jack Thomasson <jkt@Helius.COM> * partially based on the Siemens DVB driver by Ralph+Marcus Metzler * * CI interface support (c) 2004 Andrew de Quincey <adq_dvb@lidskialf.net> - * + * * 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 + * 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/ */ @@ -39,81 +39,96 @@ #include <linux/spinlock.h> #include "dvb_functions.h" +#include "dvb_ca_en50221.h" #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) #include "input_fake.h" #endif -#define DEBIADDR_IR 0x1234 -#define DEBIADDR_CICONTROL 0x0000 -#define DEBIADDR_CIVERSION 0x4000 -#define DEBIADDR_CIIRQCONTROL 0x4000 +#define DEBIADDR_IR 0x1234 +#define DEBIADDR_CICONTROL 0x0000 +#define DEBIADDR_CIVERSION 0x4000 +#define DEBIADDR_IO 0x1000 +#define DEBIADDR_ATTR 0x3000 + +#define CICONTROL_RESET 0x01 +#define CICONTROL_ENABLETS 0x02 +#define CICONTROL_CAMDETECT 0x08 +#define DEBICICTL 0x00420000 +#define DEBICICAM 0x02420000 +#define SLOTSTATUS_NONE 1 +#define SLOTSTATUS_PRESENT 2 +#define SLOTSTATUS_RESET 4 +#define SLOTSTATUS_READY 8 +#define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY) struct budget_ci { struct budget budget; struct input_dev input_dev; struct tasklet_struct msp430_irq_tasklet; - spinlock_t debilock; - int ci_present; + struct tasklet_struct ciintf_irq_tasklet; + spinlock_t debilock; + int slot_status; + struct dvb_ca_en50221 ca; char ir_dev_name[50]; }; static u32 budget_debiread (struct budget_ci* budget_ci, u32 config, int addr, int count) { struct saa7146_dev *saa = budget_ci->budget.dev; - u32 result = 0; - + u32 result = 0; + if (count > 4 || count <= 0) return 0; - spin_lock(&budget_ci->debilock); - + spin_lock(&budget_ci->debilock); + if (saa7146_wait_for_debi_done(saa) < 0) { - spin_unlock(&budget_ci->debilock); + spin_unlock(&budget_ci->debilock); return 0; } - + saa7146_write (saa, DEBI_COMMAND, (count << 17) | 0x10000 | (addr & 0xffff)); saa7146_write(saa, DEBI_CONFIG, config); - saa7146_write(saa, DEBI_PAGE, 0); + saa7146_write(saa, DEBI_PAGE, 0); saa7146_write(saa, MC2, (2 << 16) | 2); - + saa7146_wait_for_debi_done(saa); result = saa7146_read(saa, 0x88); result &= (0xffffffffUL >> ((4 - count) * 8)); - spin_unlock(&budget_ci->debilock); + spin_unlock(&budget_ci->debilock); return result; } static u8 budget_debiwrite (struct budget_ci* budget_ci, u32 config, int addr, int count, u32 value) { struct saa7146_dev *saa = budget_ci->budget.dev; - + if (count > 4 || count <= 0) return 0; - spin_lock(&budget_ci->debilock); - + spin_lock(&budget_ci->debilock); + if (saa7146_wait_for_debi_done(saa) < 0) { - spin_unlock(&budget_ci->debilock); + spin_unlock(&budget_ci->debilock); return 0; } saa7146_write (saa, DEBI_COMMAND, (count << 17) | 0x00000 | (addr & 0xffff)); saa7146_write(saa, DEBI_CONFIG, config); - saa7146_write(saa, DEBI_PAGE, 0); + saa7146_write(saa, DEBI_PAGE, 0); saa7146_write(saa, DEBI_AD, value); saa7146_write(saa, MC2, (2 << 16) | 2); - + saa7146_wait_for_debi_done(saa); - - spin_unlock(&budget_ci->debilock); + + spin_unlock(&budget_ci->debilock); return 0; } @@ -123,52 +138,52 @@ static u8 budget_debiwrite (struct budget_ci* budget_ci, u32 config, int addr, i 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] = { +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, KEY_RED, - KEY_POWER, /* RADIO on Hauppauge */ + KEY_POWER, /* RADIO on Hauppauge */ KEY_MUTE, 0, - KEY_A, /* TV on Hauppauge */ + 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 */ + KEY_OPTION, /* RESERVED on Hauppauge */ KEY_BREAK, /* 0x2X */ KEY_CHANNELUP, KEY_CHANNELDOWN, - KEY_PREVIOUS, /* Prev. Ch on Zenith, SOURCE on Hauppauge */ + KEY_PREVIOUS, /* Prev. Ch on Zenith, SOURCE on Hauppauge */ 0, KEY_RESTART, KEY_OK, - KEY_CYCLEWINDOWS, /* MINIMIZE on Hauppauge */ + KEY_CYCLEWINDOWS, /* MINIMIZE on Hauppauge */ 0, - KEY_ENTER, /* VCR mode on Zenith */ + KEY_ENTER, /* VCR mode on Zenith */ KEY_PAUSE, 0, KEY_RIGHT, KEY_LEFT, 0, - KEY_MENU, /* FULL SCREEN on Hauppauge */ + KEY_MENU, /* FULL SCREEN on Hauppauge */ 0, /* 0x3X */ KEY_SLOW, - KEY_PREVIOUS, /* VCR mode on Zenith */ + KEY_PREVIOUS, /* VCR mode on Zenith */ KEY_REWIND, 0, KEY_FASTFORWARD, KEY_PLAY, KEY_STOP, KEY_RECORD, - KEY_TUNER, /* TV/VCR on Zenith */ + KEY_TUNER, /* TV/VCR on Zenith */ 0, KEY_C, 0, KEY_EXIT, KEY_POWER2, - KEY_TUNER, /* VCR mode on Zenith */ + KEY_TUNER, /* VCR mode on Zenith */ 0, }; @@ -185,7 +200,7 @@ static void msp430_ir_debounce (unsigned long data) 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 */ + input_event(dev, EV_KEY, key_map[dev->repeat_key], 2); /* REPEAT */ } @@ -197,22 +212,22 @@ static void msp430_ir_interrupt (unsigned long data) unsigned int code = budget_debiread(budget_ci, DEBINOSWAP, DEBIADDR_IR, 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); + 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", + printk ("DVB (%s): no key for %02x!\n", __FUNCTION__, code); - return; - } + return; + } /* initialize debounce and repeat */ dev->repeat_key = code; @@ -221,7 +236,7 @@ static void msp430_ir_interrupt (unsigned long data) /* 350 milliseconds */ dev->timer.expires = jiffies + HZ * 350 / 1000; /* MAKE */ - input_event(dev, EV_KEY, key_map[code], !0); + input_event(dev, EV_KEY, key_map[code], !0); add_timer(&dev->timer); } } @@ -249,7 +264,7 @@ static int msp430_ir_init (struct budget_ci *budget_ci) saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_06); - saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI); + saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI); return 0; } @@ -269,73 +284,215 @@ static void msp430_ir_deinit (struct budget_ci *budget_ci) input_unregister_device(dev); } +static int ciintf_read_attribute_mem(struct dvb_ca_en50221* ca, int slot, int address) { + struct budget_ci* budget_ci = (struct budget_ci*) ca->data; + + if (slot != 0) return -EINVAL; + + return budget_debiread(budget_ci, DEBICICAM, DEBIADDR_ATTR | (address & 0xfff), 1); +} + +static int ciintf_write_attribute_mem(struct dvb_ca_en50221* ca, int slot, int address, u8 value) { + struct budget_ci* budget_ci = (struct budget_ci*) ca->data; + + if (slot != 0) return -EINVAL; + + return budget_debiwrite(budget_ci, DEBICICAM, DEBIADDR_ATTR | (address & 0xfff), 1, value); +} + +static int ciintf_read_cam_control(struct dvb_ca_en50221* ca, int slot, u8 address) { + struct budget_ci* budget_ci = (struct budget_ci*) ca->data; + + if (slot != 0) return -EINVAL; + + return budget_debiread(budget_ci, DEBICICAM, DEBIADDR_IO | (address & 3), 1); +} + +static int ciintf_write_cam_control(struct dvb_ca_en50221* ca, int slot, u8 address, u8 value) { + struct budget_ci* budget_ci = (struct budget_ci*) ca->data; + + if (slot != 0) return -EINVAL; + + return budget_debiwrite(budget_ci, DEBICICAM, DEBIADDR_IO | (address & 3), 1, value); +} + +static int ciintf_slot_reset(struct dvb_ca_en50221* ca, int slot) { + struct budget_ci* budget_ci = (struct budget_ci*) ca->data; + struct saa7146_dev *saa = budget_ci->budget.dev; + + if (slot != 0) return -EINVAL; + + // trigger on RISING edge during reset so we know when READY is re-asserted + saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI); + budget_ci->slot_status = SLOTSTATUS_RESET; + budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, 0); + dvb_delay(1); + budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, CICONTROL_RESET); + + return 0; +} + +static int ciintf_slot_shutdown(struct dvb_ca_en50221* ca, int slot) { + if (slot != 0) return -EINVAL; + + // no implementation necessary + return 0; +} + +static int ciintf_slot_ts_enable(struct dvb_ca_en50221* ca, int slot) { + struct budget_ci* budget_ci = (struct budget_ci*) ca->data; + int tmp; + + if (slot != 0) return -EINVAL; + + tmp = budget_debiread(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1); + budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, tmp | CICONTROL_ENABLETS); + return 0; +} + + +static void ciintf_interrupt (unsigned long data) +{ + struct budget_ci *budget_ci = (struct budget_ci*) data; + struct saa7146_dev *saa = budget_ci->budget.dev; + unsigned int flags; + + // ensure we don't get spurious IRQs during initialisation + if (!budget_ci->budget.ci_present) return; + + flags = budget_debiread(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1); + + // always set the GPIO mode back to "normal", in case the card is + // yanked at an inopportune moment + saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO); + + if (flags & CICONTROL_CAMDETECT) { + + if (budget_ci->slot_status & SLOTSTATUS_NONE) { + // CAM insertion IRQ + budget_ci->slot_status = SLOTSTATUS_PRESENT; + dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, DVB_CA_EN50221_CAMCHANGE_INSERTED); + + } else if (budget_ci->slot_status & SLOTSTATUS_RESET) { + // CAM ready (reset completed) + budget_ci->slot_status = SLOTSTATUS_READY; + dvb_ca_en50221_camready_irq(&budget_ci->ca, 0); + + } else if (budget_ci->slot_status & SLOTSTATUS_READY) { + // FR/DA IRQ + dvb_ca_en50221_frda_irq(&budget_ci->ca, 0); + } + } else { + if (budget_ci->slot_status & SLOTSTATUS_OCCUPIED) { + budget_ci->slot_status = SLOTSTATUS_NONE; + dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, DVB_CA_EN50221_CAMCHANGE_REMOVED); + } + } +} + static int ciintf_init(struct budget_ci* budget_ci) { struct saa7146_dev *saa = budget_ci->budget.dev; + int flags; + int result; + + memset(&budget_ci->ca, 0, sizeof(struct dvb_ca_en50221)); + + // enable DEBI pins + saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800); + + // test if it is there + if ((budget_debiread(budget_ci, DEBICICTL, DEBIADDR_CIVERSION, 1) & 0xa0) != 0xa0) { + result = -ENODEV; + goto error; + } - // enable DEBI pins - saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800); - - // test if it is there - if ((budget_debiread(budget_ci, DEBICICTL, DEBIADDR_CIVERSION, 1) & 0xa0) != 0xa0) { - saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16)); - return -ENODEV; + // determine whether a CAM is present or not + flags = budget_debiread(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1); + budget_ci->slot_status = SLOTSTATUS_NONE; + if (flags & CICONTROL_CAMDETECT) budget_ci->slot_status = SLOTSTATUS_PRESENT; + + + // register CI interface + budget_ci->ca.read_attribute_mem = ciintf_read_attribute_mem; + budget_ci->ca.write_attribute_mem = ciintf_write_attribute_mem; + budget_ci->ca.read_cam_control = ciintf_read_cam_control; + budget_ci->ca.write_cam_control = ciintf_write_cam_control; + budget_ci->ca.slot_reset = ciintf_slot_reset; + budget_ci->ca.slot_shutdown = ciintf_slot_shutdown; + budget_ci->ca.slot_ts_enable = ciintf_slot_ts_enable; + budget_ci->ca.data = budget_ci; + if ((result = dvb_ca_en50221_init(budget_ci->budget.dvb_adapter, + &budget_ci->ca, + DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE | + DVB_CA_EN50221_FLAG_IRQ_FR | + DVB_CA_EN50221_FLAG_IRQ_DA, + 1)) != 0) { + printk("budget_ci: CI interface detected, but initialisation failed.\n"); + goto error; } - // reset CI interface - budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, 0); - dvb_delay(1); - budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, 1); + // Setup CI slot IRQ + tasklet_init (&budget_ci->ciintf_irq_tasklet, ciintf_interrupt, (unsigned long) budget_ci); + saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO); + saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_03); + budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, CICONTROL_RESET); - // clear any CI interrupt status - budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CIIRQCONTROL, 1, 0xC0); + // success! + printk("budget_ci: CI interface initialised\n"); + budget_ci->budget.ci_present = 1; - // FIXME: register CI slot + // route TS data out to CI interface + saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI); - // Setup CI slot IRQ - saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO); - saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_03); - budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, 0xc1); + // forge a fake CI IRQ so the CAM state is setup correctly + flags = DVB_CA_EN50221_CAMCHANGE_REMOVED; + if (budget_ci->slot_status != SLOTSTATUS_NONE) flags = DVB_CA_EN50221_CAMCHANGE_INSERTED; + dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, flags); - // FIXME: route TS data out to CI interface -// saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI); + return 0; - // success! - printk("budget_ci: CI interface detected\n"); - budget_ci->ci_present = 1; - return 0; +error: + saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16)); + return result; } -static void ciintf_deinit(struct budget_ci* budget_ci) +static void ciintf_deinit(struct budget_ci* budget_ci) { struct saa7146_dev *saa = budget_ci->budget.dev; - // disable CI interrupts - budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, 0x1); - saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_03); + // disable CI interrupts + saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_03); saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT); + tasklet_kill(&budget_ci->ciintf_irq_tasklet); + budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, 0); + dvb_delay(1); + budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, CICONTROL_RESET); - // FIXME: disable TS data stream to CI interface - saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT); + // disable TS data stream to CI interface + saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT); - // disable DEBI pins again - saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16)); + // release the CA device + dvb_ca_en50221_release(&budget_ci->ca); + + // disable DEBI pins + saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16)); } static void budget_ci_irq (struct saa7146_dev *dev, u32 *isr) { - struct budget_ci *budget_ci = (struct budget_ci*) dev->ext_priv; + struct budget_ci *budget_ci = (struct budget_ci*) dev->ext_priv; - DEB_EE(("dev: %p, budget_ci: %p\n", dev, budget_ci)); + 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_06) + tasklet_schedule (&budget_ci->msp430_irq_tasklet); - if (*isr & MASK_10) + if (*isr & MASK_10) ttpci_budget_irq10_handler (dev, isr); - if (*isr & MASK_03) - printk("CI IRQ!!\n"); + if ((*isr & MASK_03) && (budget_ci->budget.ci_present)) + tasklet_schedule (&budget_ci->ciintf_irq_tasklet); } @@ -351,8 +508,8 @@ static int budget_ci_attach (struct saa7146_dev* dev, DEB_EE(("budget_ci: %p\n", budget_ci)); - spin_lock_init(&budget_ci->debilock); - budget_ci->ci_present = 0; + spin_lock_init(&budget_ci->debilock); + budget_ci->budget.ci_present = 0; if ((err = ttpci_budget_init (&budget_ci->budget, dev, info))) { kfree (budget_ci); @@ -365,8 +522,9 @@ static int budget_ci_attach (struct saa7146_dev* dev, (unsigned long) budget_ci); msp430_ir_init (budget_ci); - - ciintf_init(budget_ci); + + // UNCOMMENT TO TEST CI INTERFACE +// ciintf_init(budget_ci); return 0; } @@ -377,7 +535,9 @@ static int budget_ci_detach (struct saa7146_dev* dev) { struct budget_ci *budget_ci = (struct budget_ci*) dev->ext_priv; struct saa7146_dev *saa = budget_ci->budget.dev; - int err; + int err; + + if (budget_ci->budget.ci_present) ciintf_deinit(budget_ci); err = ttpci_budget_deinit (&budget_ci->budget); @@ -385,11 +545,9 @@ static int budget_ci_detach (struct saa7146_dev* dev) msp430_ir_deinit (budget_ci); - if (budget_ci->ci_present) ciintf_deinit(budget_ci); + // disable frontend and CI interface + saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT); - // disable frontend and CI interface - saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT); - kfree (budget_ci); return err; @@ -397,17 +555,17 @@ static int budget_ci_detach (struct saa7146_dev* dev) -static struct saa7146_extension budget_extension; +static struct saa7146_extension budget_extension; MAKE_BUDGET_INFO(ttbci, "TT-Budget/WinTV-NOVA-CI PCI", BUDGET_TT_HW_DISEQC); -MAKE_BUDGET_INFO(ttbt2, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT); +MAKE_BUDGET_INFO(ttbt2, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT); static struct pci_device_id pci_tbl[] = { MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c), MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100f), - MAKE_EXTENSION_PCI(ttbt2, 0x13c2, 0x1011), + MAKE_EXTENSION_PCI(ttbt2, 0x13c2, 0x1011), { - .vendor = 0, + .vendor = 0, } }; @@ -415,7 +573,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl); static struct saa7146_extension budget_extension = { .name = "budget_ci dvb\0", - .flags = 0, + .flags = 0, .module = THIS_MODULE, .pci_tbl = &pci_tbl[0], @@ -424,10 +582,10 @@ static struct saa7146_extension budget_extension = { .irq_mask = MASK_03 | MASK_06 | MASK_10, .irq_func = budget_ci_irq, -}; +}; -static int __init budget_ci_init(void) +static int __init budget_ci_init(void) { return saa7146_register_extension(&budget_extension); } @@ -436,7 +594,7 @@ static int __init budget_ci_init(void) static void __exit budget_ci_exit(void) { DEB_EE((".\n")); - saa7146_unregister_extension(&budget_extension); + saa7146_unregister_extension(&budget_extension); } module_init(budget_ci_init); diff --git a/linux/drivers/media/dvb/ttpci/budget-core.c b/linux/drivers/media/dvb/ttpci/budget-core.c index 302a3495c..2b626a4f4 100644 --- a/linux/drivers/media/dvb/ttpci/budget-core.c +++ b/linux/drivers/media/dvb/ttpci/budget-core.c @@ -6,12 +6,12 @@ * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de> * * Copyright (C) 1999-2002 Ralph Metzler - * & Marcus Metzler for convergence integrated media GmbH - * + * & Marcus Metzler for convergence integrated media GmbH + * * 26feb2004 Support for FS Activy Card (Grundig tuner) by - * Michael Dreher <michael@5dot1.de>, - * Oliver Endriss <o.endriss@gmx.de>, - * Andreas 'randy' Weinberger + * Michael Dreher <michael@5dot1.de>, + * Oliver Endriss <o.endriss@gmx.de>, + * Andreas 'randy' Weinberger * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -21,7 +21,7 @@ * * 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 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * @@ -47,33 +47,33 @@ static int stop_ts_capture(struct budget *budget) { DEB_EE(("budget: %p\n",budget)); - if (--budget->feeding) - return budget->feeding; + if (--budget->feeding) + return budget->feeding; - saa7146_write(budget->dev, MC1, MASK_20); // DMA3 off + saa7146_write(budget->dev, MC1, MASK_20); // DMA3 off IER_DISABLE(budget->dev, MASK_10); - return 0; + return 0; } static int start_ts_capture (struct budget *budget) { - struct saa7146_dev *dev=budget->dev; + struct saa7146_dev *dev=budget->dev; DEB_EE(("budget: %p\n",budget)); - if (budget->feeding) - return ++budget->feeding; + if (budget->feeding) + return ++budget->feeding; - saa7146_write(dev, MC1, MASK_20); // DMA3 off + saa7146_write(dev, MC1, MASK_20); // DMA3 off - memset(budget->grabbing, 0x00, TS_HEIGHT*TS_WIDTH); + memset(budget->grabbing, 0x00, TS_HEIGHT*TS_WIDTH); - saa7146_write(dev, PCI_BT_V1, 0x001c0000 | - (saa7146_read(dev, PCI_BT_V1) & ~0x001f0000)); + saa7146_write(dev, PCI_BT_V1, 0x001c0000 | + (saa7146_read(dev, PCI_BT_V1) & ~0x001f0000)); - budget->tsf=0xff; - budget->ttbp=0; + budget->tsf=0xff; + budget->ttbp=0; /* * Signal path on the Activy: @@ -82,71 +82,77 @@ static int start_ts_capture (struct budget *budget) * * Since the tuner feeds 204 bytes packets into the SAA7146, * DMA3 is configured to strip the trailing 16 FEC bytes: - * Pitch: 188, NumBytes3: 188, NumLines3: 1024 + * Pitch: 188, NumBytes3: 188, NumLines3: 1024 */ - if (budget->card->type == BUDGET_FS_ACTIVY) { - saa7146_write(dev, DD1_INIT, 0x04000000); - saa7146_write(dev, MC2, (MASK_09 | MASK_25)); - saa7146_write(dev, BRS_CTRL, 0x00000000); - } else { - saa7146_write(dev, DD1_INIT, 0x02000600); - saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26)); - saa7146_write(dev, BRS_CTRL, 0x60000000); - } - - saa7146_write(dev, MC2, (MASK_08 | MASK_24)); - mdelay(10); - - saa7146_write(dev, BASE_ODD3, 0); - saa7146_write(dev, BASE_EVEN3, 0); - saa7146_write(dev, PROT_ADDR3, TS_WIDTH*TS_HEIGHT); - saa7146_write(dev, BASE_PAGE3, budget->pt.dma |ME1|0x90); - - if (budget->card->type == BUDGET_FS_ACTIVY) { - saa7146_write(dev, PITCH3, TS_WIDTH/2); - saa7146_write(dev, NUM_LINE_BYTE3, ((TS_HEIGHT*2)<<16)|(TS_WIDTH/2)); - } else { - saa7146_write(dev, PITCH3, TS_WIDTH); - saa7146_write(dev, NUM_LINE_BYTE3, (TS_HEIGHT<<16)|TS_WIDTH); - } - - saa7146_write(dev, MC2, (MASK_04 | MASK_20)); - saa7146_write(dev, MC1, (MASK_04 | MASK_20)); // DMA3 on + if (budget->card->type == BUDGET_FS_ACTIVY) { + saa7146_write(dev, DD1_INIT, 0x04000000); + saa7146_write(dev, MC2, (MASK_09 | MASK_25)); + saa7146_write(dev, BRS_CTRL, 0x00000000); + } else { + if (!budget->ci_present) { + saa7146_write(dev, DD1_INIT, 0x02000600); + saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26)); + saa7146_write(dev, BRS_CTRL, 0x60000000); + } else { + saa7146_write(dev, DD1_INIT, 0x06000200); + saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26)); + saa7146_write(dev, BRS_CTRL, 0x00000000); + } + } + + saa7146_write(dev, MC2, (MASK_08 | MASK_24)); + mdelay(10); + + saa7146_write(dev, BASE_ODD3, 0); + saa7146_write(dev, BASE_EVEN3, 0); + saa7146_write(dev, PROT_ADDR3, TS_WIDTH*TS_HEIGHT); + saa7146_write(dev, BASE_PAGE3, budget->pt.dma |ME1|0x90); + + if (budget->card->type == BUDGET_FS_ACTIVY) { + saa7146_write(dev, PITCH3, TS_WIDTH/2); + saa7146_write(dev, NUM_LINE_BYTE3, ((TS_HEIGHT*2)<<16)|(TS_WIDTH/2)); + } else { + saa7146_write(dev, PITCH3, TS_WIDTH); + saa7146_write(dev, NUM_LINE_BYTE3, (TS_HEIGHT<<16)|TS_WIDTH); + } + + saa7146_write(dev, MC2, (MASK_04 | MASK_20)); + saa7146_write(dev, MC1, (MASK_04 | MASK_20)); // DMA3 on IER_ENABLE(budget->dev, MASK_10); // VPE - return ++budget->feeding; + return ++budget->feeding; } static void vpeirq (unsigned long data) { - struct budget *budget = (struct budget*) data; - u8 *mem = (u8 *)(budget->grabbing); - u32 olddma = budget->ttbp; - u32 newdma = saa7146_read(budget->dev, PCI_VDP3); + struct budget *budget = (struct budget*) data; + u8 *mem = (u8 *)(budget->grabbing); + u32 olddma = budget->ttbp; + u32 newdma = saa7146_read(budget->dev, PCI_VDP3); - /* nearest lower position divisible by 188 */ - newdma -= newdma % 188; + /* nearest lower position divisible by 188 */ + newdma -= newdma % 188; - if (newdma >= TS_BUFLEN) - return; + if (newdma >= TS_BUFLEN) + return; budget->ttbp = newdma; if(budget->feeding == 0 || newdma == olddma) return; - if (newdma > olddma) { /* no wraparound, dump olddma..newdma */ - dvb_dmx_swfilter_packets(&budget->demux, - mem+olddma, (newdma-olddma) / 188); - } else { /* wraparound, dump olddma..buflen and 0..newdma */ - dvb_dmx_swfilter_packets(&budget->demux, - mem+olddma, (TS_BUFLEN-olddma) / 188); - dvb_dmx_swfilter_packets(&budget->demux, - mem, newdma / 188); - } + if (newdma > olddma) { /* no wraparound, dump olddma..newdma */ + dvb_dmx_swfilter_packets(&budget->demux, + mem+olddma, (newdma-olddma) / 188); + } else { /* wraparound, dump olddma..buflen and 0..newdma */ + dvb_dmx_swfilter_packets(&budget->demux, + mem+olddma, (TS_BUFLEN-olddma) / 188); + dvb_dmx_swfilter_packets(&budget->demux, + mem, newdma / 188); + } } @@ -156,21 +162,21 @@ static void vpeirq (unsigned long data) static int budget_start_feed(struct dvb_demux_feed *feed) { - struct dvb_demux *demux = feed->demux; - struct budget *budget = (struct budget*) demux->priv; + struct dvb_demux *demux = feed->demux; + struct budget *budget = (struct budget*) demux->priv; DEB_EE(("budget: %p\n",budget)); - if (!demux->dmx.frontend) - return -EINVAL; + if (!demux->dmx.frontend) + return -EINVAL; return start_ts_capture (budget); } static int budget_stop_feed(struct dvb_demux_feed *feed) { - struct dvb_demux *demux = feed->demux; - struct budget *budget = (struct budget *) demux->priv; + struct dvb_demux *demux = feed->demux; + struct budget *budget = (struct budget *) demux->priv; DEB_EE(("budget: %p\n",budget)); @@ -180,49 +186,49 @@ static int budget_stop_feed(struct dvb_demux_feed *feed) static int budget_register(struct budget *budget) { - struct dvb_demux *dvbdemux = &budget->demux; - int ret; + struct dvb_demux *dvbdemux = &budget->demux; + int ret; DEB_EE(("budget: %p\n",budget)); - dvbdemux->priv = (void *) budget; + 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->feednum = 256; + dvbdemux->start_feed = budget_start_feed; + dvbdemux->stop_feed = budget_stop_feed; + dvbdemux->write_to_decoder = NULL; - dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING | - DMX_MEMORY_BASED_FILTERING); + dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING | + DMX_MEMORY_BASED_FILTERING); - dvb_dmx_init(&budget->demux); + dvb_dmx_init(&budget->demux); - 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); + dvb_dmxdev_init(&budget->dmxdev, budget->dvb_adapter); - budget->hw_frontend.source = DMX_FRONTEND_0; + budget->hw_frontend.source = DMX_FRONTEND_0; - ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &budget->hw_frontend); + ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &budget->hw_frontend); if (ret < 0) - return ret; - - 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, - &budget->hw_frontend); - if (ret < 0) - return ret; - - dvb_net_init(budget->dvb_adapter, &budget->dvb_net, &dvbdemux->dmx); + return ret; + + 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, + &budget->hw_frontend); + if (ret < 0) + return ret; + + dvb_net_init(budget->dvb_adapter, &budget->dvb_net, &dvbdemux->dmx); return 0; } @@ -230,18 +236,18 @@ static int budget_register(struct budget *budget) static void budget_unregister(struct budget *budget) { - struct dvb_demux *dvbdemux=&budget->demux; + struct dvb_demux *dvbdemux=&budget->demux; DEB_EE(("budget: %p\n",budget)); dvb_net_release(&budget->dvb_net); dvbdemux->dmx.close(&dvbdemux->dmx); - dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &budget->hw_frontend); - dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &budget->mem_frontend); + dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &budget->hw_frontend); + dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &budget->mem_frontend); - dvb_dmxdev_release(&budget->dmxdev); - dvb_dmx_release(&budget->demux); + dvb_dmxdev_release(&budget->dmxdev); + dvb_dmx_release(&budget->demux); } @@ -270,12 +276,12 @@ int ttpci_budget_init (struct budget *budget, dvb_register_adapter(&budget->dvb_adapter, budget->card->name, THIS_MODULE); /* set dd1 stream a & b */ - saa7146_write(dev, DD1_STREAM_B, 0x00000000); + saa7146_write(dev, DD1_STREAM_B, 0x00000000); saa7146_write(dev, DD1_INIT, 0x02000000); saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26)); /* the Siemens DVB needs this if you want to have the i2c chips - get recognized before the main driver is loaded */ + get recognized before the main driver is loaded */ if (bi->type != BUDGET_FS_ACTIVY) saa7146_write(dev, GPIO_CTRL, 0x500000); /* GPIO 3 = 1 */ @@ -298,7 +304,7 @@ int ttpci_budget_init (struct budget *budget, saa7146_write(dev, PCI_BT_V1, 0x001c0000); /* upload all */ - saa7146_write(dev, GPIO_CTRL, 0x000000); + saa7146_write(dev, GPIO_CTRL, 0x000000); tasklet_init (&budget->vpe_tasklet, vpeirq, (unsigned long) budget); @@ -308,7 +314,7 @@ int ttpci_budget_init (struct budget *budget, else saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI); - if (budget_register(budget) == 0) { + if (budget_register(budget) == 0) { return 0; } err: @@ -365,4 +371,3 @@ EXPORT_SYMBOL_GPL(budget_debug); MODULE_PARM(budget_debug,"i"); MODULE_LICENSE("GPL"); - diff --git a/linux/drivers/media/dvb/ttpci/budget.h b/linux/drivers/media/dvb/ttpci/budget.h index 3c730423d..b0d315a0f 100644 --- a/linux/drivers/media/dvb/ttpci/budget.h +++ b/linux/drivers/media/dvb/ttpci/budget.h @@ -45,6 +45,8 @@ struct budget { int fe_synced; struct semaphore pid_mutex; + + int ci_present; u8 tsf; u32 ttbp; @@ -75,7 +77,6 @@ static struct saa7146_pci_extension_data x_var = { \ #define BUDGET_PATCH 3 #define BUDGET_FS_ACTIVY 4 - extern int ttpci_budget_init (struct budget *budget, struct saa7146_dev* dev, struct saa7146_pci_extension_data *info); |
