diff options
author | Andrew de Quincy <devnull@localhost> | 2004-03-11 18:40:44 +0000 |
---|---|---|
committer | Andrew de Quincy <devnull@localhost> | 2004-03-11 18:40:44 +0000 |
commit | 4881f248a09885725d1ad51ec35339ff4db2d81c (patch) | |
tree | f28e1ee6e7e472092c1a2a5e9ea55825c61f7c04 /linux/drivers/media/dvb/ttpci | |
parent | 455c6bb685dcf96d46dc80361513fc6476d541e7 (diff) | |
download | mediapointer-dvb-s2-4881f248a09885725d1ad51ec35339ff4db2d81c.tar.gz mediapointer-dvb-s2-4881f248a09885725d1ad51ec35339ff4db2d81c.tar.bz2 |
Checked in experimental frontend patch
Also some minimal budget-ci CI support implemented (just detection+IRQs)
Diffstat (limited to 'linux/drivers/media/dvb/ttpci')
-rw-r--r-- | linux/drivers/media/dvb/ttpci/budget-ci.c | 136 |
1 files changed, 122 insertions, 14 deletions
diff --git a/linux/drivers/media/dvb/ttpci/budget-ci.c b/linux/drivers/media/dvb/ttpci/budget-ci.c index 601109de8..21162885b 100644 --- a/linux/drivers/media/dvb/ttpci/budget-ci.c +++ b/linux/drivers/media/dvb/ttpci/budget-ci.c @@ -6,6 +6,8 @@ * 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 @@ -34,44 +36,86 @@ #include <linux/slab.h> #include <linux/interrupt.h> #include <linux/input.h> +#include <linux/spinlock.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 + struct budget_ci { struct budget budget; struct input_dev input_dev; struct tasklet_struct msp430_irq_tasklet; + spinlock_t debilock; + int ci_present; char ir_dev_name[50]; }; -static u32 budget_debiread4 (struct saa7146_dev *saa, u32 config, int addr, int count) +static u32 budget_debiread (struct budget_ci* budget_ci, u32 config, int addr, int count) { - u32 result = 0; - + struct saa7146_dev *saa = budget_ci->budget.dev; + u32 result = 0; + if (count > 4 || count <= 0) return 0; - if (saa7146_wait_for_debi_done(saa) < 0) + spin_lock(budget_ci->debilock); + + if (saa7146_wait_for_debi_done(saa) < 0) { + 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, MC2, (2 << 16) | 2); - + saa7146_wait_for_debi_done(saa); - result = saa7146_read(saa, DEBI_AD); + result = saa7146_read(saa, 0x88); result &= (0xffffffffUL >> ((4 - count) * 8)); + 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); + + if (saa7146_wait_for_debi_done(saa) < 0) { + 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_AD, value); + saa7146_write(saa, MC2, (2 << 16) | 2); + + saa7146_wait_for_debi_done(saa); + + spin_unlock(&budget_ci->debilock); + return 0; +} + + /* from reading the following remotes: Zenith Universal 7 / TV Mode 807 / VCR Mode 837 Hauppauge (from NOVA-CI-s box product) @@ -147,9 +191,8 @@ static void msp430_ir_debounce (unsigned long data) 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 = budget_debiread4(saa, DEBINOSWAP, 0x1234, 2) >> 8; + unsigned int code = budget_debiread(budget_ci, DEBINOSWAP, DEBIADDR_IR, 2) >> 8; if (code & 0x40) { code &= 0x3f; @@ -217,7 +260,6 @@ static void msp430_ir_deinit (struct budget_ci *budget_ci) saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_06); saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT); - saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT); if (del_timer(&dev->timer)) input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0); @@ -225,6 +267,58 @@ static void msp430_ir_deinit (struct budget_ci *budget_ci) input_unregister_device(dev); } +static int ciintf_init(struct budget_ci* budget_ci) +{ + struct saa7146_dev *saa = budget_ci->budget.dev; + + // enable DEBI pins +transfers + saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x880 << 16) | 0x880); + + // test if it is there + if ((budget_debiread(budget_ci, DEBICICTL, DEBIADDR_CIVERSION, 1) & 0xa0) != 0xa0) { + saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x880 << 16)); + return -ENODEV; + } + + // reset CI interface + budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, 0); + dvb_delay(1); + budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, 1); + + // clear any CI interrupt status + budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CIIRQCONTROL, 1, 0xC0); + + // FIXME: register CI slot + + // 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); + + // FIXME: route TS data out to CI interface +// saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI); + + // success! + printk("budget_ci: CI interface detected\n"); + budget_ci->ci_present = 1; + return 0; +} + +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); + saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT); + + // FIXME: disable TS data stream to CI interface + saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT); + + // disable DEBI pins+transfers again + saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x880 << 16)); +} static void budget_ci_irq (struct saa7146_dev *dev, u32 *isr) { @@ -237,6 +331,9 @@ static void budget_ci_irq (struct saa7146_dev *dev, u32 *isr) if (*isr & MASK_10) ttpci_budget_irq10_handler (dev, isr); + + if (*isr & MASK_03) + printk("CI IRQ!!\n"); } @@ -252,6 +349,9 @@ 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; + if ((err = ttpci_budget_init (&budget_ci->budget, dev, info))) { kfree (budget_ci); return err; @@ -263,6 +363,8 @@ static int budget_ci_attach (struct saa7146_dev* dev, (unsigned long) budget_ci); msp430_ir_init (budget_ci); + + ciintf_init(budget_ci); return 0; } @@ -272,7 +374,8 @@ static int budget_ci_attach (struct saa7146_dev* dev, static int budget_ci_detach (struct saa7146_dev* dev) { struct budget_ci *budget_ci = (struct budget_ci*) dev->ext_priv; - int err; + struct saa7146_dev *saa = budget_ci->budget.dev; + int err; err = ttpci_budget_deinit (&budget_ci->budget); @@ -280,6 +383,11 @@ 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); + kfree (budget_ci); return err; @@ -312,7 +420,7 @@ static struct saa7146_extension budget_extension = { .attach = budget_ci_attach, .detach = budget_ci_detach, - .irq_mask = MASK_06 | MASK_10, + .irq_mask = MASK_03 | MASK_06 | MASK_10, .irq_func = budget_ci_irq, }; @@ -333,7 +441,7 @@ module_init(budget_ci_init); module_exit(budget_ci_exit); MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Michael Hunold, Jack Thomasson, others"); +MODULE_AUTHOR("Michael Hunold, Jack Thomasson, Andrew de Quincey, others"); MODULE_DESCRIPTION("driver for the SAA7146 based so-called " "budget PCI DVB cards w/ CI-module produced by " "Siemens, Technotrend, Hauppauge"); |