V4L/DVB (13092): cx25840: Improvements to the cx23885/7/8 chip detection mechanism.
authorSteven Toth <stoth@kernellabs.com>
Sun, 27 Sep 2009 18:54:47 +0000 (15:54 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Sat, 5 Dec 2009 20:40:19 +0000 (18:40 -0200)
The prior mechanism wasn't reliable with the cx23887. This new mechanism
tests correctly against cx23885, 7 and 8 based products.

Signed-off-by: Steven Toth <stoth@kernellabs.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/cx25840/cx25840-core.c

index 56ead3d..904e9a5 100644 (file)
@@ -1598,14 +1598,29 @@ static u32 get_cx2388x_ident(struct i2c_client *client)
        /* Come out of digital power down */
        cx25840_write(client, 0x000, 0);
 
+       /* Detecting whether the part is cx23885/7/8 is more
+        * difficult than it needs to be. No ID register. Instead we
+        * probe certain registers indicated in the datasheets to look
+        * for specific defaults that differ between the silicon designs. */
+
+       /* It's either 885/7 if the IR Tx Clk Divider register exists */
        if (cx25840_read4(client, 0x204) & 0xffff) {
-               /* IR Tx Clk Divider register exists; chip must be a CX23885 */
-               ret = V4L2_IDENT_CX23885_AV;
+               /* CX23885 returns bogus repetitive byte values for the DIF,
+                * which doesn't exist for it. (Ex. 8a8a8a8a or 31313131) */
+               ret = cx25840_read4(client, 0x300);
+               if (((ret & 0xffff0000) >> 16) == (ret & 0xffff)) {
+                       /* No DIF */
+                       ret = V4L2_IDENT_CX23885_AV;
+               } else {
+                       /* CX23887 has a broken DIF, but the registers
+                        * appear valid (but unsed), good enough to detect. */
+                       ret = V4L2_IDENT_CX23887_AV;
+               }
        } else if (cx25840_read4(client, 0x300) & 0x0fffffff) {
                /* DIF PLL Freq Word reg exists; chip must be a CX23888 */
                ret = V4L2_IDENT_CX23888_AV;
        } else {
-               /* A CX23887 A/V core has neither IR nor DIF */
+               v4l_err(client, "Unable to detect h/w, assuming cx23887\n");
                ret = V4L2_IDENT_CX23887_AV;
        }