Re: knc-1 CAM problems

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Friday 21 April 2006 14:55, norbert wrote:
> Am Freitag, 21. April 2006 15:36 schrieb Andrew de Quincey:
> > On Friday 21 April 2006 14:24, norbert wrote:
> > > hello,
> > >
> > > I tested your latest 'budget-av-cam-1.patch', but now I can't talk to
> > > the CAM. Using your  'budget-av-tda10021.patch' patch worked for me in
> > > this way, that I got data out of the dvr device, with the cam plugged
> > > in on unscrambled channels and I could talk to the CAM.
> >
> > Right, sorry about that - new patch attached to my other mail - can you
> > let me know if it helps?
>
> Sorry to say, but the new patch also doesn't work for me. Now there is
> continues output of 'budget-av: cam inserted' and i can't communicate with
> the CAM.

Sorry about that - I missed a bit. Attached should fix it

> > > Some other problem is, that I can't decrypt encrypted channels, neither
> > > ca_zap nor vdr work. I also have problems decrypting channels under
> > > windows, which means there could be a problem with the alphacrypt cam
> > > or SmartCard.
> >
> > Argh that is very hard to track down that sort of problem - the cams
> > don't give any feedback :(
>
> I know the SmartCard itself is working in a standalone receiver with a
> builtin cam, so I have to test the CAM anywhere in the next days.

Right, cool.

> Are unencrypted channels routed through the CAM, or only encrypted ones?

All TS data goes through the CAM.
diff -r 0a8f56ab07fa linux/drivers/media/dvb/frontends/tda10021.c
--- a/linux/drivers/media/dvb/frontends/tda10021.c	Mon Apr 17 16:44:02 2006 -0300
+++ b/linux/drivers/media/dvb/frontends/tda10021.c	Fri Apr 21 15:25:18 2006 +0100
@@ -89,6 +89,14 @@ static int tda10021_writereg (struct tda
 	msleep(10);
 	return (ret != 1) ? -EREMOTEIO : 0;
 }
+
+int tda10021_write_byte(struct dvb_frontend* fe, int reg, int data)
+{
+	struct tda10021_state* state = fe->demodulator_priv;
+
+	return tda10021_writereg(state, reg, data);
+}
+EXPORT_SYMBOL(tda10021_write_byte);
 
 static u8 tda10021_readreg (struct tda10021_state* state, u8 reg)
 {
diff -r 0a8f56ab07fa linux/drivers/media/dvb/frontends/tda10021.h
--- a/linux/drivers/media/dvb/frontends/tda10021.h	Mon Apr 17 16:44:02 2006 -0300
+++ b/linux/drivers/media/dvb/frontends/tda10021.h	Fri Apr 21 15:25:18 2006 +0100
@@ -39,4 +39,6 @@ extern struct dvb_frontend* tda10021_att
 extern struct dvb_frontend* tda10021_attach(const struct tda10021_config* config,
 					    struct i2c_adapter* i2c, u8 pwm);
 
+extern int tda10021_write_byte(struct dvb_frontend* fe, int reg, int data);
+
 #endif // TDA10021_H
diff -r 0a8f56ab07fa linux/drivers/media/dvb/ttpci/budget-av.c
--- a/linux/drivers/media/dvb/ttpci/budget-av.c	Mon Apr 17 16:44:02 2006 -0300
+++ b/linux/drivers/media/dvb/ttpci/budget-av.c	Fri Apr 21 15:25:18 2006 +0100
@@ -50,6 +50,12 @@
 
 #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_av {
 	struct budget budget;
 	struct video_device *vd;
@@ -58,6 +64,10 @@ struct budget_av {
 	struct tasklet_struct ciintf_irq_tasklet;
 	int slot_status;
 	struct dvb_ca_en50221 ca;
+	int reinitialise_demod;
+	int tda10021_poclkp;
+	int tda10021_ts_enabled;
+	int (*tda10021_set_frontend)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p);
 };
 
 /* GPIO Connections:
@@ -129,9 +139,8 @@ static int ciintf_read_attribute_mem(str
 	udelay(1);
 
 	result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 1);
-
 	if (result == -ETIMEDOUT)
-		budget_av->slot_status = 0;
+		budget_av->slot_status = SLOTSTATUS_NONE;
 	return result;
 }
 
@@ -147,9 +156,8 @@ static int ciintf_write_attribute_mem(st
 	udelay(1);
 
 	result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 1);
-
 	if (result == -ETIMEDOUT)
-		budget_av->slot_status = 0;
+		budget_av->slot_status = SLOTSTATUS_NONE;
 	return result;
 }
 
@@ -165,9 +173,8 @@ static int ciintf_read_cam_control(struc
 	udelay(1);
 
 	result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 3, 1, 0, 0);
-
 	if (result == -ETIMEDOUT)
-		budget_av->slot_status = 0;
+		budget_av->slot_status = SLOTSTATUS_NONE;
 	return result;
 }
 
@@ -183,9 +190,8 @@ static int ciintf_write_cam_control(stru
 	udelay(1);
 
 	result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 3, 1, value, 0, 0);
-
 	if (result == -ETIMEDOUT)
-		budget_av->slot_status = 0;
+		budget_av->slot_status = SLOTSTATUS_NONE;
 	return result;
 }
 
@@ -193,12 +199,12 @@ static int ciintf_slot_reset(struct dvb_
 {
 	struct budget_av *budget_av = (struct budget_av *) ca->data;
 	struct saa7146_dev *saa = budget_av->budget.dev;
-	int timeout = 50; // 5 seconds (4.4.6 Ready)
 
 	if (slot != 0)
 		return -EINVAL;
 
 	dprintk(1, "ciintf_slot_reset\n");
+        budget_av->slot_status = SLOTSTATUS_RESET;
 
 	saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
 
@@ -208,20 +214,17 @@ static int ciintf_slot_reset(struct dvb_
 	msleep(20); /* 20 ms Vcc settling time */
 
 	saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO); /* enable card */
-
-	/* This should have been based on pin 16 READY of the pcmcia port,
-	 * but AFAICS it is not routed to the saa7146 */
-	while (--timeout > 0 && ciintf_read_attribute_mem(ca, slot, 0) != 0x1d)
-		msleep(100);
-
-	/* reinitialise the frontend */
-	dvb_frontend_reinitialise(budget_av->budget.dvb_frontend);
-
-	if (timeout <= 0)
-	{
-		printk(KERN_ERR "budget-av: cam reset failed (timeout).\n");
-		saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
-		return -ETIMEDOUT;
+        ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
+	msleep(20);
+
+	/* reinitialise the frontend if necessary */
+	if (budget_av->reinitialise_demod)
+		dvb_frontend_reinitialise(budget_av->budget.dvb_frontend);
+
+	/* set tda10021 back to original clock configuration on reset */
+	if (budget_av->tda10021_poclkp) {
+		tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa0);
+		budget_av->tda10021_ts_enabled = 0;
 	}
 
 	return 0;
@@ -237,8 +240,15 @@ static int ciintf_slot_shutdown(struct d
 
 	dprintk(1, "ciintf_slot_shutdown\n");
 
+	saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
 	ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
-	budget_av->slot_status = 0;
+	budget_av->slot_status = SLOTSTATUS_NONE;
+
+	/* set tda10021 back to original clock configuration when cam removed */
+	if (budget_av->tda10021_poclkp) {
+		tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa0);
+		budget_av->tda10021_ts_enabled = 0;
+	}
 	return 0;
 }
 
@@ -253,6 +263,13 @@ static int ciintf_slot_ts_enable(struct 
 	dprintk(1, "ciintf_slot_ts_enable: %d\n", budget_av->slot_status);
 
 	ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA);
+
+	/* tda10021 seems to need a different TS clock config when data is routed to the CAM */
+	if (budget_av->tda10021_poclkp) {
+		tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa1);
+		budget_av->tda10021_ts_enabled = 1;
+	}
+
 	return 0;
 }
 
@@ -260,50 +277,59 @@ static int ciintf_poll_slot_status(struc
 {
 	struct budget_av *budget_av = (struct budget_av *) ca->data;
 	struct saa7146_dev *saa = budget_av->budget.dev;
-	int cam_present = 0;
 
 	if (slot != 0)
 		return -EINVAL;
 
-	if (!budget_av->slot_status)
-	{
-		// first of all test the card detect line
+	/* test the card detect line - only done if there is no card present,
+	 * since it never goes high for some CAMs on this interface (e.g. topuptv) */
+	if (budget_av->slot_status == SLOTSTATUS_NONE) {
 		saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
 		udelay(1);
-		if (saa7146_read(saa, PSR) & MASK_06)
-		{
-			cam_present = 1;
+		if (saa7146_read(saa, PSR) & MASK_06) {
+			saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO); /* enable card */
+			budget_av->slot_status = SLOTSTATUS_PRESENT;
+			printk(KERN_INFO "budget-av: cam inserted\n");
 		}
 		saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
-
-		// that is unreliable however, so try and read from IO memory
-		if (!cam_present)
-		{
-			saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
-			if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1) != -ETIMEDOUT)
-			{
-				cam_present = 1;
+	}
+
+	/* We also try and read from IO memory to work round the above bugs. If
+	 * there is no CAM, we will get a timeout. Only done if there is no cam
+	 * present, since this test actually breaks some cams :(
+	 *
+	 * if the CI interface is not open, we also do the above test since we
+	 * don't care if the cam has problems - we'll be resetting it on open() anyway */
+	if ((budget_av->slot_status == SLOTSTATUS_NONE) || (!open)) {
+		saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
+		if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1) != -ETIMEDOUT) {
+			if (budget_av->slot_status == SLOTSTATUS_NONE) {
+				saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO); /* enable card */
+				budget_av->slot_status = SLOTSTATUS_PRESENT;
+				printk(KERN_INFO "budget-av: cam inserted\n");
+			}
+		} else {
+			if (budget_av->slot_status != SLOTSTATUS_NONE) {
+				ciintf_slot_shutdown(ca, slot);
+				printk(KERN_INFO "budget-av: cam ejected\n");
 			}
 		}
-
-		// did we find something?
-		if (cam_present) {
-			printk(KERN_INFO "budget-av: cam inserted\n");
-			budget_av->slot_status = 1;
+	}
+
+	/* during a reset, read from the attribute memory to know when CAM is ready */
+	if (budget_av->slot_status == SLOTSTATUS_RESET) {
+		if (ciintf_read_attribute_mem(ca, slot, 0) == 0x1d) {
+			budget_av->slot_status = SLOTSTATUS_READY;
 		}
-	} else if (!open) {
-		saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
-		if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1) == -ETIMEDOUT)
-		{
-			printk(KERN_INFO "budget-av: cam ejected\n");
-			saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
-			budget_av->slot_status = 0;
+	}
+
+	/* work out correct return code */
+	if (budget_av->slot_status != SLOTSTATUS_NONE) {
+		if (budget_av->slot_status & SLOTSTATUS_READY) {
+			return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
 		}
-	}
-
-	if (budget_av->slot_status == 1)
-		return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
-
+		return DVB_CA_EN50221_POLL_CAM_PRESENT;
+	}
 	return 0;
 }
 
@@ -333,6 +359,8 @@ static int ciintf_init(struct budget_av 
 	budget_av->ca.slot_ts_enable = ciintf_slot_ts_enable;
 	budget_av->ca.poll_slot_status = ciintf_poll_slot_status;
 	budget_av->ca.data = budget_av;
+	budget_av->budget.ci_present = 1;
+	budget_av->slot_status = SLOTSTATUS_NONE;
 
 	if ((result = dvb_ca_en50221_init(&budget_av->budget.dvb_adapter,
 					  &budget_av->ca, 0, 1)) != 0) {
@@ -341,7 +369,6 @@ static int ciintf_init(struct budget_av 
 	}
 
 	printk(KERN_INFO "budget-av: ci interface initialised.\n");
-	budget_av->budget.ci_present = 1;
 	return 0;
 
 error:
@@ -1012,6 +1039,23 @@ static u8 read_pwm(struct budget_av *bud
 #define SUBID_DVBT_KNC1		0x0030
 #define SUBID_DVBT_CINERGY1200	0x1157
 
+
+static int tda10021_set_frontend(struct dvb_frontend *fe,
+				 struct dvb_frontend_parameters *p)
+{
+	struct budget_av* budget_av = fe->dvb->priv;
+	int result;
+
+	result = budget_av->tda10021_set_frontend(fe, p);
+	if (budget_av->tda10021_ts_enabled) {
+		tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa1);
+	} else {
+		tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa0);
+	}
+
+	return result;
+}
+
 static void frontend_init(struct budget_av *budget_av)
 {
 	struct saa7146_dev * saa = budget_av->budget.dev;
@@ -1062,24 +1106,21 @@ static void frontend_init(struct budget_
 
 	case SUBID_DVBC_KNC1:
 	case SUBID_DVBC_KNC1_PLUS:
-		fe = tda10021_attach(&philips_cu1216_config,
-				     &budget_av->budget.i2c_adap,
-				     read_pwm(budget_av));
-		break;
-
-	case SUBID_DVBT_KNC1:
-	case SUBID_DVBT_KNC1_PLUS:
-		fe = tda10046_attach(&philips_tu1216_config,
-				     &budget_av->budget.i2c_adap);
-		break;
-
 	case SUBID_DVBC_CINERGY1200:
 		fe = tda10021_attach(&philips_cu1216_config,
 				     &budget_av->budget.i2c_adap,
 				     read_pwm(budget_av));
+		if (fe) {
+			budget_av->tda10021_poclkp = 1;
+			budget_av->tda10021_set_frontend = fe->ops->set_frontend;
+			fe->ops->set_frontend = tda10021_set_frontend;
+		}
 		break;
 
+	case SUBID_DVBT_KNC1:
+	case SUBID_DVBT_KNC1_PLUS:
 	case SUBID_DVBT_CINERGY1200:
+		budget_av->reinitialise_demod = 1;
 		fe = tda10046_attach(&philips_tu1216_config,
 				     &budget_av->budget.i2c_adap);
 		break;
_______________________________________________

linux-dvb@xxxxxxxxxxx
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb

[Index of Archives]     [Linux Media]     [Video 4 Linux]     [Asterisk]     [Samba]     [Xorg]     [Xfree86]     [Linux USB]

  Powered by Linux