Commit 989eb154 authored by Mike Isely's avatar Mike Isely Committed by Mauro Carvalho Chehab

V4L/DVB (6692): pvrusb2: Centralize device specific attributes into a single place

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: default avatarMike Isely <isely@pobox.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent 681c7399
/*
*
* $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: ***
*/
/*
*
* $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: ***
*/
...@@ -370,13 +370,13 @@ static int pvr2_encoder_prep_config(struct pvr2_hdw *hdw) ...@@ -370,13 +370,13 @@ static int pvr2_encoder_prep_config(struct pvr2_hdw *hdw)
/* This ENC_MISC(3,encMisc3Arg) command is critical - without /* This ENC_MISC(3,encMisc3Arg) command is critical - without
it there will eventually be video corruption. Also, the it there will eventually be video corruption. Also, the
29xxx case is strange - the Windows driver is passing 1 saa7115 case is strange - the Windows driver is passing 1
regardless of device type but if we have 1 for 29xxx device regardless of device type but if we have 1 for saa7115
the video turns sluggish. */ devices the video turns sluggish. */
switch (hdw->hdw_type) { if (hdw->hdw_desc->flag_has_cx25840) {
case PVR2_HDW_TYPE_24XXX: encMisc3Arg = 1; break; encMisc3Arg = 1;
case PVR2_HDW_TYPE_29XXX: encMisc3Arg = 0; break; } else {
default: break; encMisc3Arg = 0;
} }
ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 3, ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 3,
encMisc3Arg,0,0); encMisc3Arg,0,0);
...@@ -434,7 +434,7 @@ int pvr2_encoder_configure(struct pvr2_hdw *hdw) ...@@ -434,7 +434,7 @@ int pvr2_encoder_configure(struct pvr2_hdw *hdw)
/* saa7115: 0xf0 */ /* saa7115: 0xf0 */
val = 0xf0; val = 0xf0;
if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) { if (hdw->hdw_desc->flag_has_cx25840) {
/* ivtv cx25840: 0x140 */ /* ivtv cx25840: 0x140 */
val = 0x140; val = 0x140;
} }
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include "pvrusb2-hdw.h" #include "pvrusb2-hdw.h"
#include "pvrusb2-io.h" #include "pvrusb2-io.h"
#include <media/cx2341x.h> #include <media/cx2341x.h>
#include "pvrusb2-devattr.h"
/* Legal values for PVR2_CID_HSM */ /* Legal values for PVR2_CID_HSM */
#define PVR2_CVAL_HSM_FAIL 0 #define PVR2_CVAL_HSM_FAIL 0
...@@ -162,10 +163,6 @@ struct pvr2_decoder_ctrl { ...@@ -162,10 +163,6 @@ struct pvr2_decoder_ctrl {
#define FW1_STATE_RELOAD 3 #define FW1_STATE_RELOAD 3
#define FW1_STATE_OK 4 #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); typedef int (*pvr2_i2c_func)(struct pvr2_hdw *,u8,u8 *,u16,u8 *, u16);
#define PVR2_I2C_FUNC_CNT 128 #define PVR2_I2C_FUNC_CNT 128
...@@ -179,6 +176,7 @@ struct pvr2_hdw { ...@@ -179,6 +176,7 @@ struct pvr2_hdw {
/* Device type, one of PVR2_HDW_TYPE_xxxxx */ /* Device type, one of PVR2_HDW_TYPE_xxxxx */
unsigned int hdw_type; unsigned int hdw_type;
const struct pvr2_device_desc *hdw_desc;
/* Kernel worker thread handling */ /* Kernel worker thread handling */
struct workqueue_struct *workqueue; struct workqueue_struct *workqueue;
......
...@@ -41,47 +41,6 @@ ...@@ -41,47 +41,6 @@
#define TV_MIN_FREQ 55250000L #define TV_MIN_FREQ 55250000L
#define TV_MAX_FREQ 850000000L #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 struct pvr2_hdw *unit_pointers[PVR_NUM] = {[ 0 ... PVR_NUM-1 ] = NULL};
static DEFINE_MUTEX(pvr2_unit_mtx); static DEFINE_MUTEX(pvr2_unit_mtx);
...@@ -394,8 +353,8 @@ static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp) ...@@ -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) static int ctrl_vres_min_get(struct pvr2_ctrl *cptr,int *vp)
{ {
/* Actual minimum depends on device type. */ /* Actual minimum depends on device digitizer type. */
if (cptr->hdw->hdw_type == PVR2_HDW_TYPE_24XXX) { if (cptr->hdw->hdw_desc->flag_has_cx25840) {
*vp = 75; *vp = 75;
} else { } else {
*vp = 17; *vp = 17;
...@@ -1131,23 +1090,8 @@ static int pvr2_upload_firmware1(struct pvr2_hdw *hdw) ...@@ -1131,23 +1090,8 @@ static int pvr2_upload_firmware1(struct pvr2_hdw *hdw)
unsigned int pipe; unsigned int pipe;
int ret; int ret;
u16 address; 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)) || if (!hdw->hdw_desc->fx2_firmware.cnt) {
(!fw_file_defs[hdw->hdw_type].lst)) {
hdw->fw1_state = FW1_STATE_OK; hdw->fw1_state = FW1_STATE_OK;
return 0; return 0;
} }
...@@ -1157,8 +1101,8 @@ static int pvr2_upload_firmware1(struct pvr2_hdw *hdw) ...@@ -1157,8 +1101,8 @@ static int pvr2_upload_firmware1(struct pvr2_hdw *hdw)
trace_firmware("pvr2_upload_firmware1"); trace_firmware("pvr2_upload_firmware1");
ret = pvr2_locate_firmware(hdw,&fw_entry,"fx2 controller", ret = pvr2_locate_firmware(hdw,&fw_entry,"fx2 controller",
fw_file_defs[hdw->hdw_type].cnt, hdw->hdw_desc->fx2_firmware.cnt,
fw_file_defs[hdw->hdw_type].lst); hdw->hdw_desc->fx2_firmware.lst);
if (ret < 0) { if (ret < 0) {
if (ret == -ENOENT) hdw->fw1_state = FW1_STATE_MISSING; if (ret == -ENOENT) hdw->fw1_state = FW1_STATE_MISSING;
return ret; return ret;
...@@ -1233,8 +1177,7 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw) ...@@ -1233,8 +1177,7 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
CX2341X_FIRM_ENC_FILENAME, CX2341X_FIRM_ENC_FILENAME,
}; };
if ((hdw->hdw_type != PVR2_HDW_TYPE_29XXX) && if (hdw->hdw_desc->flag_skip_cx23416_firmware) {
(hdw->hdw_type != PVR2_HDW_TYPE_24XXX)) {
return 0; return 0;
} }
...@@ -1652,8 +1595,7 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) ...@@ -1652,8 +1595,7 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
unsigned int idx; unsigned int idx;
struct pvr2_ctrl *cptr; struct pvr2_ctrl *cptr;
int reloadFl = 0; int reloadFl = 0;
if ((hdw->hdw_type == PVR2_HDW_TYPE_29XXX) || if (hdw->hdw_desc->fx2_firmware.cnt) {
(hdw->hdw_type == PVR2_HDW_TYPE_24XXX)) {
if (!reloadFl) { if (!reloadFl) {
reloadFl = reloadFl =
(hdw->usb_intf->cur_altsetting->desc.bNumEndpoints (hdw->usb_intf->cur_altsetting->desc.bNumEndpoints
...@@ -1689,17 +1631,11 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) ...@@ -1689,17 +1631,11 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
} }
if (!pvr2_hdw_dev_ok(hdw)) return; if (!pvr2_hdw_dev_ok(hdw)) return;
if (hdw->hdw_type < ARRAY_SIZE(pvr2_client_lists)) { for (idx = 0; idx < hdw->hdw_desc->client_modules.cnt; idx++) {
for (idx = 0; request_module(hdw->hdw_desc->client_modules.lst[idx]);
idx < pvr2_client_lists[hdw->hdw_type].cnt;
idx++) {
request_module(
pvr2_client_lists[hdw->hdw_type].lst[idx]);
}
} }
if ((hdw->hdw_type == PVR2_HDW_TYPE_29XXX) || if (!hdw->hdw_desc->flag_no_powerup) {
(hdw->hdw_type == PVR2_HDW_TYPE_24XXX)) {
pvr2_hdw_cmd_powerup(hdw); pvr2_hdw_cmd_powerup(hdw);
if (!pvr2_hdw_dev_ok(hdw)) return; if (!pvr2_hdw_dev_ok(hdw)) return;
} }
...@@ -1857,20 +1793,22 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, ...@@ -1857,20 +1793,22 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
unsigned int hdw_type; unsigned int hdw_type;
int valid_std_mask; int valid_std_mask;
struct pvr2_ctrl *cptr; struct pvr2_ctrl *cptr;
const struct pvr2_device_desc *hdw_desc;
__u8 ifnum; __u8 ifnum;
struct v4l2_queryctrl qctrl; struct v4l2_queryctrl qctrl;
struct pvr2_ctl_info *ciptr; struct pvr2_ctl_info *ciptr;
hdw_type = devid - pvr2_device_table; 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, pvr2_trace(PVR2_TRACE_ERROR_LEGS,
"Bogus device type of %u reported",hdw_type); "Bogus device type of %u reported",hdw_type);
return NULL; return NULL;
} }
hdw_desc = pvr2_device_descriptions + hdw_type;
hdw = kzalloc(sizeof(*hdw),GFP_KERNEL); hdw = kzalloc(sizeof(*hdw),GFP_KERNEL);
pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_create: hdw=%p, type \"%s\"", 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; if (!hdw) goto fail;
init_timer(&hdw->quiescent_timer); init_timer(&hdw->quiescent_timer);
...@@ -1894,6 +1832,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, ...@@ -1894,6 +1832,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
GFP_KERNEL); GFP_KERNEL);
if (!hdw->controls) goto fail; if (!hdw->controls) goto fail;
hdw->hdw_type = hdw_type; hdw->hdw_type = hdw_type;
hdw->hdw_desc = hdw_desc;
for (idx = 0; idx < hdw->control_cnt; idx++) { for (idx = 0; idx < hdw->control_cnt; idx++) {
cptr = hdw->controls + idx; cptr = hdw->controls + idx;
cptr->hdw = hdw; cptr->hdw = hdw;
......
...@@ -311,9 +311,6 @@ void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw); ...@@ -311,9 +311,6 @@ void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw);
a debugging aid. */ a debugging aid. */
int pvr2_upload_firmware2(struct pvr2_hdw *hdw); 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 */ #endif /* __PVRUSB2_HDW_H */
/* /*
......
...@@ -980,14 +980,16 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw) ...@@ -980,14 +980,16 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
printk(KERN_INFO "%s: IR disabled\n",hdw->name); printk(KERN_INFO "%s: IR disabled\n",hdw->name);
hdw->i2c_func[0x18] = i2c_black_hole; hdw->i2c_func[0x18] = i2c_black_hole;
} else if (ir_mode[hdw->unit_number] == 1) { } 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; hdw->i2c_func[0x18] = i2c_24xxx_ir;
} }
} }
if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) { if (hdw->hdw_desc->flag_has_cx25840) {
hdw->i2c_func[0x1b] = i2c_hack_wm8775;
hdw->i2c_func[0x44] = i2c_hack_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. // Configure the adapter and set up everything else related to it.
memcpy(&hdw->i2c_adap,&pvr2_i2c_adap_template,sizeof(hdw->i2c_adap)); memcpy(&hdw->i2c_adap,&pvr2_i2c_adap_template,sizeof(hdw->i2c_adap));
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include "pvrusb2-hdw.h" #include "pvrusb2-hdw.h"
#include "pvrusb2-devattr.h"
#include "pvrusb2-context.h" #include "pvrusb2-context.h"
#include "pvrusb2-debug.h" #include "pvrusb2-debug.h"
#include "pvrusb2-v4l2.h" #include "pvrusb2-v4l2.h"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment