summaryrefslogtreecommitdiff
path: root/linux/drivers/media/dvb/ttpci
diff options
context:
space:
mode:
authorAndrew de Quincy <devnull@localhost>2004-04-05 12:17:33 +0000
committerAndrew de Quincy <devnull@localhost>2004-04-05 12:17:33 +0000
commit65a6213f98192e62d653b6035502414c63053613 (patch)
tree226d419d5868894c3eefab1528bdaa8ba5cde5c4 /linux/drivers/media/dvb/ttpci
parent752cadb89bc935db0ec866d49cae06d79fc54487 (diff)
downloadmediapointer-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.c382
-rw-r--r--linux/drivers/media/dvb/ttpci/budget-core.c229
-rw-r--r--linux/drivers/media/dvb/ttpci/budget.h3
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);