V4L/DVB (6692): pvrusb2: Centralize device specific attributes into a single place
authorMike Isely <isely@pobox.com>
Mon, 26 Nov 2007 04:53:12 +0000 (01:53 -0300)
committerMauro Carvalho Chehab <mchehab@infradead.org>
Fri, 25 Jan 2008 21:03:02 +0000 (19:03 -0200)
The pvrusb2 driver currently supports two variants of the Hauppauge
PVR USB2.  However there are other hardware types potentially
supportable, but the driver at the moment is not structured to make it
easy to describe these minor variations.  This changeset is the first
set of changes to make such additional device support possible.
Device attributes are held in several tables all contained within
pvrusb2-devattr.c; all other device-specific driver behavior now
derives from these tables.

Signed-off-by: Mike Isely <isely@pobox.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
drivers/media/video/pvrusb2/pvrusb2-devattr.c [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-devattr.h [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-encoder.c
drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
drivers/media/video/pvrusb2/pvrusb2-hdw.c
drivers/media/video/pvrusb2/pvrusb2-hdw.h
drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
drivers/media/video/pvrusb2/pvrusb2-main.c

diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c
new file mode 100644 (file)
index 0000000..aebcb84
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2007 Mike Isely <isely@pobox.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*
+
+This source file should encompass ALL per-device type information for the
+driver.  To define a new device, add elements to the pvr2_device_table and
+pvr2_device_desc structures.
+
+*/
+
+#include "pvrusb2-devattr.h"
+#include <linux/usb.h>
+
+/* Known major hardware variants, keyed from device ID */
+#define PVR2_HDW_TYPE_29XXX 0
+#define PVR2_HDW_TYPE_24XXX 1
+
+struct usb_device_id pvr2_device_table[] = {
+       [PVR2_HDW_TYPE_29XXX] = { USB_DEVICE(0x2040, 0x2900) },
+       [PVR2_HDW_TYPE_24XXX] = { USB_DEVICE(0x2040, 0x2400) },
+       { }
+};
+
+/* Names of other client modules to request for 24xxx model hardware */
+static const char *pvr2_client_24xxx[] = {
+       "cx25840",
+       "tuner",
+       "wm8775",
+};
+
+/* Names of other client modules to request for 29xxx model hardware */
+static const char *pvr2_client_29xxx[] = {
+       "msp3400",
+       "saa7115",
+       "tuner",
+};
+
+/* Firmware file name(s) for 29xxx devices */
+static const char *pvr2_fw1_names_29xxx[] = {
+               "v4l-pvrusb2-29xxx-01.fw",
+};
+
+/* Firmware file name(s) for 29xxx devices */
+static const char *pvr2_fw1_names_24xxx[] = {
+               "v4l-pvrusb2-24xxx-01.fw",
+};
+
+const struct pvr2_device_desc pvr2_device_descriptions[] = {
+       [PVR2_HDW_TYPE_29XXX] = {
+               .description = "WinTV PVR USB2 Model Category 29xxxx",
+               .shortname = "29xxx",
+               .client_modules.lst = pvr2_client_29xxx,
+               .client_modules.cnt = ARRAY_SIZE(pvr2_client_29xxx),
+               .fx2_firmware.lst = pvr2_fw1_names_29xxx,
+               .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_29xxx),
+       },
+       [PVR2_HDW_TYPE_24XXX] = {
+               .description = "WinTV PVR USB2 Model Category 24xxxx",
+               .shortname = "24xxx",
+               .client_modules.lst = pvr2_client_24xxx,
+               .client_modules.cnt = ARRAY_SIZE(pvr2_client_24xxx),
+               .fx2_firmware.lst = pvr2_fw1_names_24xxx,
+               .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_24xxx),
+               .flag_has_cx25840 = !0,
+               .flag_has_wm8775 = !0,
+       },
+};
+
+const unsigned int pvr2_device_count = ARRAY_SIZE(pvr2_device_descriptions);
+
+MODULE_DEVICE_TABLE(usb, pvr2_device_table);
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/drivers/media/video/pvrusb2/pvrusb2-devattr.h
new file mode 100644 (file)
index 0000000..6576aef
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef __PVRUSB2_DEVATTR_H
+#define __PVRUSB2_DEVATTR_H
+
+#include <linux/mod_devicetable.h>
+
+/*
+
+  This header defines structures used to describe attributes of a device.
+
+*/
+
+
+struct pvr2_string_table {
+       const char **lst;
+       unsigned int cnt;
+};
+
+
+/* This describes a particular hardware type (except for the USB device ID
+   which must live in a separate structure due to environmental
+   constraints).  See the top of pvrusb2-hdw.c for where this is
+   instantiated. */
+struct pvr2_device_desc {
+       /* Single line text description of hardware */
+       const char *description;
+
+       /* Single token identifier for hardware */
+       const char *shortname;
+
+       /* List of additional client modules we need to load */
+       struct pvr2_string_table client_modules;
+
+       /* List of FX2 firmware file names we should search; if empty then
+          FX2 firmware check / load is skipped and we assume the device
+          was initialized from internal ROM. */
+       struct pvr2_string_table fx2_firmware;
+
+       /* If set, we don't bother trying to load cx23416 firmware. */
+       char flag_skip_cx23416_firmware;
+
+       /* Device does not require a powerup command to be issued. */
+       char flag_no_powerup;
+
+       /* Device has a cx25840 - this enables special additional logic to
+          handle it. */
+       char flag_has_cx25840;
+
+       /* Device has a wm8775 - this enables special additional logic to
+          ensure that it is found. */
+       char flag_has_wm8775;
+};
+
+extern const struct pvr2_device_desc pvr2_device_descriptions[];
+extern struct usb_device_id pvr2_device_table[];
+extern const unsigned int pvr2_device_count;
+
+#endif /* __PVRUSB2_HDW_INTERNAL_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
index 5ca548c..4271b41 100644 (file)
@@ -370,13 +370,13 @@ static int pvr2_encoder_prep_config(struct pvr2_hdw *hdw)
 
        /* This ENC_MISC(3,encMisc3Arg) command is critical - without
           it there will eventually be video corruption.  Also, the
-          29xxx case is strange - the Windows driver is passing 1
-          regardless of device type but if we have 1 for 29xxx device
-          the video turns sluggish.  */
-       switch (hdw->hdw_type) {
-       case PVR2_HDW_TYPE_24XXX: encMisc3Arg = 1; break;
-       case PVR2_HDW_TYPE_29XXX: encMisc3Arg = 0; break;
-       default: break;
+          saa7115 case is strange - the Windows driver is passing 1
+          regardless of device type but if we have 1 for saa7115
+          devices the video turns sluggish.  */
+       if (hdw->hdw_desc->flag_has_cx25840) {
+               encMisc3Arg = 1;
+       } else {
+               encMisc3Arg = 0;
        }
        ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 3,
                                 encMisc3Arg,0,0);
@@ -434,7 +434,7 @@ int pvr2_encoder_configure(struct pvr2_hdw *hdw)
 
        /* saa7115: 0xf0 */
        val = 0xf0;
-       if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) {
+       if (hdw->hdw_desc->flag_has_cx25840) {
                /* ivtv cx25840: 0x140 */
                val = 0x140;
        }
index 8ee4549..8c2d222 100644 (file)
@@ -40,6 +40,7 @@
 #include "pvrusb2-hdw.h"
 #include "pvrusb2-io.h"
 #include <media/cx2341x.h>
+#include "pvrusb2-devattr.h"
 
 /* Legal values for PVR2_CID_HSM */
 #define PVR2_CVAL_HSM_FAIL 0
@@ -162,10 +163,6 @@ struct pvr2_decoder_ctrl {
 #define FW1_STATE_RELOAD 3
 #define FW1_STATE_OK 4
 
-/* Known major hardware variants, keyed from device ID */
-#define PVR2_HDW_TYPE_29XXX 0
-#define PVR2_HDW_TYPE_24XXX 1
-
 typedef int (*pvr2_i2c_func)(struct pvr2_hdw *,u8,u8 *,u16,u8 *, u16);
 #define PVR2_I2C_FUNC_CNT 128
 
@@ -179,6 +176,7 @@ struct pvr2_hdw {
 
        /* Device type, one of PVR2_HDW_TYPE_xxxxx */
        unsigned int hdw_type;
+       const struct pvr2_device_desc *hdw_desc;
 
        /* Kernel worker thread handling */
        struct workqueue_struct *workqueue;
index 4e55a2a..c562084 100644 (file)
 #define TV_MIN_FREQ     55250000L
 #define TV_MAX_FREQ    850000000L
 
-struct usb_device_id pvr2_device_table[] = {
-       [PVR2_HDW_TYPE_29XXX] = { USB_DEVICE(0x2040, 0x2900) },
-       [PVR2_HDW_TYPE_24XXX] = { USB_DEVICE(0x2040, 0x2400) },
-       { }
-};
-
-MODULE_DEVICE_TABLE(usb, pvr2_device_table);
-
-static const char *pvr2_device_names[] = {
-       [PVR2_HDW_TYPE_29XXX] = "WinTV PVR USB2 Model Category 29xxxx",
-       [PVR2_HDW_TYPE_24XXX] = "WinTV PVR USB2 Model Category 24xxxx",
-};
-
-struct pvr2_string_table {
-       const char **lst;
-       unsigned int cnt;
-};
-
-// Names of other client modules to request for 24xxx model hardware
-static const char *pvr2_client_24xxx[] = {
-       "cx25840",
-       "tuner",
-       "wm8775",
-};
-
-// Names of other client modules to request for 29xxx model hardware
-static const char *pvr2_client_29xxx[] = {
-       "msp3400",
-       "saa7115",
-       "tuner",
-};
-
-static struct pvr2_string_table pvr2_client_lists[] = {
-       [PVR2_HDW_TYPE_29XXX] = {
-               pvr2_client_29xxx, ARRAY_SIZE(pvr2_client_29xxx)
-       },
-       [PVR2_HDW_TYPE_24XXX] = {
-               pvr2_client_24xxx, ARRAY_SIZE(pvr2_client_24xxx)
-       },
-};
-
 static struct pvr2_hdw *unit_pointers[PVR_NUM] = {[ 0 ... PVR_NUM-1 ] = NULL};
 static DEFINE_MUTEX(pvr2_unit_mtx);
 
@@ -394,8 +353,8 @@ static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp)
 
 static int ctrl_vres_min_get(struct pvr2_ctrl *cptr,int *vp)
 {
-       /* Actual minimum depends on device type. */
-       if (cptr->hdw->hdw_type == PVR2_HDW_TYPE_24XXX) {
+       /* Actual minimum depends on device digitizer type. */
+       if (cptr->hdw->hdw_desc->flag_has_cx25840) {
                *vp = 75;
        } else {
                *vp = 17;
@@ -1131,23 +1090,8 @@ static int pvr2_upload_firmware1(struct pvr2_hdw *hdw)
        unsigned int pipe;
        int ret;
        u16 address;
-       static const char *fw_files_29xxx[] = {
-               "v4l-pvrusb2-29xxx-01.fw",
-       };
-       static const char *fw_files_24xxx[] = {
-               "v4l-pvrusb2-24xxx-01.fw",
-       };
-       static const struct pvr2_string_table fw_file_defs[] = {
-               [PVR2_HDW_TYPE_29XXX] = {
-                       fw_files_29xxx, ARRAY_SIZE(fw_files_29xxx)
-               },
-               [PVR2_HDW_TYPE_24XXX] = {
-                       fw_files_24xxx, ARRAY_SIZE(fw_files_24xxx)
-               },
-       };
 
-       if ((hdw->hdw_type >= ARRAY_SIZE(fw_file_defs)) ||
-           (!fw_file_defs[hdw->hdw_type].lst)) {
+       if (!hdw->hdw_desc->fx2_firmware.cnt) {
                hdw->fw1_state = FW1_STATE_OK;
                return 0;
        }
@@ -1157,8 +1101,8 @@ static int pvr2_upload_firmware1(struct pvr2_hdw *hdw)
        trace_firmware("pvr2_upload_firmware1");
 
        ret = pvr2_locate_firmware(hdw,&fw_entry,"fx2 controller",
-                                  fw_file_defs[hdw->hdw_type].cnt,
-                                  fw_file_defs[hdw->hdw_type].lst);
+                                  hdw->hdw_desc->fx2_firmware.cnt,
+                                  hdw->hdw_desc->fx2_firmware.lst);
        if (ret < 0) {
                if (ret == -ENOENT) hdw->fw1_state = FW1_STATE_MISSING;
                return ret;
@@ -1233,8 +1177,7 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
                CX2341X_FIRM_ENC_FILENAME,
        };
 
-       if ((hdw->hdw_type != PVR2_HDW_TYPE_29XXX) &&
-           (hdw->hdw_type != PVR2_HDW_TYPE_24XXX)) {
+       if (hdw->hdw_desc->flag_skip_cx23416_firmware) {
                return 0;
        }
 
@@ -1652,8 +1595,7 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
        unsigned int idx;
        struct pvr2_ctrl *cptr;
        int reloadFl = 0;
-       if ((hdw->hdw_type == PVR2_HDW_TYPE_29XXX) ||
-           (hdw->hdw_type == PVR2_HDW_TYPE_24XXX)) {
+       if (hdw->hdw_desc->fx2_firmware.cnt) {
                if (!reloadFl) {
                        reloadFl =
                                (hdw->usb_intf->cur_altsetting->desc.bNumEndpoints
@@ -1689,17 +1631,11 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
        }
        if (!pvr2_hdw_dev_ok(hdw)) return;
 
-       if (hdw->hdw_type < ARRAY_SIZE(pvr2_client_lists)) {
-               for (idx = 0;
-                    idx < pvr2_client_lists[hdw->hdw_type].cnt;
-                    idx++) {
-                       request_module(
-                               pvr2_client_lists[hdw->hdw_type].lst[idx]);
-               }
+       for (idx = 0; idx < hdw->hdw_desc->client_modules.cnt; idx++) {
+               request_module(hdw->hdw_desc->client_modules.lst[idx]);
        }
 
-       if ((hdw->hdw_type == PVR2_HDW_TYPE_29XXX) ||
-           (hdw->hdw_type == PVR2_HDW_TYPE_24XXX)) {
+       if (!hdw->hdw_desc->flag_no_powerup) {
                pvr2_hdw_cmd_powerup(hdw);
                if (!pvr2_hdw_dev_ok(hdw)) return;
        }
@@ -1857,20 +1793,22 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
        unsigned int hdw_type;
        int valid_std_mask;
        struct pvr2_ctrl *cptr;
+       const struct pvr2_device_desc *hdw_desc;
        __u8 ifnum;
        struct v4l2_queryctrl qctrl;
        struct pvr2_ctl_info *ciptr;
 
        hdw_type = devid - pvr2_device_table;
-       if (hdw_type >= ARRAY_SIZE(pvr2_device_names)) {
+       if (hdw_type >= pvr2_device_count) {
                pvr2_trace(PVR2_TRACE_ERROR_LEGS,
                           "Bogus device type of %u reported",hdw_type);
                return NULL;
        }
+       hdw_desc = pvr2_device_descriptions + hdw_type;
 
        hdw = kzalloc(sizeof(*hdw),GFP_KERNEL);
        pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_create: hdw=%p, type \"%s\"",
-                  hdw,pvr2_device_names[hdw_type]);
+                  hdw,hdw_desc->description);
        if (!hdw) goto fail;
 
        init_timer(&hdw->quiescent_timer);
@@ -1894,6 +1832,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
                                GFP_KERNEL);
        if (!hdw->controls) goto fail;
        hdw->hdw_type = hdw_type;
+       hdw->hdw_desc = hdw_desc;
        for (idx = 0; idx < hdw->control_cnt; idx++) {
                cptr = hdw->controls + idx;
                cptr->hdw = hdw;
index 383685f..205fa03 100644 (file)
@@ -311,9 +311,6 @@ void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw);
    a debugging aid. */
 int pvr2_upload_firmware2(struct pvr2_hdw *hdw);
 
-/* List of device types that we can match */
-extern struct usb_device_id pvr2_device_table[];
-
 #endif /* __PVRUSB2_HDW_H */
 
 /*
index f8b7bd1..7721ec8 100644 (file)
@@ -980,14 +980,16 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
                printk(KERN_INFO "%s: IR disabled\n",hdw->name);
                hdw->i2c_func[0x18] = i2c_black_hole;
        } else if (ir_mode[hdw->unit_number] == 1) {
-               if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) {
+               if (hdw->hdw_desc->flag_has_cx25840) {
                        hdw->i2c_func[0x18] = i2c_24xxx_ir;
                }
        }
-       if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) {
-               hdw->i2c_func[0x1b] = i2c_hack_wm8775;
+       if (hdw->hdw_desc->flag_has_cx25840) {
                hdw->i2c_func[0x44] = i2c_hack_cx25840;
        }
+       if (hdw->hdw_desc->flag_has_wm8775) {
+               hdw->i2c_func[0x1b] = i2c_hack_wm8775;
+       }
 
        // Configure the adapter and set up everything else related to it.
        memcpy(&hdw->i2c_adap,&pvr2_i2c_adap_template,sizeof(hdw->i2c_adap));
index 11b3b2e..a837073 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/videodev2.h>
 
 #include "pvrusb2-hdw.h"
+#include "pvrusb2-devattr.h"
 #include "pvrusb2-context.h"
 #include "pvrusb2-debug.h"
 #include "pvrusb2-v4l2.h"