[linux-dvb] Problem with init some CAM blocks on TTBudget-S1500 + CI

Simon Baxter linuxtv at nzbaxters.com
Sun Jul 29 01:06:14 CEST 2007


I've seen these problems too.  Mark Anderson sent me the following patch, which introduces delays as you mention.

This fixed my CAM access problems I had with dvb_ca_en50221.c


--- drivers/media/dvb/dvb-core/dvb_ca_en50221.c.orig    2007-05-3121:45:21.700049473 +1000
+++ drivers/media/dvb/dvb-core/dvb_ca_en50221.c 2007-06-0123:21:32.596707598 +1000
@@ -721,29 +721,34 @@ static int dvb_ca_en50221_write_data(str
        // sanity check
        if (bytes_write > ca->slot_info[slot].link_buf_size)
                return -EINVAL;
-
+msleep(1);
        /* check if interface is actually waiting for us to read fromit, or if a read is in progress */
        if ((status = ca->pub->read_cam_control(ca->pub, slot,CTRLIF_STATUS)) < 0)
                goto exitnowrite;
+msleep(1);
        if (status & (STATUSREG_DA | STATUSREG_RE)) {
                status = -EAGAIN;
                goto exitnowrite;
        }
+msleep(1);


        /* OK, set HC bit */
        if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND,
                                                 IRQEN | CMDREG_HC)) != 0)
                goto exit;
+msleep(1);

        /* check if interface is still free */
        if ((status = ca->pub->read_cam_control(ca->pub, slot,CTRLIF_STATUS)) < 0)
                goto exit;
+msleep(1);
        if (!(status & STATUSREG_FR)) {
                /* it wasn't free => try again later */
                status = -EAGAIN;
                goto exit;
        }
+msleep(1);

        /* send the amount of data */
        if ((status = ca->pub->write_cam_control(ca->pub, slot,CTRLIF_SIZE_HIGH, bytes_write >> 8)) != 0)
@@ -752,21 +757,26 @@ static int dvb_ca_en50221_write_data(str
                                                 bytes_write & 0xff)) != 0)
                goto exit;

+msleep(1);
        /* send the buffer */
        for (i = 0; i < bytes_write; i++) {
                if ((status = ca->pub->write_cam_control(ca->pub,slot, CTRLIF_DATA, buf[i])) != 0)
                        goto exit;
        }

+msleep(1);
        /* check for write error (WE should now be 0) */
        if ((status = ca->pub->read_cam_control(ca->pub, slot,CTRLIF_STATUS)) < 0)
                goto exit;
+msleep(1);
        if (status & STATUSREG_WE) {
                ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT;
                status = -EIO;
                goto exit;
        }
+msleep(1);
        status = bytes_write;
+msleep(1);

        dprintk("Wrote CA packet for slot %i, connection id 0x%xlast_frag:%i size:0x%x\n", slot,                buf[0], (buf[1] & 0x80) == 0, bytes_write);

--- drivers/media/common/saa7146_i2c.c.orig     2007-05-31
22:17:57.922566547 +1000
+++ drivers/media/common/saa7146_i2c.c  2007-06-01 20:51:56.638799917 +1000
@@ -179,6 +179,7 @@ static int saa7146_i2c_writeout(struct s
        u32 status = 0, mc2 = 0;
        int trial = 0;
        unsigned long timeout;
+       int retry;

        /* write out i2c-command */
        DEB_I2C(("before: 0x%08x (status: 0x%08x),%d\n",*dword,saa7146_read(dev, I2C_STATUS), dev->i2c_op));
@@ -194,6 +195,9 @@ static int saa7146_i2c_writeout(struct s
                saa7146_write(dev, MC2, (MASK_00 | MASK_16));

                timeout = HZ/100 + 1; /* 10ms */
+               retry = 1000;
+               while (retry-- > 0)
+               {
                timeout = wait_event_interruptible_timeout(dev->i2c_wq, dev->i2c_op == 0,timeout);
                if (timeout == -ERESTARTSYS || dev->i2c_op) {
                        SAA7146_IER_DISABLE(dev, MASK_16|MASK_17);
@@ -203,10 +207,21 @@ static int saa7146_i2c_writeout(struct s
                                return -ERESTARTSYS;

                        printk(KERN_WARNING "saa7146_i2c_writeout:timed out waiting for end of xfer\n");
+                               msleep(1);
+                       }
+                       else
+                       {
+                               break;
+                       }
+               }
+               if (retry <= 0)
+               {
                        return -EIO;
                }
                status = saa7146_read(dev, I2C_STATUS);
-       } else {
+       }
+       else
+       {
                saa7146_write(dev, I2C_STATUS,   dev->i2c_bitrate);
                saa7146_write(dev, I2C_TRANSFER, *dword);
                saa7146_write(dev, MC2, (MASK_00 | MASK_16));
@@ -235,7 +250,7 @@ static int saa7146_i2c_writeout(struct s
                                /* this is normal when probing the bus
                                 * (no answer from nonexisistant device...)
                                 */
-                               DEB_I2C(("saa7146_i2c_writeout: timedout waiting for end of xfer\n"));
+                               DEB_I2C(("saa7146_i2c_writeout: timedout waiting for end of xfer2\n"));
                                return -EIO;
                        }
                        if (++trial < 50 && short_delay)



  ----- Original Message ----- 
  From: Akiva Sadovski 
  To: linux-dvb at linuxtv.org 
  Sent: Friday, July 20, 2007 9:01 AM
  Subject: Re: [linux-dvb] Problem with init some CAM blocks on TTBudget-S1500 + CI


  Evgen, all,
     I'm only a stupid newbie in the linuxtv world,
  but from my experience with CAM cards it seems to me that Eugen's observation is correct but not precious:

  IMHO, the sequence should be (from the DVB-CI standard):

    1) "host now tells the module to use this buffer size by writing a '1' to the SW bit in the Command Register"
     2) "waiting until the FR bit is set"
     3) "writing the size as 2 bytes of data, most significant byte first..."
     4) "At the end of the transfer the host sets the SW bit to '0'. "

  this is actually what is coded in  dvb_ca_en50221.c, but I GUESS - I HAVEN'T TESTED IT!!
  that the problem is that one have to introduce some delay between writing the buffer size
  and setting the SW bit to zero - since according to the standard we have to wait until the transfer (and not
  simply the write operation) is finished

           if ((ret = dvb_ca_en50221_write_data(ca, slot, buf, 2)) != 2)
                   return -EIO;
  /*
     WE NEED DELAY HERE ... ?
  */
           if ((ret = ca->pub->write_cam_control(ca->pub, slot, 
  CTRLIF_COMMAND, IRQEN)) != 0)
                   return ret;
  =======================
  Now my question:
    I'm writing the DVB-CI driver for customer made HW developed by the firm I'm working for.
    I'm going to use the dvb-core infrastructure.
    Is there any card which driver already uses the dvb_ca part of the dvb-core ?
    
    I put an eye on Twinhan 1030 card, but it has the vendor-specific driver which has nothing in common
  with dvb-core

  Thanks in advance,

  Akiva Sadovski

  Scopus Video Networks


------------------------------------------------------------------------------


  _______________________________________________
  linux-dvb mailing list
  linux-dvb at linuxtv.org
  http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.linuxtv.org/pipermail/linux-dvb/attachments/20070729/1f117c83/attachment-0001.htm 


More information about the linux-dvb mailing list