knc-1 CAM problems

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

 



Hi, bear with me and hopefully we can get this blasted card fixed once and for 
all.

I can test the DVBT cards, and you guys can test DVBS and DVBC respectively. 
So, attached is a patch (against hg latest) which attempts to fix the 
following:

1) rewrite cam detection code to work more reliably.
2) reinitialise the tda10046 after cam reset.
3) set the tda10021 into the correct transport stream mode depending on 
whether the CAM is in or out.
4) Don't reinitialise the tda10021 or stv0299 on cam reset.

Can you let me know how it goes. I _really_ want to get this sorted, it seems 
to keep coming back :(

Please reply to this thread so we can keep track of how things are going.
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 00:09:34 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 00:09:34 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 00:09:34 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:
@@ -120,7 +130,6 @@ static int ciintf_read_attribute_mem(str
 static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
 {
 	struct budget_av *budget_av = (struct budget_av *) ca->data;
-	int result;
 
 	if (slot != 0)
 		return -EINVAL;
@@ -128,17 +137,12 @@ static int ciintf_read_attribute_mem(str
 	saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI);
 	udelay(1);
 
-	result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 1);
-
-	if (result == -ETIMEDOUT)
-		budget_av->slot_status = 0;
-	return result;
+	return ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 1);
 }
 
 static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)
 {
 	struct budget_av *budget_av = (struct budget_av *) ca->data;
-	int result;
 
 	if (slot != 0)
 		return -EINVAL;
@@ -146,17 +150,12 @@ static int ciintf_write_attribute_mem(st
 	saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI);
 	udelay(1);
 
-	result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 1);
-
-	if (result == -ETIMEDOUT)
-		budget_av->slot_status = 0;
-	return result;
+	return ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 1);
 }
 
 static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)
 {
 	struct budget_av *budget_av = (struct budget_av *) ca->data;
-	int result;
 
 	if (slot != 0)
 		return -EINVAL;
@@ -164,17 +163,12 @@ static int ciintf_read_cam_control(struc
 	saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
 	udelay(1);
 
-	result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 3, 1, 0, 0);
-
-	if (result == -ETIMEDOUT)
-		budget_av->slot_status = 0;
-	return result;
+	return ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 3, 1, 0, 0);
 }
 
 static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)
 {
 	struct budget_av *budget_av = (struct budget_av *) ca->data;
-	int result;
 
 	if (slot != 0)
 		return -EINVAL;
@@ -182,23 +176,19 @@ static int ciintf_write_cam_control(stru
 	saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
 	udelay(1);
 
-	result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 3, 1, value, 0, 0);
-
-	if (result == -ETIMEDOUT)
-		budget_av->slot_status = 0;
-	return result;
+	return ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 3, 1, value, 0, 0);
 }
 
 static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
 {
 	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 +198,16 @@ 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);
+
+	/* setup tda10021 if necessary */
+	if (budget_av->tda10021_poclkp && budget_av->tda10021_ts_enabled) {
+		tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa1);
 	}
 
 	return 0;
@@ -237,8 +223,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 +246,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 +260,44 @@ 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
-		saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
-		udelay(1);
-		if (saa7146_read(saa, PSR) & MASK_06)
-		{
-			cam_present = 1;
+	/* we used to test the card detect line here, but that doesn't work
+	 * with some cams on this interface (e.g. topuptv), so it was removed.
+	 * Instead we try and read from IO memory. If there is no CAM, we will
+	 * get a timeout. */
+	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");
 		}
-		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;
+	} else {
+		if (budget_av->slot_status != SLOTSTATUS_NONE) {
+			ciintf_slot_shutdown(ca, slot);
+			printk(KERN_INFO "budget-av: cam ejected\n");
+		}
+	}
+
+	/* during a reset, read from the attribute memory to know when CAM is ready */
+	if (budget_av->slot_status & SLOTSTATUS_RESET) {
+		if (budget_av->slot_status & SLOTSTATUS_RESET) {
+			if (ciintf_read_attribute_mem(ca, slot, 0) == 0x1d) {
+				budget_av->slot_status = SLOTSTATUS_READY;
 			}
 		}
-
-		// did we find something?
-		if (cam_present) {
-			printk(KERN_INFO "budget-av: cam inserted\n");
-			budget_av->slot_status = 1;
+	}
+
+	/* 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;
 		}
-	} 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;
-		}
-	}
-
-	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 +327,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 +337,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 +1007,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;
@@ -1065,10 +1077,14 @@ static void frontend_init(struct budget_
 		fe = tda10021_attach(&philips_cu1216_config,
 				     &budget_av->budget.i2c_adap,
 				     read_pwm(budget_av));
+		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:
+		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