V4L/DVB (11810): em28xx: properly set packet size based on the device's eeprom config...
authorDevin Heitmueller <dheitmueller@kernellabs.com>
Sat, 16 May 2009 20:09:28 +0000 (17:09 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Tue, 16 Jun 2009 21:21:08 +0000 (18:21 -0300)
The em28xx actually has a register that tells the driver what the maximum
packet size is (based on a value programmed into the eeprom).  Make use of
that register instead of assuming a hardcoded value of 564 (since 564 is not
correct for devices that do QAM such as the KWorld 340u).

Note that for now the em2874 code isn't there, falling back to the 564 value,
however this is not a problem since there are not any em2874 based devices in
the current v4l-dvb tree).

Thanks to Jarod Wilson for detecting the initial problem and figuring out that
the isoc configuration was wrong for his device.

Cc: Jarod Wilson <jarod@wilsonet.com>
Signed-off-by: Devin Heitmueller <dheitmueller@kernellabs.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/em28xx/em28xx-core.c
drivers/media/video/em28xx/em28xx-dvb.c
drivers/media/video/em28xx/em28xx-reg.h
drivers/media/video/em28xx/em28xx.h

index 7375353c04eb87368bd5f8a006015b4b127e2006..b7a2fedc3904c22b8ea38f404d27d91ebd997c0c 100644 (file)
@@ -1012,6 +1012,41 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets,
 }
 EXPORT_SYMBOL_GPL(em28xx_init_isoc);
 
+/* Determine the packet size for the DVB stream for the given device
+   (underlying value programmed into the eeprom) */
+int em28xx_isoc_dvb_max_packetsize(struct em28xx *dev)
+{
+       unsigned int chip_cfg2;
+       unsigned int packet_size = 564;
+
+       if (dev->chip_id == CHIP_ID_EM2874) {
+               /* FIXME - for now assume 564 like it was before, but the
+                  em2874 code should be added to return the proper value... */
+               packet_size = 564;
+       } else {
+               /* TS max packet size stored in bits 1-0 of R01 */
+               chip_cfg2 = em28xx_read_reg(dev, EM28XX_R01_CHIPCFG2);
+               switch (chip_cfg2 & EM28XX_CHIPCFG2_TS_PACKETSIZE_MASK) {
+               case EM28XX_CHIPCFG2_TS_PACKETSIZE_188:
+                       packet_size = 188;
+                       break;
+               case EM28XX_CHIPCFG2_TS_PACKETSIZE_376:
+                       packet_size = 376;
+                       break;
+               case EM28XX_CHIPCFG2_TS_PACKETSIZE_564:
+                       packet_size = 564;
+                       break;
+               case EM28XX_CHIPCFG2_TS_PACKETSIZE_752:
+                       packet_size = 752;
+                       break;
+               }
+       }
+
+       em28xx_coredbg("dvb max packet size=%d\n", packet_size);
+       return packet_size;
+}
+EXPORT_SYMBOL_GPL(em28xx_isoc_dvb_max_packetsize);
+
 /*
  * em28xx_wake_i2c()
  * configure i2c attached devices
index c8188dc2b4b57b353a745a59ad49fd84dd38bf67..e0438acf1224c42285748672ba84668b8a43111a 100644 (file)
@@ -46,7 +46,6 @@ if (debug >= level)                                           \
 } while (0)
 
 #define EM28XX_DVB_NUM_BUFS 5
-#define EM28XX_DVB_MAX_PACKETSIZE 564
 #define EM28XX_DVB_MAX_PACKETS 64
 
 struct em28xx_dvb {
@@ -142,14 +141,17 @@ static int start_streaming(struct em28xx_dvb *dvb)
 {
        int rc;
        struct em28xx *dev = dvb->adapter.priv;
+       int max_dvb_packet_size;
 
        usb_set_interface(dev->udev, 0, 1);
        rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
        if (rc < 0)
                return rc;
 
+       max_dvb_packet_size = em28xx_isoc_dvb_max_packetsize(dev);
+
        return em28xx_init_isoc(dev, EM28XX_DVB_MAX_PACKETS,
-                               EM28XX_DVB_NUM_BUFS, EM28XX_DVB_MAX_PACKETSIZE,
+                               EM28XX_DVB_NUM_BUFS, max_dvb_packet_size,
                                dvb_isoc_copy);
 }
 
index 24e39c56811e98713f8497cca6f46fbd48409209..a2676d63cfd0a673cfd26b6e0ddd593ecab10e5a 100644 (file)
 #define EM28XX_CHIPCFG_AC97                    0x10
 #define EM28XX_CHIPCFG_AUDIOMASK               0x30
 
+#define EM28XX_R01_CHIPCFG2    0x01
+
+/* em28xx Chip Configuration 2 0x01 */
+#define EM28XX_CHIPCFG2_TS_PRESENT             0x10
+#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_MASK   0x0c /* bits 3-2 */
+#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_1MF    0x00
+#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_2MF    0x04
+#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_4MF    0x08
+#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_8MF    0x0c
+#define EM28XX_CHIPCFG2_TS_PACKETSIZE_MASK     0x03 /* bits 0-1 */
+#define EM28XX_CHIPCFG2_TS_PACKETSIZE_188      0x00
+#define EM28XX_CHIPCFG2_TS_PACKETSIZE_376      0x01
+#define EM28XX_CHIPCFG2_TS_PACKETSIZE_564      0x02
+#define EM28XX_CHIPCFG2_TS_PACKETSIZE_752      0x03
+
+
        /* GPIO/GPO registers */
 #define EM2880_R04_GPO 0x04    /* em2880-em2883 only */
 #define EM28XX_R08_GPIO        0x08    /* em2820 or upper */
index 16f4c23f179bb687796c2f06c228ba99b370415b..e801f783bdc3c331ce24ea15c2d80a65f08647a7 100644 (file)
@@ -616,6 +616,7 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets,
                     int num_bufs, int max_pkt_size,
                     int (*isoc_copy) (struct em28xx *dev, struct urb *urb));
 void em28xx_uninit_isoc(struct em28xx *dev);
+int em28xx_isoc_dvb_max_packetsize(struct em28xx *dev);
 int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode);
 int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio);
 void em28xx_wake_i2c(struct em28xx *dev);