aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/pvrusb2
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/pvrusb2')
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-devattr.c6
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-devattr.h23
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h3
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw.c74
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-i2c-core.c51
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-sysfs.c22
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-v4l2.c6
7 files changed, 110 insertions, 75 deletions
diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c
index 1cb6a260e8b0..336a20eded0f 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c
@@ -71,6 +71,7 @@ static const struct pvr2_device_desc pvr2_device_29xxx = {
.flag_has_svideo = !0,
.signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
.led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
+ .ir_scheme = PVR2_IR_SCHEME_29XXX,
};
@@ -284,6 +285,11 @@ static struct tda10048_config hauppauge_tda10048_config = {
.output_mode = TDA10048_PARALLEL_OUTPUT,
.fwbulkwritelen = TDA10048_BULKWRITE_50,
.inversion = TDA10048_INVERSION_ON,
+ .dtv6_if_freq_khz = TDA10048_IF_3300,
+ .dtv7_if_freq_khz = TDA10048_IF_3800,
+ .dtv8_if_freq_khz = TDA10048_IF_4300,
+ .clk_freq_khz = TDA10048_CLK_16000,
+ .disable_gate_access = 1,
};
static struct tda829x_config tda829x_no_probe = {
diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/drivers/media/video/pvrusb2/pvrusb2-devattr.h
index 3e553389cbc3..ea04ecf8aa39 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-devattr.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.h
@@ -69,6 +69,7 @@ struct pvr2_string_table {
#define PVR2_ROUTING_SCHEME_HAUPPAUGE 0
#define PVR2_ROUTING_SCHEME_GOTVIEW 1
#define PVR2_ROUTING_SCHEME_ONAIR 2
+#define PVR2_ROUTING_SCHEME_AV400 3
#define PVR2_DIGITAL_SCHEME_NONE 0
#define PVR2_DIGITAL_SCHEME_HAUPPAUGE 1
@@ -78,8 +79,10 @@ struct pvr2_string_table {
#define PVR2_LED_SCHEME_HAUPPAUGE 1
#define PVR2_IR_SCHEME_NONE 0
-#define PVR2_IR_SCHEME_24XXX 1
-#define PVR2_IR_SCHEME_ZILOG 2
+#define PVR2_IR_SCHEME_24XXX 1 /* FX2-controlled IR */
+#define PVR2_IR_SCHEME_ZILOG 2 /* HVR-1950 style (must be taken out of reset) */
+#define PVR2_IR_SCHEME_24XXX_MCE 3 /* 24xxx MCE device */
+#define PVR2_IR_SCHEME_29XXX 4 /* Original 29xxx device */
/* This describes a particular hardware type (except for the USB device ID
which must live in a separate structure due to environmental
@@ -162,19 +165,9 @@ struct pvr2_device_desc {
ensure that it is found. */
unsigned int flag_has_wm8775:1;
- /* Indicate any specialized IR scheme that might need to be
- supported by this driver. If not set, then it is assumed that
- IR can work without help from the driver (which is frequently
- the case). This is otherwise set to one of
- PVR2_IR_SCHEME_xxxx. For "xxxx", the value "24XXX" indicates a
- Hauppauge 24xxx class device which has an FPGA-hosted IR
- receiver that can only be reached via FX2 command codes. In
- that case the pvrusb2 driver will emulate the behavior of the
- older 29xxx device's IR receiver (a "virtual" I2C chip) in terms
- of those command codes. For the value "ZILOG", we're dealing
- with an IR chip that must be taken out of reset via another FX2
- command code (which is the case for HVR-1950 devices). */
- unsigned int ir_scheme:2;
+ /* Indicate IR scheme of hardware. If not set, then it is assumed
+ that IR can work without any help from the driver. */
+ unsigned int ir_scheme:3;
/* These bits define which kinds of sources the device can handle.
Note: Digital tuner presence is inferred by the
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
index 5d75eb5211b1..5b152ff20bd0 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
@@ -200,6 +200,9 @@ struct pvr2_hdw {
int i2c_cx25840_hack_state;
int i2c_linked;
+ /* IR related */
+ unsigned int ir_scheme_active; /* IR scheme as seen from the outside */
+
/* Frequency table */
unsigned int freqTable[FREQTABLE_SIZE];
unsigned int freqProgSlot;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
index add3395d3248..0c745b142fb7 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -142,6 +142,15 @@ static const unsigned char *module_i2c_addresses[] = {
};
+static const char *ir_scheme_names[] = {
+ [PVR2_IR_SCHEME_NONE] = "none",
+ [PVR2_IR_SCHEME_29XXX] = "29xxx",
+ [PVR2_IR_SCHEME_24XXX] = "24xxx (29xxx emulation)",
+ [PVR2_IR_SCHEME_24XXX_MCE] = "24xxx (MCE device)",
+ [PVR2_IR_SCHEME_ZILOG] = "Zilog",
+};
+
+
/* Define the list of additional controls we'll dynamically construct based
on query of the cx2341x module. */
struct pvr2_mpeg_ids {
@@ -2170,7 +2179,7 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
}
/* Take the IR chip out of reset, if appropriate */
- if (hdw->hdw_desc->ir_scheme == PVR2_IR_SCHEME_ZILOG) {
+ if (hdw->ir_scheme_active == PVR2_IR_SCHEME_ZILOG) {
pvr2_issue_simple_cmd(hdw,
FX2CMD_HCW_ZILOG_RESET |
(1 << 8) |
@@ -2451,6 +2460,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
GFP_KERNEL);
if (!hdw->controls) goto fail;
hdw->hdw_desc = hdw_desc;
+ hdw->ir_scheme_active = hdw->hdw_desc->ir_scheme;
for (idx = 0; idx < hdw->control_cnt; idx++) {
cptr = hdw->controls + idx;
cptr->hdw = hdw;
@@ -4809,6 +4819,12 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which,
stats.buffers_processed,
stats.buffers_failed);
}
+ case 6: {
+ unsigned int id = hdw->ir_scheme_active;
+ return scnprintf(buf, acnt, "ir scheme: id=%d %s", id,
+ (id >= ARRAY_SIZE(ir_scheme_names) ?
+ "?" : ir_scheme_names[id]));
+ }
default: break;
}
return 0;
@@ -4825,65 +4841,35 @@ static unsigned int pvr2_hdw_report_clients(struct pvr2_hdw *hdw,
unsigned int tcnt = 0;
unsigned int ccnt;
struct i2c_client *client;
- struct list_head *item;
- void *cd;
const char *p;
unsigned int id;
- ccnt = scnprintf(buf, acnt, "Associated v4l2-subdev drivers:");
+ ccnt = scnprintf(buf, acnt, "Associated v4l2-subdev drivers and I2C clients:\n");
tcnt += ccnt;
v4l2_device_for_each_subdev(sd, &hdw->v4l2_dev) {
id = sd->grp_id;
p = NULL;
if (id < ARRAY_SIZE(module_names)) p = module_names[id];
if (p) {
- ccnt = scnprintf(buf + tcnt, acnt - tcnt, " %s", p);
+ ccnt = scnprintf(buf + tcnt, acnt - tcnt, " %s:", p);
tcnt += ccnt;
} else {
ccnt = scnprintf(buf + tcnt, acnt - tcnt,
- " (unknown id=%u)", id);
+ " (unknown id=%u):", id);
tcnt += ccnt;
}
- }
- ccnt = scnprintf(buf + tcnt, acnt - tcnt, "\n");
- tcnt += ccnt;
-
- ccnt = scnprintf(buf + tcnt, acnt - tcnt, "I2C clients:\n");
- tcnt += ccnt;
-
- mutex_lock(&hdw->i2c_adap.clist_lock);
- list_for_each(item, &hdw->i2c_adap.clients) {
- client = list_entry(item, struct i2c_client, list);
- ccnt = scnprintf(buf + tcnt, acnt - tcnt,
- " %s: i2c=%02x", client->name, client->addr);
- tcnt += ccnt;
- cd = i2c_get_clientdata(client);
- v4l2_device_for_each_subdev(sd, &hdw->v4l2_dev) {
- if (cd == sd) {
- id = sd->grp_id;
- p = NULL;
- if (id < ARRAY_SIZE(module_names)) {
- p = module_names[id];
- }
- if (p) {
- ccnt = scnprintf(buf + tcnt,
- acnt - tcnt,
- " subdev=%s", p);
- tcnt += ccnt;
- } else {
- ccnt = scnprintf(buf + tcnt,
- acnt - tcnt,
- " subdev= id %u)",
- id);
- tcnt += ccnt;
- }
- break;
- }
+ client = v4l2_get_subdevdata(sd);
+ if (client) {
+ ccnt = scnprintf(buf + tcnt, acnt - tcnt,
+ " %s @ %02x\n", client->name,
+ client->addr);
+ tcnt += ccnt;
+ } else {
+ ccnt = scnprintf(buf + tcnt, acnt - tcnt,
+ " no i2c client\n");
+ tcnt += ccnt;
}
- ccnt = scnprintf(buf + tcnt, acnt - tcnt, "\n");
- tcnt += ccnt;
}
- mutex_unlock(&hdw->i2c_adap.clist_lock);
return tcnt;
}
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
index 9af282f9e765..610bd848df24 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
@@ -42,6 +42,18 @@ static int ir_mode[PVR_NUM] = { [0 ... PVR_NUM-1] = 1 };
module_param_array(ir_mode, int, NULL, 0444);
MODULE_PARM_DESC(ir_mode,"specify: 0=disable IR reception, 1=normal IR");
+static int pvr2_disable_ir_video;
+module_param_named(disable_autoload_ir_video, pvr2_disable_ir_video,
+ int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(disable_autoload_ir_video,
+ "1=do not try to autoload ir_video IR receiver");
+
+/* Mapping of IR schemes to known I2C addresses - if any */
+static const unsigned char ir_video_addresses[] = {
+ [PVR2_IR_SCHEME_29XXX] = 0x18,
+ [PVR2_IR_SCHEME_24XXX] = 0x18,
+};
+
static int pvr2_i2c_write(struct pvr2_hdw *hdw, /* Context */
u8 i2c_addr, /* I2C address we're talking to */
u8 *data, /* Data to write */
@@ -559,6 +571,31 @@ static void do_i2c_scan(struct pvr2_hdw *hdw)
printk(KERN_INFO "%s: i2c scan done.\n", hdw->name);
}
+static void pvr2_i2c_register_ir(struct pvr2_hdw *hdw)
+{
+ struct i2c_board_info info;
+ unsigned char addr = 0;
+ if (pvr2_disable_ir_video) {
+ pvr2_trace(PVR2_TRACE_INFO,
+ "Automatic binding of ir_video has been disabled.");
+ return;
+ }
+ if (hdw->ir_scheme_active < ARRAY_SIZE(ir_video_addresses)) {
+ addr = ir_video_addresses[hdw->ir_scheme_active];
+ }
+ if (!addr) {
+ /* The device either doesn't support I2C-based IR or we
+ don't know (yet) how to operate IR on the device. */
+ return;
+ }
+ pvr2_trace(PVR2_TRACE_INFO,
+ "Binding ir_video to i2c address 0x%02x.", addr);
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+ info.addr = addr;
+ i2c_new_device(&hdw->i2c_adap, &info);
+}
+
void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
{
unsigned int idx;
@@ -574,7 +611,9 @@ 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_desc->ir_scheme == PVR2_IR_SCHEME_24XXX) {
+ if (hdw->ir_scheme_active == PVR2_IR_SCHEME_24XXX) {
+ /* Set up translation so that our IR looks like a
+ 29xxx device */
hdw->i2c_func[0x18] = i2c_24xxx_ir;
}
}
@@ -597,15 +636,23 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
i2c_add_adapter(&hdw->i2c_adap);
if (hdw->i2c_func[0x18] == i2c_24xxx_ir) {
/* Probe for a different type of IR receiver on this
- device. If present, disable the emulated IR receiver. */
+ device. This is really the only way to differentiate
+ older 24xxx devices from 24xxx variants that include an
+ IR blaster. If the IR blaster is present, the IR
+ receiver is part of that chip and thus we must disable
+ the emulated IR receiver. */
if (do_i2c_probe(hdw, 0x71)) {
pvr2_trace(PVR2_TRACE_INFO,
"Device has newer IR hardware;"
" disabling unneeded virtual IR device");
hdw->i2c_func[0x18] = NULL;
+ /* Remember that this is a different device... */
+ hdw->ir_scheme_active = PVR2_IR_SCHEME_24XXX_MCE;
}
}
if (i2c_scan) do_i2c_scan(hdw);
+
+ pvr2_i2c_register_ir(hdw);
}
void pvr2_i2c_core_done(struct pvr2_hdw *hdw)
diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
index 299c1cbc3832..6c23456e0bda 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
@@ -539,7 +539,7 @@ static void class_dev_destroy(struct pvr2_sysfs *sfp)
&sfp->attr_unit_number);
}
pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev);
- sfp->class_dev->driver_data = NULL;
+ dev_set_drvdata(sfp->class_dev, NULL);
device_unregister(sfp->class_dev);
sfp->class_dev = NULL;
}
@@ -549,7 +549,7 @@ static ssize_t v4l_minor_number_show(struct device *class_dev,
struct device_attribute *attr, char *buf)
{
struct pvr2_sysfs *sfp;
- sfp = (struct pvr2_sysfs *)class_dev->driver_data;
+ sfp = dev_get_drvdata(class_dev);
if (!sfp) return -EINVAL;
return scnprintf(buf,PAGE_SIZE,"%d\n",
pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw,
@@ -561,7 +561,7 @@ static ssize_t bus_info_show(struct device *class_dev,
struct device_attribute *attr, char *buf)
{
struct pvr2_sysfs *sfp;
- sfp = (struct pvr2_sysfs *)class_dev->driver_data;
+ sfp = dev_get_drvdata(class_dev);
if (!sfp) return -EINVAL;
return scnprintf(buf,PAGE_SIZE,"%s\n",
pvr2_hdw_get_bus_info(sfp->channel.hdw));
@@ -572,7 +572,7 @@ static ssize_t hdw_name_show(struct device *class_dev,
struct device_attribute *attr, char *buf)
{
struct pvr2_sysfs *sfp;
- sfp = (struct pvr2_sysfs *)class_dev->driver_data;
+ sfp = dev_get_drvdata(class_dev);
if (!sfp) return -EINVAL;
return scnprintf(buf,PAGE_SIZE,"%s\n",
pvr2_hdw_get_type(sfp->channel.hdw));
@@ -583,7 +583,7 @@ static ssize_t hdw_desc_show(struct device *class_dev,
struct device_attribute *attr, char *buf)
{
struct pvr2_sysfs *sfp;
- sfp = (struct pvr2_sysfs *)class_dev->driver_data;
+ sfp = dev_get_drvdata(class_dev);
if (!sfp) return -EINVAL;
return scnprintf(buf,PAGE_SIZE,"%s\n",
pvr2_hdw_get_desc(sfp->channel.hdw));
@@ -595,7 +595,7 @@ static ssize_t v4l_radio_minor_number_show(struct device *class_dev,
char *buf)
{
struct pvr2_sysfs *sfp;
- sfp = (struct pvr2_sysfs *)class_dev->driver_data;
+ sfp = dev_get_drvdata(class_dev);
if (!sfp) return -EINVAL;
return scnprintf(buf,PAGE_SIZE,"%d\n",
pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw,
@@ -607,7 +607,7 @@ static ssize_t unit_number_show(struct device *class_dev,
struct device_attribute *attr, char *buf)
{
struct pvr2_sysfs *sfp;
- sfp = (struct pvr2_sysfs *)class_dev->driver_data;
+ sfp = dev_get_drvdata(class_dev);
if (!sfp) return -EINVAL;
return scnprintf(buf,PAGE_SIZE,"%d\n",
pvr2_hdw_get_unit_number(sfp->channel.hdw));
@@ -635,7 +635,7 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
class_dev->parent = &usb_dev->dev;
sfp->class_dev = class_dev;
- class_dev->driver_data = sfp;
+ dev_set_drvdata(class_dev, sfp);
ret = device_register(class_dev);
if (ret) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
@@ -792,7 +792,7 @@ static ssize_t debuginfo_show(struct device *class_dev,
struct device_attribute *attr, char *buf)
{
struct pvr2_sysfs *sfp;
- sfp = (struct pvr2_sysfs *)class_dev->driver_data;
+ sfp = dev_get_drvdata(class_dev);
if (!sfp) return -EINVAL;
pvr2_hdw_trigger_module_log(sfp->channel.hdw);
return pvr2_debugifc_print_info(sfp->channel.hdw,buf,PAGE_SIZE);
@@ -803,7 +803,7 @@ static ssize_t debugcmd_show(struct device *class_dev,
struct device_attribute *attr, char *buf)
{
struct pvr2_sysfs *sfp;
- sfp = (struct pvr2_sysfs *)class_dev->driver_data;
+ sfp = dev_get_drvdata(class_dev);
if (!sfp) return -EINVAL;
return pvr2_debugifc_print_status(sfp->channel.hdw,buf,PAGE_SIZE);
}
@@ -816,7 +816,7 @@ static ssize_t debugcmd_store(struct device *class_dev,
struct pvr2_sysfs *sfp;
int ret;
- sfp = (struct pvr2_sysfs *)class_dev->driver_data;
+ sfp = dev_get_drvdata(class_dev);
if (!sfp) return -EINVAL;
ret = pvr2_debugifc_docmd(sfp->channel.hdw,buf,count);
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
index 9e0f2b07b93b..2d8825e5b1be 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
@@ -90,7 +90,7 @@ static struct v4l2_capability pvr_capability ={
.driver = "pvrusb2",
.card = "Hauppauge WinTV pvr-usb2",
.bus_info = "usb",
- .version = KERNEL_VERSION(0,8,0),
+ .version = KERNEL_VERSION(0, 9, 0),
.capabilities = (V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO |
V4L2_CAP_READWRITE),
@@ -267,7 +267,7 @@ static long pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
memset(&tmp,0,sizeof(tmp));
tmp.index = vi->index;
ret = 0;
- if ((vi->index < 0) || (vi->index >= fh->input_cnt)) {
+ if (vi->index >= fh->input_cnt) {
ret = -EINVAL;
break;
}
@@ -331,7 +331,7 @@ static long pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
case VIDIOC_S_INPUT:
{
struct v4l2_input *vi = (struct v4l2_input *)arg;
- if ((vi->index < 0) || (vi->index >= fh->input_cnt)) {
+ if (vi->index >= fh->input_cnt) {
ret = -ERANGE;
break;
}