All of lore.kernel.org
 help / color / mirror / Atom feed
From: Michael Hunold <hunold@linuxtv.org>
To: hunold@linuxtv.org, torvalds@osdl.org, akpm@osdl.org,
	linux-kernel@vger.kernel.org
Subject: [PATCH 3/9] DVB: Update DVB budget drivers
Date: Mon, 26 Apr 2004 09:41:51 -0400	[thread overview]
Message-ID: <10829867862196@convergence.de> (raw)
In-Reply-To: <10829867363017@convergence.de>

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 27354 bytes --]

- [DVB] budget-av: patch by Kenneth Aafløy to add support for Typhoon DVB-S budget card
- [DVB] budget.c: support for Fujitsu-Siemens Activy Card
- [DVB] budget-ci: add preliminary CI support
diff -urawBN xx-linux-2.6.5/drivers/media/dvb/ttpci/budget-av.c linux-2.6.5-patched/drivers/media/dvb/ttpci/budget-av.c
--- xx-linux-2.6.5/drivers/media/dvb/ttpci/budget-av.c	2004-03-12 20:31:29.000000000 +0100
+++ linux-2.6.5-patched/drivers/media/dvb/ttpci/budget-av.c	2004-03-19 18:13:56.000000000 +0100
@@ -39,6 +39,7 @@
 	struct budget budget;
 	struct video_device vd;
 	int cur_input;
+	int has_saa7113;
 };
 
 /****************************************************************************
@@ -149,6 +150,9 @@
 {
 	struct budget *budget = &budget_av->budget;
 
+	if ( 1 != budget_av->has_saa7113 )
+		return -ENODEV;
+
 	if (input == 1) {
 		i2c_writereg(budget->i2c_bus, 0x4a, 0x02, 0xc7);
 		i2c_writereg(budget->i2c_bus, 0x4a, 0x09, 0x80);
@@ -170,11 +174,13 @@
 
 	DEB_EE(("dev: %p\n",dev));
 
+	if ( 1 == budget_av->has_saa7113 ) {
 	saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO);
 
 	dvb_delay(200);
 
 	saa7146_unregister_device (&budget_av->vd, dev);
+	}
 
 	err = ttpci_budget_deinit (&budget_av->budget);
 
@@ -221,11 +227,8 @@
 	saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTHI);
 	dvb_delay(500);
 
-	if ((err = saa7113_init (budget_av))) {
-		/* fixme: proper cleanup here */
-		ERR(("cannot init saa7113.\n"));
-		return err;
-	}
+	if ( 0 == saa7113_init(budget_av) ) {
+		budget_av->has_saa7113 = 1;
 
 	if ( 0 != saa7146_vv_init(dev,&vv_data)) {
 		/* fixme: proper cleanup here */
@@ -246,14 +249,12 @@
 					SAA7146_HPS_SYNC_PORT_A);
 
 	saa7113_setinput (budget_av, 0);
+	} else {
+		budget_av->has_saa7113 = 0;
 
-	/* what is this? since we don't support open()/close()
-	   notifications, we simply put this into the release handler... */
-/*
 	saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO);
-	set_current_state(TASK_INTERRUPTIBLE);
-	schedule_timeout (20);
-*/
+	}
+
 	/* fixme: find some sane values here... */
 	saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
 
@@ -333,13 +334,13 @@
 static struct saa7146_standard standard[] = {
 	{
 		.name	= "PAL", 	.id	= V4L2_STD_PAL,
-		.v_offset	= 0x17,	.v_field 	= 288,	.v_calc		= 576,
-		.h_offset	= 0x14,	.h_pixels 	= 680,	.h_calc		= 680+1,
-		.v_max_out	= 576,	.h_max_out	= 768,
+		.v_offset	= 0x17,	.v_field 	= 288,
+		.h_offset	= 0x14,	.h_pixels 	= 680,  	      
+		.v_max_out	= 576,	.h_max_out	= 768
 	}, {
 		.name	= "NTSC", 	.id	= V4L2_STD_NTSC,
-		.v_offset	= 0x16,	.v_field 	= 240,	.v_calc		= 480,
-		.h_offset	= 0x06,	.h_pixels 	= 708,	.h_calc		= 708+1,
+		.v_offset	= 0x16,	.v_field 	= 240,
+		.h_offset	= 0x06,	.h_pixels 	= 708,
 		.v_max_out	= 480,	.h_max_out	= 640,
 	}
 };
diff -urawBN xx-linux-2.6.5/drivers/media/dvb/ttpci/budget.c linux-2.6.5-patched/drivers/media/dvb/ttpci/budget.c
--- xx-linux-2.6.5/drivers/media/dvb/ttpci/budget.c	2003-12-18 03:58:57.000000000 +0100
+++ linux-2.6.5-patched/drivers/media/dvb/ttpci/budget.c	2004-02-27 14:45:59.000000000 +0100
@@ -8,6 +8,11 @@
  * Copyright (C) 1999-2002 Ralph  Metzler 
  *                       & 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> and
+ *           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
  * as published by the Free Software Foundation; either version 2
@@ -142,6 +147,49 @@
 }
 
 
+/*
+ *   Routines for the Fujitsu Siemens Activy budget card
+ *   22 kHz tone and DiSEqC are handled by the frontend.
+ *   Voltage must be set here.
+ */
+static int SetVoltage_Activy (struct budget *budget, fe_sec_voltage_t voltage)
+{
+	struct saa7146_dev *dev=budget->dev;
+
+	DEB_EE(("budget: %p\n",budget));
+
+	switch (voltage) {
+		case SEC_VOLTAGE_13:
+			saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTLO);
+			break;
+		case SEC_VOLTAGE_18:
+			saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
+			break;
+		default:
+			return -EINVAL;
+	}
+
+	return 0;
+}
+
+
+static int budget_ioctl_activy (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_VOLTAGE:
+			return SetVoltage_Activy (budget, (fe_sec_voltage_t) arg);
+		default:
+			return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+
 static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info)
 {
 	struct budget *budget = NULL;
@@ -160,6 +208,10 @@
 		return err;
 	}
 
+	if (budget->card->type == BUDGET_FS_ACTIVY)
+		dvb_add_frontend_ioctls (budget->dvb_adapter,
+				 budget_ioctl_activy, NULL, budget);
+	else
 	dvb_add_frontend_ioctls (budget->dvb_adapter,
 				 budget_diseqc_ioctl, NULL, budget);
 
@@ -174,6 +226,10 @@
 	struct budget *budget = (struct budget*) dev->ext_priv;
 	int err;
 
+	if (budget->card->type == BUDGET_FS_ACTIVY)
+		dvb_remove_frontend_ioctls (budget->dvb_adapter,
+				    budget_ioctl_activy, NULL);
+	else
 	dvb_remove_frontend_ioctls (budget->dvb_adapter,
 				    budget_diseqc_ioctl, NULL);
 
@@ -193,6 +249,7 @@
 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(satel,	"SATELCO Multimedia PCI",	BUDGET_TT_HW_DISEQC);
+MAKE_BUDGET_INFO(fsacs, "Fujitsu Siemens Activy Budget-S PCI", BUDGET_FS_ACTIVY);
 /* Uncomment for Budget Patch */
 /*MAKE_BUDGET_INFO(fs_1_3,"Siemens/Technotrend/Hauppauge PCI rev1.3+Budget_Patch", BUDGET_PATCH);*/
 
@@ -203,6 +260,7 @@
 	MAKE_EXTENSION_PCI(ttbc,  0x13c2, 0x1004),
 	MAKE_EXTENSION_PCI(ttbt,  0x13c2, 0x1005),
 	MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013),
+	MAKE_EXTENSION_PCI(fsacs, 0x1131, 0x4f61),
 	{
 		.vendor    = 0,
 	}
diff -urawBN xx-linux-2.6.5/drivers/media/dvb/ttpci/budget-ci.c linux-2.6.5-patched/drivers/media/dvb/ttpci/budget-ci.c
--- xx-linux-2.6.5/drivers/media/dvb/ttpci/budget-ci.c	2004-01-16 18:25:17.000000000 +0100
+++ linux-2.6.5-patched/drivers/media/dvb/ttpci/budget-ci.c	2004-04-21 01:23:32.000000000 +0200
@@ -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,22 +36,59 @@
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/input.h>
+#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_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;
+	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_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)
 {
+	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));
@@ -53,18 +92,47 @@
 
 	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)
@@ -140,9 +208,8 @@
 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;
@@ -182,7 +249,8 @@
 
 	memset(&budget_ci->input_dev, 0, sizeof(struct input_dev));
 
-	budget_ci->input_dev.name = saa->name;
+	sprintf (budget_ci->ir_dev_name, "Budget-CI dvb ir receiver %s", saa->name);
+	budget_ci->input_dev.name = budget_ci->ir_dev_name;
 
 	set_bit(EV_KEY, budget_ci->input_dev.evbit);
 
@@ -209,7 +277,6 @@
 
 	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);
@@ -217,6 +284,209 @@
 	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);
+
+	saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
+   	ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
+	return 0;
+}
+
+static int ciintf_slot_shutdown(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;
+
+	saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
+	ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
+	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;
+	struct saa7146_dev *saa = budget_ci->budget.dev;
+	int tmp;
+
+	if (slot != 0) return -EINVAL;
+
+
+	saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTLO);
+
+	tmp = budget_debiread(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1);
+	budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, tmp | CICONTROL_ENABLETS);
+
+   	ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA);
+	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;
+	}
+
+	// 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;
+	}
+
+	// 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);
+
+	// success!
+	printk("budget_ci: CI interface initialised\n");
+	budget_ci->budget.ci_present = 1;
+
+	// 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);
+
+	return 0;
+
+error:
+	saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16));
+	return result;
+}
+
+static void ciintf_deinit(struct budget_ci* budget_ci)
+{
+	struct saa7146_dev *saa = budget_ci->budget.dev;
+
+	// 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);
+
+	// disable TS data stream to CI interface
+	saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT);
+
+	// 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)
 {
@@ -229,6 +499,9 @@
 
         if (*isr & MASK_10)
 		ttpci_budget_irq10_handler (dev, isr);
+
+	if ((*isr & MASK_03) && (budget_ci->budget.ci_present))
+		tasklet_schedule (&budget_ci->ciintf_irq_tasklet);
 }
 
 
@@ -244,6 +517,9 @@
 
 	DEB_EE(("budget_ci: %p\n", budget_ci));
 
+	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);
 		return err;
@@ -256,6 +532,9 @@
 
 	msp430_ir_init (budget_ci);
 
+	// UNCOMMENT TO TEST CI INTERFACE
+//	ciintf_init(budget_ci);
+
 	return 0;
 }
 
@@ -264,14 +543,20 @@
 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;
 
+	if (budget_ci->budget.ci_present) ciintf_deinit(budget_ci);
+
 	err = ttpci_budget_deinit (&budget_ci->budget);
 
 	tasklet_kill (&budget_ci->msp430_irq_tasklet);
 
 	msp430_ir_deinit (budget_ci);
 
+	// disable frontend and CI interface
+	saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT);
+
 	kfree (budget_ci);
 
 	return err;
@@ -304,7 +589,7 @@
 	.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,
 };	
 
@@ -325,7 +610,7 @@
 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");
diff -urawBN xx-linux-2.6.5/drivers/media/dvb/ttpci/budget-core.c linux-2.6.5-patched/drivers/media/dvb/ttpci/budget-core.c
--- xx-linux-2.6.5/drivers/media/dvb/ttpci/budget-core.c	2003-12-18 03:58:39.000000000 +0100
+++ linux-2.6.5-patched/drivers/media/dvb/ttpci/budget-core.c	2004-04-21 01:23:32.000000000 +0200
@@ -1,3 +1,39 @@
+/*
+ * budget-core.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
+ *
+ * 26feb2004 Support for FS Activy Card (Grundig tuner) by
+ *	     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
+ * 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"
 #include "ttpci-eeprom.h"
 
@@ -38,10 +74,33 @@
 
         budget->tsf=0xff;
         budget->ttbp=0;
+
+	/*
+	 *  Signal path on the Activy:
+	 *
+	 *  tuner -> SAA7146 port A -> SAA7146 BRS -> SAA7146 DMA3 -> memory
+	 *
+	 *  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
+	 */
+
+	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->video_port == BUDGET_VIDEO_PORTA) {
+			saa7146_write(dev, DD1_INIT, 0x06000200);
+			saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
+			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);
 
@@ -49,9 +108,15 @@
         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);
-        saa7146_write(dev, PITCH3, TS_WIDTH);
 
+	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
 
@@ -99,23 +164,31 @@
 {
         struct dvb_demux *demux = feed->demux;
         struct budget *budget = (struct budget*) demux->priv;
+	int status;
 
 	DEB_EE(("budget: %p\n",budget));
 
         if (!demux->dmx.frontend)
                 return -EINVAL;
 
-	return start_ts_capture (budget); 
+   	spin_lock(&budget->feedlock);   
+	status = start_ts_capture (budget);
+   	spin_unlock(&budget->feedlock);
+	return status;
 }
 
 static int budget_stop_feed(struct dvb_demux_feed *feed)
 {
         struct dvb_demux *demux = feed->demux;
         struct budget *budget = (struct budget *) demux->priv;
+	int status;
 
 	DEB_EE(("budget: %p\n",budget));
 
-	return stop_ts_capture (budget); 
+   	spin_lock(&budget->feedlock);
+	status = stop_ts_capture (budget);
+   	spin_unlock(&budget->feedlock);
+	return status;
 }
 
 
@@ -208,18 +281,27 @@
 	budget->card = bi;
 	budget->dev = (struct saa7146_dev *) dev;
 
-	dvb_register_adapter(&budget->dvb_adapter, budget->card->name);
+	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, MC2, (MASK_09 | MASK_25));
+	saa7146_write(dev, MC2, (MASK_10 | MASK_26));
 	saa7146_write(dev, DD1_INIT, 0x02000000);
 	saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
 
+       	if (bi->type != BUDGET_FS_ACTIVY)
+		budget->video_port = BUDGET_VIDEO_PORTB;
+	else
+		budget->video_port = BUDGET_VIDEO_PORTA;
+	spin_lock_init(&budget->feedlock);
+
 	/* the Siemens DVB needs this if you want to have the i2c chips
            get recognized before the main driver is loaded */
-        saa7146_write(dev, GPIO_CTRL, 0x500000);
+	if (bi->type != BUDGET_FS_ACTIVY)
+		saa7146_write(dev, GPIO_CTRL, 0x500000); /* GPIO 3 = 1 */
 	
-	saa7146_i2c_adapter_prepare(dev, NULL, SAA7146_I2C_BUS_BIT_RATE_120);
+	saa7146_i2c_adapter_prepare(dev, NULL, 0, SAA7146_I2C_BUS_BIT_RATE_120);
 
 	budget->i2c_bus = dvb_register_i2c_bus (master_xfer, dev,
 						budget->dvb_adapter, 0);
@@ -242,7 +324,11 @@
 
 	tasklet_init (&budget->vpe_tasklet, vpeirq, (unsigned long) budget);
 
-	saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI); /* frontend power on */
+	/* frontend power on */
+	if (bi->type == BUDGET_FS_ACTIVY)
+		saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI);
+	else
+		saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
 
         if (budget_register(budget) == 0) {
 		return 0;
@@ -292,10 +378,28 @@
 		tasklet_schedule (&budget->vpe_tasklet);
 }
 
+void ttpci_budget_set_video_port(struct saa7146_dev* dev, int video_port)
+{
+	struct budget *budget = (struct budget*)dev->ext_priv;
+
+	spin_lock(&budget->feedlock);
+	budget->video_port = video_port;
+	if (budget->feeding) {
+		int oldfeeding = budget->feeding;
+	   	budget->feeding = 1;
+		stop_ts_capture(budget);
+		start_ts_capture(budget);
+	   	budget->feeding = oldfeeding;
+	}
+   	spin_unlock(&budget->feedlock);
+}
+
+
 
 EXPORT_SYMBOL_GPL(ttpci_budget_init);
 EXPORT_SYMBOL_GPL(ttpci_budget_deinit);
 EXPORT_SYMBOL_GPL(ttpci_budget_irq10_handler);
+EXPORT_SYMBOL_GPL(ttpci_budget_set_video_port);
 EXPORT_SYMBOL_GPL(budget_debug);
 
 MODULE_PARM(budget_debug,"i");
diff -urawBN xx-linux-2.6.5/drivers/media/dvb/ttpci/budget.h linux-2.6.5-patched/drivers/media/dvb/ttpci/budget.h
--- xx-linux-2.6.5/drivers/media/dvb/ttpci/budget.h	2004-01-16 18:25:17.000000000 +0100
+++ linux-2.6.5-patched/drivers/media/dvb/ttpci/budget.h	2004-04-21 01:23:32.000000000 +0200
@@ -46,10 +46,15 @@
         int                     fe_synced; 
         struct semaphore        pid_mutex;
 
+	int                     ci_present;
+        int                     video_port;
+
         u8 tsf;
         u32 ttbp;
         int feeding;
 
+	spinlock_t feedlock;
+
         struct dvb_adapter       *dvb_adapter;
 	void			 *priv;
 };
@@ -73,13 +78,17 @@
 #define BUDGET_TT_HW_DISEQC	   1
 #define BUDGET_KNC1		   2
 #define BUDGET_PATCH		   3
+#define BUDGET_FS_ACTIVY	   4
 
+#define BUDGET_VIDEO_PORTA         0
+#define BUDGET_VIDEO_PORTB         1
 
 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);
+extern void ttpci_budget_set_video_port(struct saa7146_dev* dev, int video_port);
 
 #endif
 



  reply	other threads:[~2004-04-26 13:47 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-04-26 13:40 [PATCH 0/9] LinuxTV.org DVB update Michael Hunold
2004-04-26 13:40 ` [PATCH 1/9] V4L: Update the saa7146 driver Michael Hunold
2004-04-26 13:41   ` [PATCH 2/9] DVB: Documentation and Kconfig updazes Michael Hunold
2004-04-26 13:41     ` Michael Hunold [this message]
2004-04-26 13:42       ` [PATCH 4/9] DVB: Add EN50221 cam support to dvb-core Michael Hunold
2004-04-26 13:42         ` [PATCH 5/9] DVB: Other DVB core updates Michael Hunold
2004-04-26 13:42           ` [PATCH 6/9] DVB: AV7110 DVB driver updates Michael Hunold
2004-04-26 13:42             ` [PATCH 7/9] DVB: Misc. DVB frontend " Michael Hunold
2004-04-26 13:42               ` [PATCH 8/9] DVB: Misc. DVB USB " Michael Hunold
2004-04-26 13:42                 ` [PATCH 9/9] DVB: Follow saa7146 changes in affected V4L drivers Michael Hunold
2004-04-26 14:05     ` [PATCH 2/9] DVB: Documentation and Kconfig updazes Måns Rullgård

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=10829867862196@convergence.de \
    --to=hunold@linuxtv.org \
    --cc=akpm@osdl.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=torvalds@osdl.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.