V4L/DVB (6210): pvrusb2: Do a far better job at setting the default initial video...
authorMike Isely <isely@pobox.com>
Sun, 9 Sep 2007 01:28:51 +0000 (22:28 -0300)
committerMauro Carvalho Chehab <mchehab@infradead.org>
Wed, 10 Oct 2007 01:14:34 +0000 (22:14 -0300)
The v4l tveeprom logic tells us what video standards are supported by
the hardware, however it doesn't directly tell us what should be the
preferred initial standard.  For example "NTSC/NTSC-J" devices are
reported by tveeprom as support NTSC-M and PAL-M, and while that might
be true, in the vast majority of cases NTSC-M is really what the user
is going to want.  However the driver previously just arbitrarily
picked the "lowest numbered" standard as the initial default, which in
that case would have been PAL-M.  (And making matters more confusing -
this only caused real problems on 24xxx devices because the saa7115 on
29xxx seems to autodetect the right answer anyway.)  This change
implements an algorithm that uses the set of "supported" standards as
a hint to decide on the initial standard.  This algorithm ONLY comes
into play if the driver isn't specifically told what to do; said
another way - the user can always still change the standard via the
sysfs interface, via the usual V4L methods, or even specified as a
module parameter.  The idea here is only to pick a better starting
point if the user (or app) doesn't otherwise do something to set the
standard; otherwise this change has no real impact.

Signed-off-by: Mike Isely <isely@pobox.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
drivers/media/video/pvrusb2/pvrusb2-hdw.c

index c8ee379..20dc573 100644 (file)
@@ -1694,6 +1694,44 @@ static int pvr2_hdw_check_firmware(struct pvr2_hdw *hdw)
        return result == 0;
 }
 
+struct pvr2_std_hack {
+       v4l2_std_id pat;  /* Pattern to match */
+       v4l2_std_id msk;  /* Which bits we care about */
+       v4l2_std_id std;  /* What additional standards or default to set */
+};
+
+/* This data structure labels specific combinations of standards from
+   tveeprom that we'll try to recognize.  If we recognize one, then assume
+   a specified default standard to use.  This is here because tveeprom only
+   tells us about available standards not the intended default standard (if
+   any) for the device in question.  We guess the default based on what has
+   been reported as available.  Note that this is only for guessing a
+   default - which can always be overridden explicitly - and if the user
+   has otherwise named a default then that default will always be used in
+   place of this table. */
+const static struct pvr2_std_hack std_eeprom_maps[] = {
+       {       /* PAL(B/G) */
+               .pat = V4L2_STD_B|V4L2_STD_GH,
+               .std = V4L2_STD_PAL_B|V4L2_STD_PAL_B1|V4L2_STD_PAL_G,
+       },
+       {       /* NTSC(M) */
+               .pat = V4L2_STD_MN,
+               .std = V4L2_STD_NTSC_M,
+       },
+       {       /* PAL(I) */
+               .pat = V4L2_STD_PAL_I,
+               .std = V4L2_STD_PAL_I,
+       },
+       {       /* SECAM(L/L') */
+               .pat = V4L2_STD_SECAM_L|V4L2_STD_SECAM_LC,
+               .std = V4L2_STD_SECAM_L|V4L2_STD_SECAM_LC,
+       },
+       {       /* PAL(D/D1/K) */
+               .pat = V4L2_STD_DK,
+               .std = V4L2_STD_PAL_D/V4L2_STD_PAL_D1|V4L2_STD_PAL_K,
+       },
+};
+
 static void pvr2_hdw_setup_std(struct pvr2_hdw *hdw)
 {
        char buf[40];
@@ -1732,6 +1770,27 @@ static void pvr2_hdw_setup_std(struct pvr2_hdw *hdw)
                return;
        }
 
+       {
+               unsigned int idx;
+               for (idx = 0; idx < ARRAY_SIZE(std_eeprom_maps); idx++) {
+                       if (std_eeprom_maps[idx].msk ?
+                           ((std_eeprom_maps[idx].pat ^
+                            hdw->std_mask_eeprom) &
+                            std_eeprom_maps[idx].msk) :
+                           (std_eeprom_maps[idx].pat !=
+                            hdw->std_mask_eeprom)) continue;
+                       bcnt = pvr2_std_id_to_str(buf,sizeof(buf),
+                                                 std_eeprom_maps[idx].std);
+                       pvr2_trace(PVR2_TRACE_INIT,
+                                  "Initial video standard guessed as %.*s",
+                                  bcnt,buf);
+                       hdw->std_mask_cur = std_eeprom_maps[idx].std;
+                       hdw->std_dirty = !0;
+                       pvr2_hdw_internal_find_stdenum(hdw);
+                       return;
+               }
+       }
+
        if (hdw->std_enum_cnt > 1) {
                // Autoselect the first listed standard
                hdw->std_enum_cur = 1;