Skip to contentSkip to conversation

Update saa7146 driver core

PATCH New Michael Hunold (LinuxTV.org CVS maintainer) 1 participant 7 messages Jun 25, 2003 Media (V4L/DVB)

lore
Share & tools
lore
#0 lore raw

PATCH 1/7 Update saa7146 driver core

- fix WRITE_RPS0 and WRITE_RPS1 inlines, fix usage in mxb and budget drivers
- export "saa7146_start_preview" and "saa7146_stop_preview" to allow drivers to start and stop video overlay (necessary for analog module support in the av7110 driver)
- fix i2c implementation: some frontend drivers transfer a huge amount of firmware data (> 30kB), speed up the transmission by busy waiting between byte transfers for bigger transmissions
- change ioctl function in various driver to accept a saa7146 filehandle instead of a saa714 device structure

drivers/media/common/saa7146_hlp.c +1 -0
diff -uNrwB --new-file linux-2.5.73.bk/drivers/media/common/saa7146_hlp.c linux-2.5.73.work/drivers/media/common/saa7146_hlp.c
@@ -935,6 +935,7 @@
 static void program_capture_engine(struct saa7146_dev *dev, int planar)
 {
 	struct saa7146_vv *vv = dev->vv_data;
+	int count = 0;
 
 	unsigned long e_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_E_FID_A : CMD_E_FID_B;
 	unsigned long o_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_O_FID_A : CMD_O_FID_B;
drivers/media/common/saa7146_vbi.c +1 -0
diff -uNrwB --new-file linux-2.5.73.bk/drivers/media/common/saa7146_vbi.c linux-2.5.73.work/drivers/media/common/saa7146_vbi.c
@@ -9,6 +9,7 @@
         u32          *cpu;
         dma_addr_t   dma_addr;
 	
+	int count = 0;
 	int i;
 
 	DECLARE_WAITQUEUE(wait, current);
drivers/media/dvb/ttpci/budget-patch.c +1 -0
diff -uNrwB --new-file linux-2.5.73.bk/drivers/media/dvb/ttpci/budget-patch.c linux-2.5.73.work/drivers/media/dvb/ttpci/budget-patch.c
@@ -165,6 +165,7 @@
 {
         struct budget_patch *budget;
         int err;
+	int count = 0;
 
         if (!(budget = kmalloc (sizeof(struct budget_patch), GFP_KERNEL)))
                 return -ENOMEM;
drivers/media/common/saa7146_i2c.c +15 -5
diff -uNrwB --new-file linux-2.5.73.bk/drivers/media/common/saa7146_i2c.c linux-2.5.73.work/drivers/media/common/saa7146_i2c.c
@@ -181,9 +181,10 @@
 /* this functions writes out the data-byte 'dword' to the i2c-device.
    it returns 0 if ok, -1 if the transfer failed, -2 if the transfer
    failed badly (e.g. address error) */
-static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword)
+static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_delay)
 {
 	u32 status = 0, mc2 = 0;
+	int trial = 0;
 	int timeout;
 
 	/* write out i2c-command */
@@ -224,10 +225,13 @@
 		/* wait until we get a transfer done or error */
 		timeout = jiffies + HZ/100 + 1; /* 10ms */
 		while(1) {
+			/**
+			 *  first read usually delivers bogus results...
+			 */
+			saa7146_i2c_status(dev);
 			status = saa7146_i2c_status(dev);
-			if( (0x3 == (status & 0x3)) || (0 == (status & 0x1)) ) {
+			if ((status & 0x3) != 1)
 				break;
-			}
 			if (jiffies > timeout) {
 				/* this is normal when probing the bus
 				 * (no answer from nonexisistant device...)
@@ -235,6 +239,9 @@
 				DEB_I2C(("saa7146_i2c_writeout: timed out waiting for end of xfer\n"));
 				return -EIO;
 			}
+			if ((++trial < 20) && short_delay)
+				udelay(10);
+			else
 			my_wait(dev,1);
 		}
 	}
@@ -277,6 +284,7 @@
 	u32* buffer = dev->d_i2c.cpu_addr;
 	int err = 0;
         int address_err = 0;
+        int short_delay = 0;
 	
 	if (down_interruptible (&dev->i2c_lock))
 		return -ERESTARTSYS;
@@ -292,6 +300,8 @@
 		goto out;
 	}
 
+        if (count > 3) short_delay = 1;
+  
 	do {
 		/* reset the i2c-device if necessary */
 		err = saa7146_i2c_reset(dev);
@@ -302,7 +312,7 @@
 
 		/* write out the u32s one after another */
 		for(i = 0; i < count; i++) {
-			err = saa7146_i2c_writeout(dev, &buffer[i] );
+			err = saa7146_i2c_writeout(dev, &buffer[i], short_delay);
 			if ( 0 != err) {
 				/* this one is unsatisfying: some i2c slaves on some
 				   dvb cards don't acknowledge correctly, so the saa7146
@@ -357,7 +367,7 @@
 	if( 0 == dev->revision ) {
 		u32 zero = 0;
 		saa7146_i2c_reset(dev);
-		if( 0 != saa7146_i2c_writeout(dev, &zero)) {
+		if( 0 != saa7146_i2c_writeout(dev, &zero, short_delay)) {
 			INFO(("revision 0 error. this should never happen.\n"));
 		}
 	}
drivers/media/common/saa7146_video.c +19 -16
diff -uNrwB --new-file linux-2.5.73.bk/drivers/media/common/saa7146_video.c linux-2.5.73.work/drivers/media/common/saa7146_video.c
@@ -220,7 +220,7 @@
 	}
 }
 
-static int start_preview(struct saa7146_fh *fh)
+int saa7146_start_preview(struct saa7146_fh *fh)
 {
 	struct saa7146_dev *dev = fh->dev;
 	struct saa7146_vv *vv = dev->vv_data;
@@ -266,12 +266,12 @@
 	return 0;
 }
 
-static int stop_preview(struct saa7146_fh *fh)
+int saa7146_stop_preview(struct saa7146_fh *fh)
 {
 	struct saa7146_dev *dev = fh->dev;
 	struct saa7146_vv *vv = dev->vv_data;
 
-	DEB_EE(("saa7146.o: stop_preview()\n"));
+	DEB_EE(("saa7146.o: saa7146_stop_preview()\n"));
 
 	/* check if overlay is running */
 	if( 0 == vv->ov_data ) {
@@ -333,8 +333,8 @@
 		if( vv->ov_data != NULL ) {
 			if( fh == vv->ov_data->fh) {
 				spin_lock_irqsave(&dev->slock,flags);
-				stop_preview(fh);
-				start_preview(fh);
+				saa7146_stop_preview(fh);
+				saa7146_start_preview(fh);
 				spin_unlock_irqrestore(&dev->slock,flags);
 			}
 		}
@@ -522,8 +522,8 @@
 		if( 0 != vv->ov_data ) {
 			if( fh == vv->ov_data->fh ) {
 				spin_lock_irqsave(&dev->slock,flags);
-				stop_preview(fh);
-				start_preview(fh);
+				saa7146_stop_preview(fh);
+				saa7146_start_preview(fh);
 				spin_unlock_irqrestore(&dev->slock,flags);
 			}
 		}
@@ -747,12 +747,12 @@
 	
 	if( 0 != (dev->ext->ext_vv_data->ioctls[ee].flags & SAA7146_EXCLUSIVE) ) {
 		DEB_D(("extension handles ioctl exclusive.\n"));
-		result = dev->ext->ext_vv_data->ioctl(dev, cmd, arg);
+		result = dev->ext->ext_vv_data->ioctl(fh, cmd, arg);
 		return result;
 	}
 	if( 0 != (dev->ext->ext_vv_data->ioctls[ee].flags & SAA7146_BEFORE) ) {
 		DEB_D(("extension handles ioctl before.\n"));
-		result = dev->ext->ext_vv_data->ioctl(dev, cmd, arg);
+		result = dev->ext->ext_vv_data->ioctl(fh, cmd, arg);
 		if( -EAGAIN != result ) {
 			return result;
 		}
@@ -968,7 +968,7 @@
 
 		if( vv->ov_data != NULL ) {
 			ov_fh = vv->ov_data->fh;
-			stop_preview(ov_fh);
+			saa7146_stop_preview(ov_fh);
 			restart_overlay = 1;
 		}
 
@@ -983,7 +983,7 @@
 		}
 
 		if( 0 != restart_overlay ) {
-			start_preview(ov_fh);
+			saa7146_start_preview(ov_fh);
 		}
 		up(&dev->lock);
 
@@ -1013,7 +1013,7 @@
 				}
 			}
 			spin_lock_irqsave(&dev->slock,flags);
-			err = start_preview(fh);
+			err = saa7146_start_preview(fh);
 			spin_unlock_irqrestore(&dev->slock,flags);
 		} else {
 			if( vv->ov_data != NULL ) {
@@ -1022,7 +1022,7 @@
 				}
 			}
 			spin_lock_irqsave(&dev->slock,flags);
-			err = stop_preview(fh);
+			err = saa7146_stop_preview(fh);
 			spin_unlock_irqrestore(&dev->slock,flags);
 		}
 		return err;
@@ -1287,7 +1287,7 @@
 	if( 0 != vv->ov_data ) {
 		if( fh == vv->ov_data->fh ) {
 			spin_lock_irqsave(&dev->slock,flags);
-			stop_preview(fh);
+			saa7146_stop_preview(fh);
 			spin_unlock_irqrestore(&dev->slock,flags);
 		}
 	}
@@ -1331,7 +1331,7 @@
 
 	if( vv->ov_data != NULL ) {
 		ov_fh = vv->ov_data->fh;
-		stop_preview(ov_fh);
+		saa7146_stop_preview(ov_fh);
 		restart_overlay = 1;
 	}
 
@@ -1343,7 +1343,7 @@
 
 	/* restart overlay if it was active before */
 	if( 0 != restart_overlay ) {
-		start_preview(ov_fh);
+		saa7146_start_preview(ov_fh);
 	}
 	
 	return ret;
@@ -1360,3 +1360,6 @@
 };
 
 EXPORT_SYMBOL_GPL(saa7146_video_uops);
+
+EXPORT_SYMBOL_GPL(saa7146_start_preview);
+EXPORT_SYMBOL_GPL(saa7146_stop_preview);
include/media/saa7146_vv.h +3 -3
diff -uNrwB --new-file linux-2.5.73.bk/include/media/saa7146_vv.h linux-2.5.73.work/include/media/saa7146_vv.h
@@ -10,12 +10,10 @@
 #define BUFFER_TIMEOUT     (HZ/2)  /* 0.5 seconds */
 
 #define WRITE_RPS0(x) do { \
-	static int count = 0;	\
 	dev->d_rps0.cpu_addr[ count++ ] = cpu_to_le32(x); \
 	} while (0);
 
 #define WRITE_RPS1(x) do { \
-	static int count = 0;	\
 	dev->d_rps1.cpu_addr[ count++ ] = cpu_to_le32(x); \
 	} while (0);
 
@@ -166,7 +164,7 @@
 	int (*std_callback)(struct saa7146_dev*, struct saa7146_standard *);
 		
 	struct saa7146_extension_ioctls *ioctls;
-	int (*ioctl)(struct saa7146_dev*, unsigned int cmd, void *arg);
+	int (*ioctl)(struct saa7146_fh*, unsigned int cmd, void *arg);
 };
 
 struct saa7146_use_ops  {
@@ -201,6 +199,8 @@
 
 /* from saa7146_video.c */
 extern struct saa7146_use_ops saa7146_video_uops;
+int saa7146_start_preview(struct saa7146_fh *fh);
+int saa7146_stop_preview(struct saa7146_fh *fh);
 
 /* from saa7146_vbi.c */
 extern struct saa7146_use_ops saa7146_vbi_uops;
drivers/media/dvb/ttpci/budget-av.c +2 -1
diff -uNrwB --new-file linux-2.5.73.bk/drivers/media/dvb/ttpci/budget-av.c linux-2.5.73.work/drivers/media/dvb/ttpci/budget-av.c
@@ -256,8 +256,9 @@
 };
 
 
-static int av_ioctl(struct saa7146_dev *dev, unsigned int cmd, void *arg) 
+static int av_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) 
 {
+	struct saa7146_dev *dev = fh->dev;
 	struct budget_av *budget_av = (struct budget_av*) dev->ext_priv;
 /*
 	struct saa7146_vv *vv = dev->vv_data; 
drivers/media/video/dpc7146.c +2 -1
diff -uNrwB --new-file linux-2.5.73.bk/drivers/media/video/dpc7146.c linux-2.5.73.work/drivers/media/video/dpc7146.c
@@ -246,8 +246,9 @@
 }
 #endif
 
-static int dpc_ioctl(struct saa7146_dev *dev, unsigned int cmd, void *arg) 
+static int dpc_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) 
 {
+	struct saa7146_dev *dev = fh->dev;
 	struct dpc* dpc = (struct dpc*)dev->ext_priv;
 /*
 	struct saa7146_vv *vv = dev->vv_data; 
drivers/media/video/mxb.c +2 -1
diff -uNrwB --new-file linux-2.5.73.bk/drivers/media/video/mxb.c linux-2.5.73.work/drivers/media/video/mxb.c
@@ -566,8 +566,9 @@
 	return 0;
 }
 
-static int mxb_ioctl(struct saa7146_dev *dev, unsigned int cmd, void *arg) 
+static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) 
 {
+	struct saa7146_dev *dev = fh->dev;
 	struct mxb* mxb = (struct mxb*)dev->ext_priv;
 	struct saa7146_vv *vv = dev->vv_data; 
 	
#1 lore raw

PATCH 2/7 Update dvb core

- indentation fixes in dvb_demux.c
- include cleanup in various files
- simplify dvb/ttpci/Makefile

drivers/media/dvb/dvb-core/dvb_demux.c +4 -4
diff -uNrwB --new-file linux-2.5.73.bk/drivers/media/dvb/dvb-core/dvb_demux.c linux-2.5.73.work/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -1110,8 +1130,8 @@
 	return 0;
 }
 
-int 
-dvb_dmx_init(struct dvb_demux *dvbdemux)
+
+int dvb_dmx_init(struct dvb_demux *dvbdemux)
 {
 	int i, err;
 	struct dmx_demux *dmx = &dvbdemux->dmx;
@@ -1181,8 +1207,8 @@
 	return 0;
 }
 
-int 
-dvb_dmx_release(struct dvb_demux *dvbdemux)
+
+int dvb_dmx_release(struct dvb_demux *dvbdemux)
 {
 	struct dmx_demux *dmx = &dvbdemux->dmx;
 
drivers/media/dvb/dvb-core/dvb_functions.c +3 -3
diff -uNrwB --new-file linux-2.5.73.bk/drivers/media/dvb/dvb-core/dvb_functions.c linux-2.5.73.work/drivers/media/dvb/dvb-core/dvb_functions.c
@@ -1,10 +1,10 @@
 #include <linux/version.h>
-#include <linux/string.h>
-#include <linux/smp_lock.h>
-#include <linux/fs.h>
 #include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/string.h>
 #include <linux/module.h>
 #include <linux/ioctl.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <asm/uaccess.h>
 
drivers/media/dvb/dvb-core/dvb_functions.h +2 -0
diff -uNrwB --new-file linux-2.5.73.bk/drivers/media/dvb/dvb-core/dvb_functions.h linux-2.5.73.work/drivers/media/dvb/dvb-core/dvb_functions.h
@@ -1,6 +1,8 @@
 #ifndef __DVB_FUNCTIONS_H__
 #define __DVB_FUNCTIONS_H__
 
+#include <linux/version.h>
+
 /**
  *  a sleeping delay function, waits i ms
  *
drivers/media/dvb/dvb-core/dvbdev.c +0 -2
diff -uNrwB --new-file linux-2.5.73.bk/drivers/media/dvb/dvb-core/dvbdev.c linux-2.5.73.work/drivers/media/dvb/dvb-core/dvbdev.c
@@ -29,8 +29,6 @@
 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <linux/version.h>
-#include <asm/semaphore.h>
 
 #include "dvbdev.h"
 #include "dvb_functions.h"

int dvb_generic_open(struct inode *inode, struct file *file)

drivers/media/dvb/dvb-core/dvbdev.h +2 -1
diff -uNrwB --new-file linux-2.5.73.bk/drivers/media/dvb/dvb-core/dvbdev.h linux-2.5.73.work/drivers/media/dvb/dvb-core/dvbdev.h
@@ -27,8 +27,9 @@
 #include <linux/types.h>
 #include <linux/poll.h>
 #include <linux/fs.h>
-#include <linux/devfs_fs_kernel.h>
 #include <linux/list.h>
+#include <linux/version.h>
+#include <linux/devfs_fs_kernel.h>
 
 #define DVB_MAJOR 250
 
drivers/media/dvb/ttpci/Makefile +5 -9
diff -uNrwB --new-file linux-2.5.73.bk/drivers/media/dvb/ttpci/Makefile linux-2.5.73.work/drivers/media/dvb/ttpci/Makefile
@@ -3,16 +3,12 @@
 # and the AV7110 DVB device driver
 #
 
-dvb-ttpci-budget-objs := budget.o
-dvb-ttpci-budget-av-objs := budget-av.o
-dvb-ttpci-budget-ci-objs := budget-ci.o
-dvb-ttpci-budget-patch-objs := budget-patch.o
 dvb-ttpci-objs := av7110.o av7110_ipack.o av7110_ir.o
 
-obj-$(CONFIG_DVB_BUDGET) += budget-core.o dvb-ttpci-budget.o
-obj-$(CONFIG_DVB_BUDGET_CI) += budget-core.o dvb-ttpci-budget-ci.o
-obj-$(CONFIG_DVB_BUDGET_AV) += budget-core.o dvb-ttpci-budget-av.o
-obj-$(CONFIG_DVB_BUDGET_PATCH) += budget-core.o dvb-ttpci-budget-patch.o
-obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o
+obj-$(CONFIG_DVB_BUDGET) += budget-core.o budget.o ttpci-eeprom.o
+obj-$(CONFIG_DVB_BUDGET_AV) += budget-core.o budget-av.o ttpci-eeprom.o
+obj-$(CONFIG_DVB_BUDGET_CI) += budget-core.o budget-ci.o ttpci-eeprom.o
+obj-$(CONFIG_DVB_BUDGET_PATCH) += budget-core.o budget-patch.o ttpci-eeprom.o
+obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o ttpci-eeprom.o
 
 EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/
#2 lore raw

PATCH 3/7 Major dvb_net update

- code review and fix the old race condition in dev->set_multicast_list
- use tq_schedule instead of tq_immediate
- remove card_num and dev_num from struct dvb_net (now obsolete)
- prevent interface from being removed while it is in use
- allow add/remove only for the superuser
- set check-CRC flag on section filter to drop broken packets
- some more debug printfs in filter handling code
- cleaned up and commented packet reception handler
- fix formatting

drivers/media/dvb/dvb-core/dvb_net.c +207 -134
diff -uNrwB --new-file linux-2.5.73.bk/drivers/media/dvb/dvb-core/dvb_net.c linux-2.5.73.work/drivers/media/dvb/dvb-core/dvb_net.c
@@ -24,22 +24,25 @@
  * 
  */
 
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/ioctl.h>
-#include <linux/slab.h>
-#include <asm/uaccess.h>
-
 #include <linux/dvb/net.h>
+#include <asm/uaccess.h>
 
 #include "dvb_demux.h"
 #include "dvb_net.h"
 #include "dvb_functions.h"
 
+
+#if 1
+#define dprintk(x...) printk(x)
+#else
+#define dprintk(x...)
+#endif
+
+
 #define DVB_NET_MULTICAST_MAX 10
 
 struct dvb_net_priv {
+	int in_use;
         struct net_device_stats stats;
         char name[6];
 	u16 pid;
@@ -49,10 +52,16 @@
 	int multi_num;
 	struct dmx_section_filter *multi_secfilter[DVB_NET_MULTICAST_MAX];
 	unsigned char multi_macs[DVB_NET_MULTICAST_MAX][6];
-	int mode;
+	int rx_mode;
+#define RX_MODE_UNI 0
+#define RX_MODE_MULTI 1
+#define RX_MODE_ALL_MULTI 2
+#define RX_MODE_PROMISC 3
+	struct work_struct wq;
 };
 
-/*
+
+/**
  *	Determine the packet's protocol ID. The rule here is that we 
  *	assume 802.3 if the type field is short enough to be a length.
  *	This is normal practice and works for any 'now in use' protocol.
@@ -60,8 +69,8 @@
  *  stolen from eth.c out of the linux kernel, hacked for dvb-device
  *  by Michael Holzt <[email protected]>
  */
- 
-unsigned short my_eth_type_trans(struct sk_buff *skb, struct net_device *dev)
+static unsigned short dvb_net_eth_type_trans(struct sk_buff *skb,
+				      struct net_device *dev)
 {
 	struct ethhdr *eth;
 	unsigned char *rawp;
@@ -70,8 +79,7 @@
 	skb_pull(skb,dev->hard_header_len);
 	eth= skb->mac.ethernet;
 	
-	if(*eth->h_dest&1)
-	{
+	if (*eth->h_dest & 1) {
 		if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0)
 			skb->pkt_type=PACKET_BROADCAST;
 		else
@@ -83,7 +91,7 @@
 		
 	rawp = skb->data;
 	
-	/*
+	/**
 	 *	This is a magic hack to spot IPX packets. Older Novell breaks
 	 *	the protocol design and runs IPX over 802.3 without an 802.2 LLC
 	 *	layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
@@ -92,31 +100,60 @@
 	if (*(unsigned short *)rawp == 0xFFFF)
 		return htons(ETH_P_802_3);
 		
-	/*
+	/**
 	 *	Real 802.2 LLC
 	 */
 	return htons(ETH_P_802_2);
 }
 
-static void dvb_net_sec(struct net_device *dev, const u8 *pkt, int pkt_len)
+
+static void dvb_net_sec(struct net_device *dev, u8 *pkt, int pkt_len)
 {
         u8 *eth;
         struct sk_buff *skb;
 
-        if (pkt_len<13) {
-                printk("%s: IP/MPE packet length = %d too small.\n", dev->name, pkt_len);
+	/* note: pkt_len includes a 32bit checksum */
+	if (pkt_len < 16) {
+		printk("%s: IP/MPE packet length = %d too small.\n",
+			dev->name, pkt_len);
+		((struct dvb_net_priv *) dev->priv)->stats.rx_errors++;
+		((struct dvb_net_priv *) dev->priv)->stats.rx_length_errors++;
+		return;
+	}
+	if ((pkt[5] & 0xfd) != 0xc1) {
+		/* drop scrambled or broken packets */
+		((struct dvb_net_priv *) dev->priv)->stats.rx_errors++;
+		((struct dvb_net_priv *) dev->priv)->stats.rx_crc_errors++;
 		return;
 	}
-        skb = dev_alloc_skb(pkt_len+2);
-        if (skb == NULL) {
-                printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n",
-                       dev->name);
+	if (pkt[5] & 0x02) {
+		//FIXME: handle LLC/SNAP
                 ((struct dvb_net_priv *)dev->priv)->stats.rx_dropped++;
                 return;
         }
-        eth=(u8 *) skb_put(skb, pkt_len+2);
-        memcpy(eth+14, (void*)pkt+12, pkt_len-12);
+	if (pkt[7]) {
+		/* FIXME: assemble datagram from multiple sections */
+		((struct dvb_net_priv *) dev->priv)->stats.rx_errors++;
+		((struct dvb_net_priv *) dev->priv)->stats.rx_frame_errors++;
+		return;
+	}
+
+	/* we have 14 byte ethernet header (ip header follows);
+	 * 12 byte MPE header; 4 byte checksum; + 2 byte alignment
+	 */
+	if (!(skb = dev_alloc_skb(pkt_len - 4 - 12 + 14 + 2))) {
+		//printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
+		((struct dvb_net_priv *) dev->priv)->stats.rx_dropped++;
+		return;
+	}
+	skb_reserve(skb, 2);    /* longword align L3 header */
+	skb->dev = dev;
+
+	/* copy L3 payload */
+	eth = (u8 *) skb_put(skb, pkt_len - 12 - 4 + 14);
+	memcpy(eth + 14, pkt + 12, pkt_len - 12 - 4);
 
+	/* create ethernet header: */
         eth[0]=pkt[0x0b];
         eth[1]=pkt[0x0a];
         eth[2]=pkt[0x09];
@@ -123,11 +160,13 @@
         eth[3]=pkt[0x08];
         eth[4]=pkt[0x04];
         eth[5]=pkt[0x03];
+
         eth[6]=eth[7]=eth[8]=eth[9]=eth[10]=eth[11]=0;
-        eth[12]=0x08; eth[13]=0x00;
 
-	skb->protocol=my_eth_type_trans(skb,dev);
-        skb->dev=dev;
+	eth[12] = 0x08;	/* ETH_P_IP */
+	eth[13] = 0x00;
+
+	skb->protocol = dvb_net_eth_type_trans(skb, dev);
         
         ((struct dvb_net_priv *)dev->priv)->stats.rx_packets++;
         ((struct dvb_net_priv *)dev->priv)->stats.rx_bytes+=skb->len;
@@ -141,9 +180,11 @@
 {
         struct net_device *dev=(struct net_device *) filter->priv;
 
-	/* FIXME: this only works if exactly one complete section is
-	          delivered in buffer1 only */
-	dvb_net_sec(dev, buffer1, buffer1_len);
+	/**
+	 * we rely on the DVB API definition where exactly one complete
+	 * section is delivered in buffer1
+	 */
+	dvb_net_sec (dev, (u8*) buffer1, buffer1_len);
 	return 0;
 }
 
@@ -178,24 +223,27 @@
 	memset((*secfilter)->filter_mode,  0xff, DMX_MAX_FILTER_SIZE);
 
 	(*secfilter)->filter_value[0]=0x3e;
-	(*secfilter)->filter_mask[0]=0xff;
-
 	(*secfilter)->filter_value[3]=mac[5];
-	(*secfilter)->filter_mask[3]=mac_mask[5];
 	(*secfilter)->filter_value[4]=mac[4];
-	(*secfilter)->filter_mask[4]=mac_mask[4];
 	(*secfilter)->filter_value[8]=mac[3];
-	(*secfilter)->filter_mask[8]=mac_mask[3];
 	(*secfilter)->filter_value[9]=mac[2];
-	(*secfilter)->filter_mask[9]=mac_mask[2];
-
 	(*secfilter)->filter_value[10]=mac[1];
-	(*secfilter)->filter_mask[10]=mac_mask[1];
 	(*secfilter)->filter_value[11]=mac[0];
+
+	(*secfilter)->filter_mask[0] = 0xff;
+	(*secfilter)->filter_mask[3] = mac_mask[5];
+	(*secfilter)->filter_mask[4] = mac_mask[4];
+	(*secfilter)->filter_mask[8] = mac_mask[3];
+	(*secfilter)->filter_mask[9] = mac_mask[2];
+	(*secfilter)->filter_mask[10] = mac_mask[1];
 	(*secfilter)->filter_mask[11]=mac_mask[0];
 
-	printk("%s: filter mac=%02x %02x %02x %02x %02x %02x\n", 
+	dprintk("%s: filter mac=%02x %02x %02x %02x %02x %02x\n",
 	       dev->name, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+	dprintk("%s: filter mask=%02x %02x %02x %02x %02x %02x\n",
+	       dev->name, mac_mask[0], mac_mask[1], mac_mask[2],
+	       mac_mask[3], mac_mask[4], mac_mask[5]);
+
 	return 0;
 }
 
@@ -206,46 +254,57 @@
         struct dmx_demux *demux = priv->demux;
         unsigned char *mac = (unsigned char *) dev->dev_addr;
 		
+	dprintk("%s: rx_mode %i\n", __FUNCTION__, priv->rx_mode);
+	if (priv->secfeed || priv->secfilter || priv->multi_secfilter[0])
+		printk("%s: BUG %d\n", __FUNCTION__, __LINE__);
+
 	priv->secfeed=0;
 	priv->secfilter=0;
 
+	dprintk("%s: alloc secfeed\n", __FUNCTION__);
 	ret=demux->allocate_section_feed(demux, &priv->secfeed, 
 					 dvb_net_callback);
 	if (ret<0) {
-		printk("%s: could not get section feed\n", dev->name);
+		printk("%s: could not allocate section feed\n", dev->name);
 		return ret;
 	}
 
-	ret=priv->secfeed->set(priv->secfeed, priv->pid, 32768, 0, 0);
+	ret = priv->secfeed->set(priv->secfeed, priv->pid, 32768, 0, 1);
+
 	if (ret<0) {
 		printk("%s: could not set section feed\n", dev->name);
-		priv->demux->
-		        release_section_feed(priv->demux, priv->secfeed);
+		priv->demux->release_section_feed(priv->demux, priv->secfeed);
 		priv->secfeed=0;
 		return ret;
 	}
-	/* fixme: is this correct? */
-	try_module_get(THIS_MODULE);
 
-	if (priv->mode<3) 
+	if (priv->rx_mode != RX_MODE_PROMISC) {
+		dprintk("%s: set secfilter\n", __FUNCTION__);
 		dvb_net_filter_set(dev, &priv->secfilter, mac, mask_normal);
+	}
 
-	switch (priv->mode) {
-	case 1:
-		for (i=0; i<priv->multi_num; i++) 
+	switch (priv->rx_mode) {
+	case RX_MODE_MULTI:
+		for (i = 0; i < priv->multi_num; i++) {
+			dprintk("%s: set multi_secfilter[%d]\n", __FUNCTION__, i);
 			dvb_net_filter_set(dev, &priv->multi_secfilter[i],
 					   priv->multi_macs[i], mask_normal);
+		}
 		break;
-	case 2:
+	case RX_MODE_ALL_MULTI:
 		priv->multi_num=1;
-		dvb_net_filter_set(dev, &priv->multi_secfilter[0], mac_allmulti, mask_allmulti);
+		dprintk("%s: set multi_secfilter[0]\n", __FUNCTION__);
+		dvb_net_filter_set(dev, &priv->multi_secfilter[0],
+				   mac_allmulti, mask_allmulti);
 		break;
-	case 3:
+	case RX_MODE_PROMISC:
 		priv->multi_num=0;
+		dprintk("%s: set secfilter\n", __FUNCTION__);
 		dvb_net_filter_set(dev, &priv->secfilter, mac, mask_promisc);
 		break;
 	}
 	
+	dprintk("%s: start filtering\n", __FUNCTION__);
 	priv->secfeed->start_filtering(priv->secfeed);
 	return 0;
 }
@@ -255,89 +315,93 @@
 	struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;
 	int i;
 
+	dprintk("%s\n", __FUNCTION__);
         if (priv->secfeed) {
-	        if (priv->secfeed->is_filtering)
+		if (priv->secfeed->is_filtering) {
+			dprintk("%s: stop secfeed\n", __FUNCTION__);
 		        priv->secfeed->stop_filtering(priv->secfeed);
-	        if (priv->secfilter)
-		        priv->secfeed->
-			        release_filter(priv->secfeed, 
+		}
+
+		if (priv->secfilter) {
+			dprintk("%s: release secfilter\n", __FUNCTION__);
+			priv->secfeed->release_filter(priv->secfeed,
 					       priv->secfilter);
 		priv->secfilter=0;
+		}
 
 		for (i=0; i<priv->multi_num; i++) {
-			if (priv->multi_secfilter[i])
-				priv->secfeed->
-					release_filter(priv->secfeed, 
+			if (priv->multi_secfilter[i]) {
+				dprintk("%s: release multi_filter[%d]\n", __FUNCTION__, i);
+				priv->secfeed->release_filter(priv->secfeed,
 						       priv->multi_secfilter[i]);
 			priv->multi_secfilter[i]=0;
 		}
-		priv->demux->
-		        release_section_feed(priv->demux, priv->secfeed);
+		}
+
+		priv->demux->release_section_feed(priv->demux, priv->secfeed);
 		priv->secfeed=0;
-		/* fixme: is this correct? */
-		module_put(THIS_MODULE);
 	} else
 		printk("%s: no feed to stop\n", dev->name);
 }
 
-static int dvb_add_mc_filter(struct net_device *dev, struct dev_mc_list *mc)
+
+static int dvb_set_mc_filter (struct net_device *dev, struct dev_mc_list *mc)
 {
 	struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;
-	int ret;
 
-	if (priv->multi_num >= DVB_NET_MULTICAST_MAX)
+	if (priv->multi_num == DVB_NET_MULTICAST_MAX)
 		return -ENOMEM;
 
-	ret = memcmp(priv->multi_macs[priv->multi_num], mc->dmi_addr, 6);
 	memcpy(priv->multi_macs[priv->multi_num], mc->dmi_addr, 6);
 
 	priv->multi_num++;
-
-	return ret;
+	return 0;
 }
 
-static void dvb_net_set_multi(struct net_device *dev)
+
+static void tq_set_multicast_list (void *data)
 {
+	struct net_device *dev = data;
 	struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;
-	struct dev_mc_list *mc;
-	int mci;
-	int update = 0;
+
+	dvb_net_feed_stop(dev);
+
+	priv->rx_mode = RX_MODE_UNI;
 	
 	if(dev->flags & IFF_PROMISC) {
-//	printk("%s: promiscuous mode\n", dev->name);
-		if(priv->mode != 3)
-			update = 1;
-		priv->mode = 3;
-	} else if(dev->flags & IFF_ALLMULTI) {
-//	printk("%s: allmulti mode\n", dev->name);
-		if(priv->mode != 2)
-			update = 1;
-		priv->mode = 2;
-	} else if(dev->mc_count > 0) {
-//	printk("%s: set_mc_list, %d entries\n", 
-//	       dev->name, dev->mc_count);
-		if(priv->mode != 1)
-			update = 1;
-		priv->mode = 1;
+		dprintk("%s: promiscuous mode\n", dev->name);
+		priv->rx_mode = RX_MODE_PROMISC;
+	} else if ((dev->flags & IFF_ALLMULTI)) {
+		dprintk("%s: allmulti mode\n", dev->name);
+		priv->rx_mode = RX_MODE_ALL_MULTI;
+	} else if (dev->mc_count) {
+		int mci;
+		struct dev_mc_list *mc;
+
+		dprintk("%s: set_mc_list, %d entries\n",
+			dev->name, dev->mc_count);
+
+		priv->rx_mode = RX_MODE_MULTI;
 		priv->multi_num = 0;
+
 		for (mci = 0, mc=dev->mc_list; 
 		     mci < dev->mc_count;
-		     mc=mc->next, mci++)
-			if(dvb_add_mc_filter(dev, mc) != 0)
-				update = 1;
-	} else {
-		if(priv->mode != 0)
-			update = 1;
-		priv->mode = 0;
+		     mc = mc->next, mci++) {
+			dvb_set_mc_filter(dev, mc);
+		}
 	}
 
-	if(netif_running(dev) != 0 && update > 0)
-	{
-		dvb_net_feed_stop(dev);
 		dvb_net_feed_start(dev);
 	}
+
+
+static void dvb_net_set_multicast_list (struct net_device *dev)
+{
+	struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;
+	schedule_work(&priv->wq);
 }
 
+
 static int dvb_net_set_config(struct net_device *dev, struct ifmap *map)
 {
 	if (netif_running(dev))
@@ -348,11 +413,10 @@
 static int dvb_net_set_mac(struct net_device *dev, void *p)
 {
 	struct sockaddr *addr=p;
-	int update;
 
-	update = memcmp(dev->dev_addr, addr->sa_data, dev->addr_len);
 	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-	if (netif_running(dev) != 0 && update > 0) {
+
+	if (netif_running(dev)) {
 		dvb_net_feed_stop(dev);
 		dvb_net_feed_start(dev);
 	}
@@ -362,6 +427,9 @@
 
 static int dvb_net_open(struct net_device *dev)
 {
+	struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;
+
+	priv->in_use++;
 	dvb_net_feed_start(dev);
 	return 0;
 }
@@ -366,8 +434,12 @@
 	return 0;
 }
 
+
 static int dvb_net_stop(struct net_device *dev)
 {
+	struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;
+
+	priv->in_use--;
         dvb_net_feed_stop(dev);
 	return 0;
 }
@@ -386,16 +459,14 @@
 	dev->stop		= dvb_net_stop;
 	dev->hard_start_xmit	= dvb_net_tx;
 	dev->get_stats		= dvb_net_get_stats;
-	dev->set_multicast_list = dvb_net_set_multi;
+	dev->set_multicast_list = dvb_net_set_multicast_list;
 	dev->set_config         = dvb_net_set_config;
 	dev->set_mac_address    = dvb_net_set_mac;
 	dev->mtu		= 4096;
 	dev->mc_count           = 0;
-
-	dev->flags             |= IFF_NOARP;
 	dev->hard_header_cache  = NULL;
 
-	//SET_MODULE_OWNER(dev);
+	dev->flags |= IFF_NOARP;
 	
 	return 0;
 }
@@ -404,11 +476,13 @@
 {
 	int i;
 
-	for (i=0; i<dvbnet->dev_num; i++) 
+	for (i=0; i<DVB_NET_DEVICES_MAX; i++)
 		if (!dvbnet->state[i])
 			break;
-	if (i==dvbnet->dev_num)
+
+	if (i == DVB_NET_DEVICES_MAX)
 		return -1;
+
 	dvbnet->state[i]=1;
 	return i;
 }
@@ -414,8 +488,7 @@
 }
 
 
-int 
-dvb_net_add_if(struct dvb_net *dvbnet, u16 pid)
+static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid)
 {
         struct net_device *net;
 	struct dmx_demux *demux;
@@ -423,8 +496,7 @@
 	int result;
 	int if_num;
  
-	if_num=get_if(dvbnet);
-	if (if_num<0)
+	if ((if_num = get_if(dvbnet)) < 0)
 		return -EINVAL;
 
 	net=&dvbnet->device[if_num];
@@ -435,47 +507,52 @@
 	net->dma       = 0;
 	net->mem_start = 0;
         memcpy(net->name, "dvb0_0", 7);
-        net->name[3]=dvbnet->card_num+0x30;
-        net->name[5]=if_num+0x30;
+	net->name[3]   = dvbnet->dvbdev->adapter->num + '0';
+	net->name[5]   = if_num + '0';
+	net->addr_len  = 6;
+	memcpy(net->dev_addr, dvbnet->dvbdev->adapter->proposed_mac, 6);
         net->next      = NULL;
         net->init      = dvb_net_init_dev;
-        net->priv      = kmalloc(sizeof(struct dvb_net_priv), GFP_KERNEL);
-	if (net->priv == NULL)
+
+	if (!(net->priv = kmalloc(sizeof(struct dvb_net_priv), GFP_KERNEL)))
 			return -ENOMEM;
 
 	priv = net->priv;
 	memset(priv, 0, sizeof(struct dvb_net_priv));
         priv->demux = demux;
         priv->pid = pid;
-	priv->mode = 0;
+	priv->rx_mode = RX_MODE_UNI;
+
+	INIT_WORK(&priv->wq, tq_set_multicast_list, net);
 
         net->base_addr = pid;
                 
 	if ((result = register_netdev(net)) < 0) {
 		return result;
 	}
-	/* fixme: is this correct? */
-	try_module_get(THIS_MODULE);
 
         return if_num;
 }
 
-int 
-dvb_net_remove_if(struct dvb_net *dvbnet, int num)
+
+static int dvb_net_remove_if(struct dvb_net *dvbnet, int num)
 {
+	struct dvb_net_priv *priv = dvbnet->device[num].priv;
+
 	if (!dvbnet->state[num])
 		return -EINVAL;
+	if (priv->in_use)
+		return -EBUSY;
+
 	dvb_net_stop(&dvbnet->device[num]);
-        kfree(dvbnet->device[num].priv);
+	kfree(priv);
         unregister_netdev(&dvbnet->device[num]);
 	dvbnet->state[num]=0;
-	/* fixme: is this correct? */
-	module_put(THIS_MODULE);
-
 	return 0;
 }
 
-int dvb_net_do_ioctl(struct inode *inode, struct file *file, 
+
+static int dvb_net_do_ioctl(struct inode *inode, struct file *file,
 		  unsigned int cmd, void *parg)
 {
 	struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
@@ -490,6 +567,8 @@
 		struct dvb_net_if *dvbnetif=(struct dvb_net_if *)parg;
 		int result;
 		
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
 		result=dvb_net_add_if(dvbnet, dvbnetif->pid);
 		if (result<0)
 			return result;
@@ -502,7 +581,7 @@
 		struct dvb_net_priv *priv_data;
 		struct dvb_net_if *dvbnetif=(struct dvb_net_if *)parg;
 
-		if (dvbnetif->if_num >= dvbnet->dev_num ||
+		if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX ||
 		    !dvbnet->state[dvbnetif->if_num])
 			return -EFAULT;
 
@@ -512,7 +591,9 @@
 		break;
 	}
 	case NET_REMOVE_IF:
-		return dvb_net_remove_if(dvbnet, (long) parg);
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		return dvb_net_remove_if(dvbnet, (int) parg);
 	default:
 		return -EINVAL;
 	}
@@ -542,28 +627,29 @@
         .fops = &dvb_net_fops,
 };
 
-void
-dvb_net_release(struct dvb_net *dvbnet)
+
+void dvb_net_release (struct dvb_net *dvbnet)
 {
 	int i;
 
 	dvb_unregister_device(dvbnet->dvbdev);
-	for (i=0; i<dvbnet->dev_num; i++) {
+
+	for (i=0; i<DVB_NET_DEVICES_MAX; i++) {
 		if (!dvbnet->state[i])
 			continue;
 		dvb_net_remove_if(dvbnet, i);
 	}
 }
 
-int
-dvb_net_init(struct dvb_adapter *adap, struct dvb_net *dvbnet, struct dmx_demux *dmx)
+
+int dvb_net_init (struct dvb_adapter *adap, struct dvb_net *dvbnet,
+		  struct dmx_demux *dmx)
 {
 	int i;
 		
 	dvbnet->demux = dmx;
-	dvbnet->dev_num = DVB_NET_DEVICES_MAX;
 
-	for (i=0; i<dvbnet->dev_num; i++) 
+	for (i=0; i<DVB_NET_DEVICES_MAX; i++)
 		dvbnet->state[i] = 0;
 
 	dvb_register_device (adap, &dvbnet->dvbdev, &dvbdev_net,
drivers/media/dvb/dvb-core/dvb_net.h +0 -2
diff -uNrwB --new-file linux-2.5.73.bk/drivers/media/dvb/dvb-core/dvb_net.h linux-2.5.73.work/drivers/media/dvb/dvb-core/dvb_net.h
@@ -35,8 +35,6 @@
 
 struct dvb_net {
 	struct dvb_device *dvbdev;
-	int card_num;
-	int dev_num;
 	struct net_device device[DVB_NET_DEVICES_MAX];
 	int state[DVB_NET_DEVICES_MAX];
 	struct dmx_demux *demux;
#3 lore raw

PATCH 4/7 Update various dvb frontend drivers

- grundig_29504-401.c: fix charge pump and band switch setting bug, catched by Robert Schlabbach <[email protected]>
- grundig_29504-401.c: pass apply_frontend_param() return value to upper layers
- grundig_29504-401.c: try to make a more specific detection mechanism
- grundig_29504-491.c:remove bogus out-of-range check, FEC table index is limited to 0...7 due to &= ~0x03 anyway...
- nxt6000.c: Patch by Paul Andreassen: Add Support for Comtech DVBT-6k07 (PLL IC: SP5730)
- ves1820.c: use Robert Schlabbach's suggestions for CLKCONF (0x03) and CARCONF (0x04)
- alps_bsrv2.c: don't enable voltage on init + inversion bugfix

drivers/media/dvb/dvb-core/dvb_frontend.c +6 -0
diff -uNrwB --new-file linux-2.5.73.bk/drivers/media/dvb/dvb-core/dvb_frontend.c linux-2.5.73.work/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -263,8 +263,14 @@
                 if (flags & O_NONBLOCK)
                         return -EWOULDBLOCK;
 
+		up(&fe->sem);
+
                 ret = wait_event_interruptible (events->wait_queue,
                                                 events->eventw != events->eventr);
+
+        	if (down_interruptible (&fe->sem))
+			return -ERESTARTSYS;
+
                 if (ret < 0)
                         return ret;
         }
drivers/media/dvb/frontends/alps_bsrv2.c +18 -4
diff -uNrwB --new-file linux-2.5.73.bk/drivers/media/dvb/frontends/alps_bsrv2.c linux-2.5.73.work/drivers/media/dvb/frontends/alps_bsrv2.c
@@ -55,7 +55,7 @@
         0x01, 0xA4, 0x35, 0x81, 0x2A, 0x0d, 0x55, 0xC4,
         0x09, 0x69, 0x00, 0x86, 0x4c, 0x28, 0x7F, 0x00,
         0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	
-        0x80, 0x00, 0x31, 0xb0, 0x14, 0x00, 0xDC, 0x20,
+        0x80, 0x00, 0x31, 0xb0, 0x14, 0x00, 0xDC, 0x00,
         0x81, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
         0x00, 0x55, 0x00, 0x00, 0x7f, 0x00
@@ -158,6 +158,11 @@
 {
 	u8 val;
 
+	/*
+	 * inversion on/off are interchanged because i and q seem to
+	 * be swapped on the hardware
+	 */
+
 	switch (inversion) {
 	case INVERSION_OFF:
 		val = 0xc0;
@@ -166,13 +171,16 @@
 		val = 0x80;
 		break;
 	case INVERSION_AUTO:
-		val = 0x40;
+		val = 0x00;
 		break;
 	default:
 		return -EINVAL;
 	}
 
-	return ves1893_writereg (i2c, 0x0c, (init_1893_tab[0x0c] & 0x3f) | val);
+	/* needs to be saved for FE_GET_FRONTEND */
+	init_1893_tab[0x0c] = (init_1893_tab[0x0c] & 0x3f) | val;
+
+	return ves1893_writereg (i2c, 0x0c, init_1893_tab[0x0c]);
 }
 
 
@@ -383,8 +391,14 @@
 		afc = (afc * (int)(p->u.qpsk.symbol_rate/1000/8))/16;
 
 		p->frequency -= afc;
+
+		/*
+		 * inversion indicator is only valid
+		 * if auto inversion was used
+		 */
+		if (!(init_1893_tab[0x0c] & 0x80))
 		p->inversion = (ves1893_readreg (i2c, 0x0f) & 2) ? 
-					INVERSION_ON : INVERSION_OFF;
+					INVERSION_OFF : INVERSION_ON;
 		p->u.qpsk.fec_inner = ves1893_get_fec (i2c);
 	/*  XXX FIXME: timing offset !! */
 		break;
drivers/media/dvb/frontends/grundig_29504-401.c +57 -21

131 lines not on this page · raw message

drivers/media/dvb/frontends/grundig_29504-491.c +1 -4
diff -uNrwB --new-file linux-2.5.73.bk/drivers/media/dvb/frontends/grundig_29504-491.c linux-2.5.73.work/drivers/media/dvb/frontends/grundig_29504-491.c
@@ -179,10 +179,7 @@
 	static fe_code_rate_t fec_tab [] = { FEC_8_9, FEC_1_2, FEC_2_3, FEC_3_4,
 				       FEC_4_5, FEC_5_6, FEC_6_7, FEC_7_8 };
 
-	index = tda8083_readreg (i2c, 0x0e) & 0x3;
-
-	if (index > 7)
-		return FEC_NONE;
+	index = tda8083_readreg(i2c, 0x0e) & 0x07;
 
 	return fec_tab [index];
 }
drivers/media/dvb/frontends/nxt6000.c +51 -0

83 lines not on this page · raw message

drivers/media/dvb/frontends/ves1820.c +5 -5
diff -uNrwB --new-file linux-2.5.73.bk/drivers/media/dvb/frontends/ves1820.c linux-2.5.73.work/drivers/media/dvb/frontends/ves1820.c
@@ -95,7 +95,7 @@
 
 static u8 ves1820_inittab [] =
 {
-	0x69, 0x6A, 0x9B, 0x0A, 0x52, 0x46, 0x26, 0x1A,
+	0x69, 0x6A, 0x9B, 0x12, 0x12, 0x46, 0x26, 0x1A,
 	0x43, 0x6A, 0xAA, 0xAA, 0x1E, 0x85, 0x43, 0x28,
 	0xE0, 0x00, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00,
 	0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
@@ -109,7 +109,7 @@
 {
 	u8 addr = GET_DEMOD_ADDR(fe->data);
         u8 buf[] = { 0x00, reg, data };
-	struct i2c_msg msg = { addr: addr, .flags = 0, .buf = buf, .len = 3 };
+	struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 };
 	struct dvb_i2c_bus *i2c = fe->i2c;
         int ret;
 
@@ -130,8 +130,8 @@
 	u8 b0 [] = { 0x00, reg };
 	u8 b1 [] = { 0 };
 	u8 addr = GET_DEMOD_ADDR(fe->data);
-	struct i2c_msg msg [] = { { addr: addr, .flags = 0, .buf = b0, .len = 2 },
-	                   { addr: addr, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
+	struct i2c_msg msg [] = { { .addr = addr, .flags = 0, .buf = b0, .len = 2 },
+	                   { .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
 	struct dvb_i2c_bus *i2c = fe->i2c;
 	int ret;
 
@@ -147,7 +147,7 @@
 static int tuner_write (struct dvb_i2c_bus *i2c, u8 addr, u8 data [4])
 {
         int ret;
-        struct i2c_msg msg = { addr: addr, .flags = 0, .buf = data, .len = 4 };
+        struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = data, .len = 4 };
 
         ret = i2c->xfer (i2c, &msg, 1);
 
#4 lore raw

PATCH 5/7 Add two new dvb frontend drivers

- Zarlink MT312 satellite channel decoder driver contributed by Andreas Oberritter
- tda10045 DVB-T driver contributed by Andrew de Quincy and Robert Schlalach

drivers/media/dvb/frontends/Kconfig +19 -0
diff -uNrwB --new-file linux-2.5.73.bk/drivers/media/dvb/frontends/Kconfig linux-2.5.73.work/drivers/media/dvb/frontends/Kconfig
@@ -93,6 +93,16 @@
 	  DVB adapter simply enable all supported frontends, the 
 	  right one will get autodetected.
 
+config DVB_MT312
+	tristate "Zarlink MT312 Satellite Channel Decoder (QPSK)"
+	depends on DVB_CORE
+	help
+	  A DVB-S tuner module. Say Y when you want to support this frontend.
+
+	  If you don't know what tuner module is soldered on your 
+	  DVB adapter simply enable all supported frontends, the 
+	  right one will get autodetected.
+
 config DVB_VES1820
 	tristate "Frontends with external VES1820 demodulator (QAM)"
 	depends on DVB_CORE
@@ -105,3 +115,12 @@
 	  DVB adapter simply enable all supported frontends, the 
 	  right one will get autodetected.
 
+config DVB_TDA10045H
+	tristate "Frontends with external TDA10045H demodulator (OFDM)"
+	depends on DVB_CORE
+	help
+	  A DVB-T tuner module. Say Y when you want to support this frontend.
+
+	  If you don't know what tuner module is soldered on your 
+	  DVB adapter simply enable all supported frontends, the 
+	  right one will get autodetected.
drivers/media/dvb/frontends/Makefile +2 -0
diff -uNrwB --new-file linux-2.5.73.bk/drivers/media/dvb/frontends/Makefile linux-2.5.73.work/drivers/media/dvb/frontends/Makefile
@@ -12,4 +12,6 @@
 obj-$(CONFIG_DVB_CX24110) += cx24110.o
 obj-$(CONFIG_DVB_GRUNDIG_29504_491) += grundig_29504-491.o
 obj-$(CONFIG_DVB_GRUNDIG_29504_401) += grundig_29504-401.o
+obj-$(CONFIG_DVB_MT312) += mt312.o
 obj-$(CONFIG_DVB_VES1820) += ves1820.o
+obj-$(CONFIG_DVB_TDA10045H) += tda10045h.o
drivers/media/dvb/frontends/mt312.c +714 -0

714 lines not on this page · raw message

drivers/media/dvb/frontends/mt312.h +162 -0

162 lines not on this page · raw message

drivers/media/dvb/frontends/tda10045h.c +1231 -0

1,231 lines not on this page · raw message

#5 lore raw

PATCH 6/7 Update dvb budget driver

- follow changes in dvb_net, use new eeprom parse code to properly detect the mac
- add new subvendor/subystem id pair

drivers/media/dvb/ttpci/budget-core.c +4 -2
diff -uNrwB --new-file linux-2.5.73.bk/drivers/media/dvb/ttpci/budget-core.c linux-2.5.73.work/drivers/media/dvb/ttpci/budget-core.c
@@ -1,4 +1,5 @@
 #include "budget.h"
+#include "ttpci-eeprom.h"
 
 int budget_debug = 0;
 
@@ -165,7 +166,6 @@
         if (ret < 0)
                 return ret;
 
-        budget->dvb_net.card_num = budget->dvb_adapter->num;
         dvb_net_init(budget->dvb_adapter, &budget->dvb_net, &dvbdemux->dmx);
 
 	return 0;
@@ -222,7 +222,7 @@
            get recognized before the main driver is loaded */
         saa7146_write(dev, GPIO_CTRL, 0x500000);
 	
-	saa7146_i2c_adapter_prepare(dev, NULL, SAA7146_I2C_BUS_BIT_RATE_3200);
+	saa7146_i2c_adapter_prepare(dev, NULL, SAA7146_I2C_BUS_BIT_RATE_120);
 
 	budget->i2c_bus = dvb_register_i2c_bus (master_xfer, dev,
 						budget->dvb_adapter, 0);
@@ -232,6 +232,8 @@
 		return -ENOMEM;
 	}
 
+	ttpci_eeprom_parse_mac(budget->i2c_bus);
+
 	if( NULL == (budget->grabbing = saa7146_vmalloc_build_pgtable(dev->pci,length,&budget->pt))) {
 		ret = -ENOMEM;
 		goto err;
drivers/media/dvb/ttpci/budget.c +2 -0
diff -uNrwB --new-file linux-2.5.73.bk/drivers/media/dvb/ttpci/budget.c linux-2.5.73.work/drivers/media/dvb/ttpci/budget.c
@@ -192,6 +192,7 @@
 MAKE_BUDGET_INFO(ttbs,	"TT-Budget/WinTV-NOVA-S  PCI",	BUDGET_TT);
 MAKE_BUDGET_INFO(ttbc,	"TT-Budget/WinTV-NOVA-C  PCI",	BUDGET_TT);
 MAKE_BUDGET_INFO(ttbt,	"TT-Budget/WinTV-NOVA-T  PCI",	BUDGET_TT);
+MAKE_BUDGET_INFO(ttbt2,	"TT-Budget/WinTV-NOVA-T  PCI",	BUDGET_TT);
 MAKE_BUDGET_INFO(satel,	"SATELCO Multimedia PCI",	BUDGET_TT_HW_DISEQC);
 /* Uncomment for Budget Patch */
 /*MAKE_BUDGET_INFO(fs_1_3,"Siemens/Technotrend/Hauppauge PCI rev1.3+Budget_Patch", BUDGET_PATCH);*/
@@ -202,6 +203,7 @@
 	MAKE_EXTENSION_PCI(ttbs,  0x13c2, 0x1003),
 	MAKE_EXTENSION_PCI(ttbc,  0x13c2, 0x1004),
 	MAKE_EXTENSION_PCI(ttbt,  0x13c2, 0x1005),
+	MAKE_EXTENSION_PCI(ttbt2,  0x13c2, 0x1011),	
 	MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013),
 	{
 		.vendor    = 0,
#6 lore raw

PATCH 7/7 Update dvb av7110 driver

- Fix to 'Sharing SDRAM between TT re-insertion and OSD...' - OSD didn't get the maximum available memory in one piece; needs new firmware version 0x2616
- Improved performance when setting palette with full 256 color OSD
- read MAC from EEPROM if available, contributed by Michael Glaum <[email protected]>
- add some MODULE_PARM_DESC for modinfo
- add support for the "analog module" available for DVB-C cards: the saa7113 is initialized and some more v4l2 ioctls are available. you can use "xawtv" now to switch between "dvb" and "analog" input. when you are one the "analog" input, you can tune in analog channels.

drivers/media/dvb/ttpci/av7110.c +328 -22
diff -uNrwB --new-file linux-2.5.73.bk/drivers/media/dvb/ttpci/av7110.c linux-2.5.73.work/drivers/media/dvb/ttpci/av7110.c
@@ -86,6 +86,7 @@
 	#define DEB_EE(x)
 #endif
 
+#include "ttpci-eeprom.h"
 #include "av7110.h"
 #include "av7110_ipack.h"
 
@@ -110,7 +112,8 @@
 
 int av7110_num = 0;
 
-#define FW_CI_LL_SUPPORT(arm_app) (((arm_app) >> 16) & 0x8000)
+#define FW_CI_LL_SUPPORT(arm_app) ((arm_app) & 0x80000000)
+#define FW_VERSION(arm_app)       ((arm_app) & 0x0000FFFF)
 
 /****************************************************************************
  * DEBI functions
@@ -1089,7 +1092,7 @@
         u32 stat;
 #endif
 
-	DEB_EE(("av7110: %p\n",av7110));
+//	DEB_EE(("av7110: %p\n",av7110));
 
 	if (!av7110->arm_ready) {
 		DEB_D(("arm not ready.\n"));
@@ -1166,7 +1169,7 @@
 {
         int ret;
         
- 	DEB_EE(("av7110: %p\n",av7110));
+// 	DEB_EE(("av7110: %p\n",av7110));
 
         if (!av7110->arm_ready) {
 		DEB_D(("arm not ready.\n"));
@@ -1190,7 +1193,7 @@
         u16 buf[num+2];
         int i, ret;
 
- 	DEB_EE(("av7110: %p\n",av7110));
+// 	DEB_EE(("av7110: %p\n",av7110));
 
         buf[0]=(( type << 8 ) | com);
         buf[1]=num;
@@ -1332,7 +1335,7 @@
 
 static inline int SendDAC(struct av7110 *av7110, u8 addr, u8 data)
 {
- 	DEB_EE(("av7110: %p\n",av7110));
+// 	DEB_EE(("av7110: %p\n",av7110));
 
         return outcom(av7110, COMTYPE_AUDIODAC, AudioDAC, 2, addr, data);
 }
@@ -1659,6 +1662,24 @@
                   color, ((blend>>4)&0x0f));
 }
 
+static int OSDSetPalette(struct av7110 *av7110, u32 *colors, u8 first, u8 last)
+{
+       int i;
+       int length = last - first + 1;
+
+       if (length * 4 > DATA_BUFF3_SIZE)
+               return -1;
+
+       for (i=0; i<length; i++) {
+               u32 blend = (colors[i] & 0xF0000000) >> 4;
+               u32 yuv = blend ? RGB2YUV(colors[i] & 0xFF, (colors[i] >> 8) & 0xFF, (colors[i] >> 16) & 0xFF) | blend : 0;
+               yuv = ((yuv & 0xFFFF0000) >> 16) | ((yuv & 0x0000FFFF) << 16); // TODO kls2003-06-15: not sure if this is endian-proof
+               wdebi(av7110, DEBINOSWAP, DATA_BUFF3_BASE + i*4, yuv, 4);
+       }
+       return outcom(av7110, COMTYPE_OSD, Set_Palette, 4,
+               av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]], first, last);
+}
+
 static int OSDSetBlock(struct av7110 *av7110, int x0, int y0, int x1, int y1, int inc, u8 *data)
 {
         uint w, h, bpp, bpl, size, lpb, bnum, brest;
@@ -1721,6 +1742,9 @@
                 return 0;
         case OSD_SetPalette:
         {      
+                if (FW_VERSION(av7110->arm_app) >= 0x2618)
+                        OSDSetPalette(av7110, (u32 *)dc->data, dc->color, dc->x0);
+                else {
                 int i, len=dc->x0-dc->color+1;
                 u8 *colors=(u8 *)dc->data;
 
@@ -1728,6 +1752,7 @@
                         OSDSetColor(av7110, dc->color+i,
                                     colors[i*4]  , colors[i*4+1],
                                     colors[i*4+2], colors[i*4+3]);
+                }
                 return 0;
         }
         case OSD_SetTrans: 
@@ -2087,28 +2112,28 @@
 
 static inline void TestMode(struct av7110 *av7110, int mode)
 {
- 	DEB_EE(("av7110: %p\n",av7110));
+//	DEB_EE(("av7110: %p\n",av7110));
         outcom(av7110, COMTYPE_ENCODER, SetTestMode, 1, mode);
 }
 
 static inline void VidMode(struct av7110 *av7110, int mode)
 {
- 	DEB_EE(("av7110: %p\n",av7110));
+// 	DEB_EE(("av7110: %p\n",av7110));
         outcom(av7110, COMTYPE_ENCODER, SetVidMode, 1, mode);
 }
            
 
-static inline int vidcom(struct av7110 *av7110, u32 com, u32 arg)
+static int inline vidcom(struct av7110 *av7110, u32 com, u32 arg)
 {
- 	DEB_EE(("av7110: %p\n",av7110));
+// 	DEB_EE(("av7110: %p\n",av7110));
         return outcom(av7110, 0x80, 0x02, 4, 
                       (com>>16), (com&0xffff), 
                       (arg>>16), (arg&0xffff));
 }
 
-static inline int audcom(struct av7110 *av7110, u32 com)
+static int inline audcom(struct av7110 *av7110, u32 com)
 {
-	DEB_EE(("av7110: %p\n",av7110));
+//	DEB_EE(("av7110: %p\n",av7110));
 	return outcom(av7110, 0x80, 0x03, 4, 
                       (com>>16), (com&0xffff));
 }
@@ -2583,38 +2608,274 @@
  * V4L SECTION
  ****************************************************************************/
 
-int av7110_ioctl(struct saa7146_dev *dev, unsigned int cmd, void *arg) 
+static struct v4l2_input inputs[2] = {
+	{ 0,	"DVB",		V4L2_INPUT_TYPE_CAMERA,	1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, 
+	{ 1,	"ANALOG",	V4L2_INPUT_TYPE_TUNER,	2, 1, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
+};
+
+/* taken from ves1820.c */
+static int ves1820_writereg(struct saa7146_dev *dev, u8 reg, u8 data)
 {
+	u8 addr = 0x09;
+        u8 buf[] = { 0x00, reg, data };
+	struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 };
+
+  	DEB_EE(("av7710: dev: %p\n",dev));
+
+	if( 1 != saa7146_i2c_transfer(dev, &msg, 1, 1)) {
+		return -1;
+	}
+	return 0;
+}
+
+static int tuner_write(struct saa7146_dev *dev, u8 addr, u8 data [4])
+{
+        struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = data, .len = 4 };
+
+  	DEB_EE(("av7710: dev: %p\n",dev));
+
+	if( 1 != saa7146_i2c_transfer(dev, &msg, 1, 1)) {
+		return -1;
+	}
+	return 0;
+}
+
+
+/**
+ *   set up the downconverter frequency divisor for a
+ *   reference clock comparision frequency of 62.5 kHz.
+ */
+static int tuner_set_tv_freq (struct saa7146_dev *dev, u32 freq)
+{
+        u32 div;
+	u8 config;
+        u8 buf [4];
+
+ 	DEB_EE(("av7710: freq: 0x%08x\n",freq));
+
+	/* magic number: 56. tuning with the frequency given by v4l2
+	   is always off by 56*62.5 kHz...*/
+	div = freq + 56;
+
+	buf[0] = (div >> 8) & 0x7f;
+	buf[1] = div & 0xff;
+	buf[2] = 0x8e;
+
+	if (freq < 16*168.25 ) 
+		config = 0xa0;
+	else if (freq < 16*447.25) 
+		config = 0x90;
+	else
+		config = 0x30;
+	config &= ~0x02;
+
+	buf[3] = config;
+
+        return tuner_write (dev, 0x61, buf);
+}
+
+static struct saa7146_standard analog_standard[];
+static struct saa7146_standard dvb_standard[];
+static struct saa7146_standard standard[];
+
+int av7110_dvb_c_switch(struct saa7146_fh *fh)
+{
+	struct saa7146_dev *dev = fh->dev;
+	struct saa7146_vv *vv = dev->vv_data;
+	struct av7110 *av7110 = (struct av7110*)dev->ext_priv;
+	u16 buf[3] = { ((COMTYPE_AUDIODAC << 8) + ADSwitch), 1, 1 };
+
+	u8 band = 0;
+	int source, sync;
+	struct saa7146_fh *ov_fh = NULL;
+	int restart_overlay = 0;
+
+	DEB_EE(("av7110: %p\n",av7110));
+
+	if( vv->ov_data != NULL ) {
+		ov_fh = vv->ov_data->fh;
+		saa7146_stop_preview(ov_fh);
+		restart_overlay = 1;
+	}
+
+	if( 0 != av7110->current_input ) {
+		buf[2] = 0;
+		band = 0x68; /* analog band */
+		source = SAA7146_HPS_SOURCE_PORT_B;
+		sync = SAA7146_HPS_SYNC_PORT_B;
+		memcpy(standard,analog_standard,sizeof(struct saa7146_standard)*2);
+	} else {
+		buf[2] = 1;
+		band = 0x28; /* digital band */	
+		source = SAA7146_HPS_SOURCE_PORT_A;
+		sync = SAA7146_HPS_SYNC_PORT_A;
+		memcpy(standard,dvb_standard,sizeof(struct saa7146_standard)*2);
+	}
+
+	/* hmm, this does not do anything!? */
+	if (OutCommand(av7110, buf, 3)) {
+		printk("ADSwitch error\n");
+	}
+
+	if( 0 != ves1820_writereg(dev, 0x0f, band )) {
+		printk("setting band in demodulator failed.\n");
+	}
+	saa7146_set_hps_source_and_sync(dev, source, sync);
+
+	/* restart overlay if it was active before */
+	if( 0 != restart_overlay ) {
+		saa7146_start_preview(ov_fh);
+	}
+
+	return 0;
+}
+
+int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) 
+{
+	struct saa7146_dev *dev = fh->dev;
+	struct av7110 *av7110 = (struct av7110*)dev->ext_priv;
  	DEB_EE(("saa7146_dev: %p\n",dev));
 
 	switch(cmd) {
+	case VIDIOC_G_TUNER:
+	{
+		struct v4l2_tuner *t = arg;
+
+		DEB_EE(("VIDIOC_G_TUNER: %d\n", t->index));
+
+		if( 0 == av7110->has_analog_tuner || av7110->current_input != 1 ) {
+			return -EINVAL;
+		}
+
+		memset(t,0,sizeof(*t));
+		strcpy(t->name, "Television");
+
+		t->type = V4L2_TUNER_ANALOG_TV;
+		t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
+		t->rangelow = 772;	/* 48.25 MHZ / 62.5 kHz = 772, see fi1216mk2-specs, page 2 */
+		t->rangehigh = 13684;	/* 855.25 MHz / 62.5 kHz = 13684 */
+		/* FIXME: add the real signal strength here */
+		t->signal = 0xffff;
+		t->afc = 0;		
+		/* fixme: real autodetection here */
+		t->rxsubchans 	= V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO;
+
+		return 0;
+	}
+	case VIDIOC_S_TUNER:
+	{
+		struct v4l2_tuner *t = arg;
+		
+		DEB_EE(("VIDIOC_S_TUNER: %d\n", t->index));
+
+		if( 0 == av7110->has_analog_tuner || av7110->current_input != 1 ) {
+			return -EINVAL;
+		}
+
+
+		switch(t->audmode) {
+			case V4L2_TUNER_MODE_STEREO: {
+				DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_STEREO\n"));
+				break;
+			}
+			case V4L2_TUNER_MODE_LANG1: {
+				DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1\n"));
+				break;
+			}
+			case V4L2_TUNER_MODE_LANG2: {
+				DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG2\n"));
+				break;
+			}
+			default: { /* case V4L2_TUNER_MODE_MONO: {*/
+				DEB_D(("VIDIOC_S_TUNER: TDA9840_SET_MONO\n"));
+				break;
+			}
+		}
+
+		return 0;
+	}
+	case VIDIOC_G_FREQUENCY:
+	{
+		struct v4l2_frequency *f = arg;
+
+		DEB_EE(("VIDIOC_G_FREQ: freq:0x%08x.\n", f->frequency));
+
+		if( 0 == av7110->has_analog_tuner || av7110->current_input != 1 ) {
+			return -EINVAL;
+		}
+
+		memset(f,0,sizeof(*f));
+		f->type = V4L2_TUNER_ANALOG_TV;
+		f->frequency =  av7110->current_freq;
+
+		return 0;
+	}
+	case VIDIOC_S_FREQUENCY:
+	{
+		struct v4l2_frequency *f = arg;
+
+		DEB_EE(("VIDIOC_S_FREQUENCY: freq:0x%08x.\n",f->frequency));
+
+		if( 0 == av7110->has_analog_tuner || av7110->current_input != 1 ) {
+			return -EINVAL;
+		}
+
+		if (V4L2_TUNER_ANALOG_TV != f->type)
+			return -EINVAL;
+
+		/* tune in desired frequency */			
+		tuner_set_tv_freq(dev, f->frequency);
+		av7110->current_freq = f->frequency;
+
+		return 0;
+	}
 	case VIDIOC_ENUMINPUT:
 	{
 		struct v4l2_input *i = arg;
 		
+		DEB_EE(("VIDIOC_ENUMINPUT: %d\n", i->index));
+
+		if( 0 != av7110->has_analog_tuner ) {
+			if( i->index < 0 || i->index >= 2) {
+				return -EINVAL;
+			}
+		} else {
 		if( i->index != 0 ) {
 			return -EINVAL;
 		}
+		}		
 
-		memset(i,0,sizeof(*i));
-		i->index = 0;
-		strcpy(i->name, "DVB");
-		i->type = V4L2_INPUT_TYPE_CAMERA;
-		i->audioset = 1;
+		memcpy(i, &inputs[i->index], sizeof(struct v4l2_input));
 		
 		return 0;
 	}
 	case VIDIOC_G_INPUT:
 	{
 		int *input = (int *)arg;
-		*input = 0;
+		*input = av7110->current_input;
+		DEB_EE(("VIDIOC_G_INPUT: %d\n", *input));
 		return 0;		
 	}	
 	case VIDIOC_S_INPUT:
 	{
+		int input = *(int *)arg;
+
+		DEB_EE(("VIDIOC_S_INPUT: %d\n", input));
+
+		if( 0 == av7110->has_analog_tuner ) {
 		return 0;		
 	}	
+		
+		if( input < 0 || input >= 2) {
+			return -EINVAL;
+		}
+		
+		/* fixme: switch inputs here */
+		av7110->current_input = input;
+		return av7110_dvb_c_switch(fh);
+	}	
 	default:
+		printk("no such ioctl\n");
 		return -ENOIOCTLCMD;
 	}
 	return 0;
@@ -4006,7 +4267,6 @@
 #endif
 //        }
         
-        av7110->dvb_net.card_num=av7110->dvb_adapter->num;
         dvb_net_init(av7110->dvb_adapter, &av7110->dvb_net, &dvbdemux->dmx);
 
 	return 0;
@@ -4061,6 +4321,10 @@
 	{ VIDIOC_ENUMINPUT, 	SAA7146_EXCLUSIVE },
 	{ VIDIOC_G_INPUT,	SAA7146_EXCLUSIVE },
 	{ VIDIOC_S_INPUT,	SAA7146_EXCLUSIVE },
+	{ VIDIOC_G_FREQUENCY,	SAA7146_EXCLUSIVE },
+	{ VIDIOC_S_FREQUENCY, 	SAA7146_EXCLUSIVE },
+	{ VIDIOC_G_TUNER, 	SAA7146_EXCLUSIVE },
+	{ VIDIOC_S_TUNER, 	SAA7146_EXCLUSIVE },
 	{ 0, 0 }
 };
 
@@ -4114,6 +4378,8 @@
 		return -ENOMEM;
 	}
 
+	ttpci_eeprom_parse_mac(av7110->i2c_bus);
+
 	saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
 	saa7146_write(dev, BCS_CTRL, 0x80400040);
 
@@ -4186,9 +4452,9 @@
 	bootarm(av7110);
 	firmversion(av7110);
 
-	if ((av7110->arm_app&0xffff)<0x2501)
+	if (FW_VERSION(av7110->arm_app)<0x2501)
 		printk ("av7110: Warning, firmware version 0x%04x is too old. "
-			"System might be unstable!\n", av7110->arm_app&0xffff);
+			"System might be unstable!\n", FW_VERSION(av7110->arm_app));
 
 	kernel_thread(arm_thread, (void *) av7110, 0);
 
@@ -4199,6 +4465,8 @@
 	VidMode(av7110, vidmode);
 
 	/* remaining inits according to card and frontend type */
+	av7110->has_analog_tuner = 0;
+	av7110->current_input = 0;
 	if (i2c_writereg(av7110, 0x20, 0x00, 0x00)==1) {
 		printk ("av7110(%d): Crystal audio DAC detected\n",
 			av7110->dvb_adapter->num);
@@ -4225,6 +4493,31 @@
 			msp_writereg(av7110, 0x12, 0x000a, 0x0220); // SCART 1 source
 			msp_writereg(av7110, 0x12, 0x0007, 0x7f00); // SCART 1 volume
 			msp_writereg(av7110, 0x12, 0x000d, 0x4800); // prescale SCART
+		
+		if (i2c_writereg(av7110, 0x48, 0x01, 0x00)!=1) {
+			INFO(("saa7113 not accessible.\n"));
+		} else {
+			av7110->has_analog_tuner = 1;
+			/* init the saa7113 */
+			i2c_writereg(av7110, 0x48, 0x02, 0xd0); i2c_writereg(av7110, 0x48, 0x03, 0x23); i2c_writereg(av7110, 0x48, 0x04, 0x00);
+			i2c_writereg(av7110, 0x48, 0x05, 0x00); i2c_writereg(av7110, 0x48, 0x06, 0xe9); i2c_writereg(av7110, 0x48, 0x07, 0x0d);
+			i2c_writereg(av7110, 0x48, 0x08, 0x98); i2c_writereg(av7110, 0x48, 0x09, 0x02); i2c_writereg(av7110, 0x48, 0x0a, 0x80);
+			i2c_writereg(av7110, 0x48, 0x0b, 0x40); i2c_writereg(av7110, 0x48, 0x0c, 0x40); i2c_writereg(av7110, 0x48, 0x0d, 0x00);
+			i2c_writereg(av7110, 0x48, 0x0e, 0x01);	i2c_writereg(av7110, 0x48, 0x0f, 0x7c); i2c_writereg(av7110, 0x48, 0x10, 0x48);
+			i2c_writereg(av7110, 0x48, 0x11, 0x0c);	i2c_writereg(av7110, 0x48, 0x12, 0x8b);	i2c_writereg(av7110, 0x48, 0x13, 0x10);
+			i2c_writereg(av7110, 0x48, 0x14, 0x00);	i2c_writereg(av7110, 0x48, 0x15, 0x00);	i2c_writereg(av7110, 0x48, 0x16, 0x00);
+			i2c_writereg(av7110, 0x48, 0x17, 0x00);	i2c_writereg(av7110, 0x48, 0x18, 0x00);	i2c_writereg(av7110, 0x48, 0x19, 0x00);
+			i2c_writereg(av7110, 0x48, 0x1a, 0x00);	i2c_writereg(av7110, 0x48, 0x1b, 0x00);	i2c_writereg(av7110, 0x48, 0x1c, 0x00);
+			i2c_writereg(av7110, 0x48, 0x1d, 0x00);	i2c_writereg(av7110, 0x48, 0x1e, 0x00);
+		}	
+
+		memcpy(standard,dvb_standard,sizeof(struct saa7146_standard)*2);
+		/* set dd1 stream a & b */
+      		saa7146_write(dev, DD1_STREAM_B, 0x00000000);
+		saa7146_write(dev, DD1_INIT, 0x0200700);
+		saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
+
+
 	} else if (dev->pci->subsystem_vendor == 0x110a) {
 		printk("av7110(%d): DVB-C w/o analog module detected\n",
 			av7110->dvb_adapter->num);
@@ -4330,6 +4623,16 @@
 	{ "NTSC", V4L2_STD_NTSC, 0x10, 244, 480, 0x40, 708, 709, 480, 640 },
 };
 
+static struct saa7146_standard analog_standard[] = {
+	{ "PAL", V4L2_STD_PAL, 0x18, 288, 576, 0x08, 708, 709, 576, 768 },
+	{ "NTSC", V4L2_STD_NTSC, 0x10, 244, 480, 0x40, 708, 709, 480, 640 },
+};
+
+static struct saa7146_standard dvb_standard[] = {
+	{ "PAL", V4L2_STD_PAL, 0x14, 288, 576, 0x4a, 708, 709, 576, 768 },
+	{ "NTSC", V4L2_STD_NTSC, 0x10, 244, 480, 0x40, 708, 709, 480, 640 },
+};
+
 static struct saa7146_extension av7110_extension;
 
 #define MAKE_AV7110_INFO(x_var,x_name) \
@@ -4390,7 +4693,7 @@
 static struct saa7146_ext_vv av7110_vv_data = {
 	.inputs		= 1,
 	.audios 	= 1,
-	.capabilities	= 0,
+	.capabilities	= V4L2_CAP_TUNER,
 	.flags		= SAA7146_EXT_SWAP_ODD_EVEN,
 
 	.stds		= &standard[0],
@@ -4442,7 +4745,11 @@
 
 MODULE_PARM(av7110_debug,"i");
 MODULE_PARM(vidmode,"i");
+MODULE_PARM_DESC(vidmode,"analog video out: 0 off, 1 CVBS+RGB (default), 2 CVBS+YC, 3 YC");
 MODULE_PARM(pids_off,"i");
+MODULE_PARM_DESC(pids_off,"clear video/audio/PCR PID filters when demux is closed");
 MODULE_PARM(adac,"i");
+MODULE_PARM_DESC(adac,"audio DAC type: 0 TI, 1 CRYSTAL, 2 MSP (use if autodetection fails)");
 MODULE_PARM(hw_sections, "i");
+MODULE_PARM_DESC(hw_sections, "0 use software section filter, 1 use hardware");
 
drivers/media/dvb/ttpci/av7110.h +10 -1
diff -uNrwB --new-file linux-2.5.73.bk/drivers/media/dvb/ttpci/av7110.h linux-2.5.73.work/drivers/media/dvb/ttpci/av7110.h
@@ -153,7 +153,8 @@
 	BlitBmp,
 	ReleaseBmp,
 	SetWTrans,
-	SetWNoTrans
+        SetWNoTrans,
+        Set_Palette
 };
 
 enum av7110_pid_command { 
@@ -405,6 +406,11 @@
 	struct dvb_i2c_bus	*i2c_bus;	
 	char			*card_name;
 
+	/* support for analog module of dvb-c */
+	int			has_analog_tuner;
+	int			current_input;
+	u32			current_freq;
+				
 	struct tasklet_struct   debi_tasklet;
 	struct tasklet_struct   gpio_tasklet;
 
@@ -572,6 +578,9 @@
 #define DATA_BUFF2_BASE	(DATA_BUFF1_BASE+DATA_BUFF1_SIZE)
 #define DATA_BUFF2_SIZE	0x0800
 
+#define DATA_BUFF3_BASE (DATA_BUFF2_BASE+DATA_BUFF2_SIZE)
+#define DATA_BUFF3_SIZE 0x0400
+
 #define Reserved	(DPRAM_BASE + 0x1E00)
 #define Reserved_SIZE	0x1C0
 
drivers/media/dvb/ttpci/ttpci-eeprom.c +118 -0

118 lines not on this page · raw message

drivers/media/dvb/ttpci/ttpci-eeprom.h +32 -0
diff -uNrwB --new-file linux-2.5.73.patch/drivers/media/dvb/ttpci/ttpci-eeprom.h linux-2.5.73.work/drivers/media/dvb/ttpci/ttpci-eeprom.h
@@ -0,0 +1,32 @@
+/*
+    Retrieve encoded MAC address from ATMEL ttpci_eeprom serial 2-wire EEPROM,
+    decode it and store it in associated adapter net device
+
+    Robert Schlabbach	GMX
+    Michael Glaum	KVH Industries
+    Holger Waechtler	Convergence
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef __TTPCI_EEPROM_H__
+#define __TTPCI_EEPROM_H__
+
+#include "dvb_i2c.h"
+
+extern int ttpci_eeprom_parse_mac(struct dvb_i2c_bus *i2c);
+
+#endif
drivers/media/dvb/dvb-core/dvbdev.h +1 -0
diff -uNrwB --new-file linux-2.5.73.bk/drivers/media/dvb/dvb-core/dvbdev.h linux-2.5.73.work/drivers/media/dvb/dvb-core/dvbdev.h
@@ -48,6 +48,7 @@
 	struct list_head list_head;
 	struct list_head device_list;
 	const char *name;
+	u8 proposed_mac [6];
 };