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