--- linux-dvb.cvs-20030816/driver/frontends/ves1820.c.orig	Sat Aug 16 14:14:37 2003
+++ linux-dvb.cvs-20030816/driver/frontends/ves1820.c	Sun Aug 17 16:53:49 2003
@@ -19,6 +19,21 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */    
 
+/*
+ * 20030817: Dr. Peter Bieringer <pb at bieringer dot de>
+ * 	add support for optional module options per card (max 4 cards are supported at the moment)
+ *		clkconf: apply dedicated CLKCONF value per card (-1: default)
+ *		carconf: apply dedicated CARCONF value per card (-1: default)
+ *		pwm    : apply dedicated PWM value per card (-1: take EEPROM stored value)
+ *	   Usage: 
+ *	   /etc/modules.conf:
+ *		options ves1820 clkconf=0x0a,0x12 carconf=0x52,0x12 pwm=0x38,-1
+ *	   insmod:
+ *		insmod ves1820 clkconf=0x0a,-1 carconf=0x52,-1 pwm=0x38,-1
+ *
+ *	extend logging information, display now also card number
+*/
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/delay.h>
@@ -27,7 +42,7 @@
 #include "dvb_frontend.h"
 
 
-#if 0
+#if 1
 #define dprintk(x...) printk(x)
 #else
 #define dprintk(x...)
@@ -98,7 +113,11 @@
 static
 u8 ves1820_inittab [] =
 {
-	0x69, 0x6A, 0x9B, 0x12, 0x12, 0x46, 0x26, 0x1A,
+	/* 0x69, 0x6A, 0x9B, 0x0A, 0x52, 0x46, 0x26, 0x1A, */ /* source 2003-05-24 */
+	/* 0x69, 0x6A, 0x9B, 0x02, 0x12, 0x46, 0x26, 0x1A, */ /* (No DYN, No GAIN3, No CAR_P[2]) */
+	/* 0x69, 0x6A, 0x9B, 0x0A, 0x12, 0x46, 0x26, 0x1A, */ /* (DYN, No GAIN3, No CAR_P[2]) */
+	/* 0x69, 0x6A, 0x9B, 0x12, 0x52, 0x46, 0x26, 0x1A, */ /* working with not proper PMW */
+	0x69, 0x6A, 0x9B, 0x12, 0x12, 0x46, 0x26, 0x1A, /* source 2003-08-16 */
 	0x43, 0x6A, 0xAA, 0xAA, 0x1E, 0x85, 0x43, 0x28,
 	0xE0, 0x00, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00,
 	0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
@@ -108,6 +127,15 @@
 };
 
 
+/* optional CLKCONF, CARCONF, PWM parameters per card, can be overwritten by module options */
+#define MAX_UNITS 4
+
+static int clkconf[MAX_UNITS] = { -1, -1, -1, -1 };
+static int carconf[MAX_UNITS] = { -1, -1, -1, -1 };
+static int pwm[MAX_UNITS] = { -1, -1, -1, -1 };
+static int pwm_eeprom[MAX_UNITS] = { -1, -1, -1, -1 }; /* original PWM in EEPROM */
+
+
 static
 int ves1820_writereg (struct dvb_frontend *fe, u8 reg, u8 data)
 {
@@ -120,9 +148,9 @@
 	ret = i2c->xfer (i2c, &msg, 1);
 
 	if (ret != 1)
-		dprintk("%s: writereg error "
+		dprintk("DVB: VES1820(%d): %s: writereg error "
 			"(reg == 0x%02x, val == 0x%02x, ret == %i)\n",
-			__FUNCTION__, reg, data, ret);
+			fe->i2c->adapter->num, __FUNCTION__, reg, data, ret);
 
 	mdelay(10);
 	return (ret != 1) ? -EREMOTEIO : 0;
@@ -143,7 +171,7 @@
 	ret = i2c->xfer (i2c, msg, 2);
 
 	if (ret != 2)
-		dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
+		dprintk("DVB: VES1820(%d): %s: readreg error (ret == %i)\n", fe->i2c->adapter->num, __FUNCTION__, ret);
 
 	return b1[0];
 }
@@ -240,13 +268,40 @@
 int ves1820_init (struct dvb_frontend *fe)
 {
 	int i;
+	int num_card = fe->i2c->adapter->num;
+	u8 value;
         
-        dprintk("VES1820: init chip\n");
+        dprintk("DVB: VES1820(%d): init chip\n", num_card);
 
         ves1820_writereg (fe, 0, 0);
 
-	for (i=0; i<53; i++)
-                ves1820_writereg (fe, i, ves1820_inittab[i]);
+	for (i=0; i<53; i++) {
+                value = ves1820_inittab[i];
+
+		if ((num_card >= 0) && (num_card < MAX_UNITS)) {
+			/* only set per card values on MAX_UNITS supported cards */
+			if (i == 0x03) {
+				if (clkconf[num_card] != -1) {
+					if ((clkconf[num_card] >=0) && (clkconf[num_card] <=0xff)) {
+						dprintk("DVB: VES1820(%d): init chip/CLKCONF: overwrite with 0x%02x (default: 0x%02x)\n", num_card, clkconf[num_card], value);
+						value = (u8) clkconf[num_card]; /* ves1820_inittab[0x03] per card */
+					} else {
+						dprintk("DVB: VES1820(%d): init chip/CLKCONF: given value out of range: 0x%x (use default: 0x%02x)\n", num_card, clkconf[num_card], value);
+					};
+				};
+			} else if (i == 0x04) {
+				if (carconf[num_card] != -1) {
+					if ((carconf[num_card] >=0) && (carconf[num_card] <=0xff)) {
+						dprintk("DVB: VES1820(%d): init chip/CARCONF: overwrite with 0x%02x (default: 0x%02x)\n", num_card, carconf[num_card], value);
+						value = (u8) carconf[num_card]; /* ves1820_inittab[0x04] per card */
+					} else {
+						dprintk("DVB: VES1820(%d): init chip/CARCONF: given value out of range: 0x%x (use default: 0x%02x)\n", num_card, carconf[num_card], value);
+					};
+				};
+			};
+		};
+                ves1820_writereg (fe, i, value);
+	};
 
 	ves1820_writereg (fe, 0x34, GET_PWM(fe->data)); 
 
@@ -257,11 +312,14 @@
 static
 int ves1820_set_symbolrate (struct dvb_frontend *fe, u32 symbolrate)
 {
+	int num_card = fe->i2c->adapter->num;
+
         s32 BDR; 
         s32 BDRI;
         s16 SFIL=0;
         u16 NDEC = 0;
         u32 tmp, ratio;
+	u8 value;
 
 #define XIN 57840000UL
 #define FIN (XIN >> 4)
@@ -298,8 +356,15 @@
                 BDRI = 0xFF;
         
         SFIL = (SFIL << 4) | ves1820_inittab[0x0E];
-        
-        NDEC = (NDEC << 6) | ves1820_inittab[0x03];
+       
+	value = ves1820_inittab[0x03];	
+	if ((num_card >= 0) && (num_card < MAX_UNITS)) {
+		/* only set per card values on MAX_UNITS supported cards */
+		if ((clkconf[num_card] >=0) && (clkconf[num_card] <=0xff)) {
+			value = (u8) clkconf[num_card]; /* ves1820_inittab[0x03] per card, currently always from card 0 */
+		};
+	};
+        NDEC = (NDEC << 6) | value;
 
         ves1820_writereg (fe, 0x03, NDEC);
         ves1820_writereg (fe, 0x0a, BDR&0xff);
@@ -423,7 +488,7 @@
 		if (sync & 2)
 			/* AFC only valid when carrier has been recovered */
 			afc = ves1820_readreg(fe, 0x19);
-		dprintk ("%s: AFC (%d) %dHz\n", __FILE__, afc,
+		dprintk ("DVB: VES1820(%d): AFC (%d) %dHz\n", fe->i2c->adapter->num, afc,
 				-((s32)(p->u.qam.symbol_rate >> 3) * afc >> 7));
 
 
@@ -465,15 +530,14 @@
 
 	if (i2c->xfer(i2c, &msg1, 1) == 1) {
 		type = 0;
-		printk ("%s: setup for tuner spXXXX\n", __FILE__);
+		dprintk ("DVB: VES1820(%d): setup for tuner spXXXX\n", i2c->adapter->num);
 	} else if (i2c->xfer(i2c, &msg2, 1) == 1) {
 		type = 1;
-		printk ("%s: setup for tuner sp5659c\n", __FILE__);
+		dprintk ("DVB: VES1820(%d): setup for tuner sp5659c\n", i2c->adapter->num);
 	} else {
 		type = -1;
-		printk ("%s: unknown PLL, "
-			"please report to <linuxdvb@linuxtv.org>!!\n",
-			__FILE__);
+		dprintk ("DVB: VES1820(%d): unknown PLL, "
+			"please report to <linuxdvb@linuxtv.org>!!\n", i2c->adapter->num);
 	}
 
 	return type;
@@ -490,7 +554,7 @@
 
 	i2c->xfer (i2c, msg, 2);
 
-	dprintk("VES1820: pwm=%02x\n", pwm);
+	dprintk("DVB: VES1820(%d): pwm=0x%02x\n", i2c->adapter->num, pwm);
 
 	if (pwm == 0xff)
 		pwm = 0x48;
@@ -525,6 +589,8 @@
 	void *data = NULL;
 	int demod_addr;
 	int tuner_type;
+	int num_card = i2c->adapter->num;
+	u8 value;
 
 	if ((demod_addr = probe_demod_addr(i2c)) < 0)
 		return -ENODEV;
@@ -532,7 +598,23 @@
 	if ((tuner_type = probe_tuner(i2c)) < 0)
 		return -ENODEV;
 
-	SET_PWM(data, read_pwm(i2c));
+	value = read_pwm(i2c);
+	if ((num_card >= 0) && (num_card < MAX_UNITS)) {
+		/* only set per card values on MAX_UNITS supported cards */
+		pwm_eeprom[num_card] = value;
+		if (pwm[num_card] != -1) {
+			if ((pwm[num_card] >=0) && (pwm[num_card] <=0xff)) {
+				dprintk("DVB: VES1820(%d): attach/PWM: overwrite with 0x%02x (EEPROM: 0x%02x)\n", num_card, pwm[num_card], pwm_eeprom[num_card]);
+				value = (u8) pwm[num_card]; /* overwrite PWM per card */
+			} else {
+				dprintk("DVB: VES1820(%d): attach/PWM: given value out of range: 0x%x (use EEPROM: 0x%02x)\n", num_card, pwm[num_card], pwm_eeprom[num_card]);
+				value = pwm_eeprom[num_card];
+			};
+		} else {
+			dprintk("DVB: VES1820(%d): attach/PWM: use EEPROM value: 0x%02x\n", num_card, pwm_eeprom[num_card]);
+		};
+	};
+	SET_PWM(data, value);
 	SET_REG0(data, ves1820_inittab[0]);
 	SET_TUNER(data, tuner_type);
 	SET_DEMOD_ADDR(data, demod_addr);
@@ -553,6 +635,7 @@
 static
 int __init init_ves1820 (void)
 {
+        dprintk("DVB: VES1820: module loaded\n");
 	return dvb_register_i2c_device (THIS_MODULE,
 					ves1820_attach, ves1820_detach);
 }
@@ -568,6 +651,13 @@
 module_init(init_ves1820);
 module_exit(exit_ves1820);
 
+MODULE_PARM(clkconf, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(carconf, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(pwm, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM_DESC(clkconf, "apply dedicated CLKCONF value per card (-1: default)");
+MODULE_PARM_DESC(carconf, "apply dedicated CARCONF value per card (-1: default)");
+MODULE_PARM_DESC(pwm, "apply dedicated PWM value per card (-1: take EEPROM stored value)");
+
 MODULE_DESCRIPTION("VES1820 DVB-C frontend driver");
 MODULE_AUTHOR("Ralph Metzler, Holger Waechtler");
 MODULE_LICENSE("GPL");
