summaryrefslogtreecommitdiff
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/Kconfig27
-rw-r--r--drivers/media/video/pvrusb2/Makefile6
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-context.c13
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-ctrl.c21
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c16
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-encoder.c4
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h31
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw.c109
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw.h8
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c8
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c2
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-i2c-core.c85
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-io.c4
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-main.c1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-sysfs.c3
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-v4l2.c161
16 files changed, 303 insertions, 196 deletions
diff --git a/drivers/media/video/pvrusb2/Kconfig b/drivers/media/video/pvrusb2/Kconfig
index 7e727fe14b32..5645c9318890 100644
--- a/drivers/media/video/pvrusb2/Kconfig
+++ b/drivers/media/video/pvrusb2/Kconfig
@@ -5,8 +5,6 @@ config VIDEO_PVRUSB2
select VIDEO_TUNER
select VIDEO_TVEEPROM
select VIDEO_CX2341X
- select VIDEO_SAA711X
- select VIDEO_MSP3400
---help---
This is a video4linux driver for Conexant 23416 based
usb2 personal video recorder devices.
@@ -14,6 +12,20 @@ config VIDEO_PVRUSB2
To compile this driver as a module, choose M here: the
module will be called pvrusb2
+config VIDEO_PVRUSB2_29XXX
+ bool "Hauppauge WinTV-PVR USB2 support for 29xxx model series"
+ depends on VIDEO_PVRUSB2 && EXPERIMENTAL
+ select VIDEO_SAA711X
+ select VIDEO_MSP3400
+ ---help---
+ This option enables support for WinTV-PVR USB2 devices whose
+ model number is of the form "29xxx" (leading prefix of "29"
+ followed by 3 digits).
+ To see if you may need this option, examine the white
+ sticker on the underside of your device.
+
+ If you are in doubt, say Y.
+
config VIDEO_PVRUSB2_24XXX
bool "Hauppauge WinTV-PVR USB2 support for 24xxx model series"
depends on VIDEO_PVRUSB2 && EXPERIMENTAL
@@ -25,14 +37,9 @@ config VIDEO_PVRUSB2_24XXX
form "24xxx" (leading prefix of "24" followed by 3 digits).
To see if you may need this option, examine the white
sticker on the underside of your device. Enabling this
- option will not harm support for older devices, however it
- is a separate option because of the experimental nature of
- this new feature.
-
- If you are in doubt, say N.
+ option will not harm support for older devices.
- Note: This feature is _very_ experimental. You have been
- warned.
+ If you are in doubt, say Y.
config VIDEO_PVRUSB2_SYSFS
bool "pvrusb2 sysfs support (EXPERIMENTAL)"
@@ -60,3 +67,5 @@ config VIDEO_PVRUSB2_DEBUGIFC
You do not need to select this option unless you plan
on debugging the driver or performing a manual firmware
extraction.
+
+ If you are in doubt, say N.
diff --git a/drivers/media/video/pvrusb2/Makefile b/drivers/media/video/pvrusb2/Makefile
index 02e414210dac..69b3e43cd0eb 100644
--- a/drivers/media/video/pvrusb2/Makefile
+++ b/drivers/media/video/pvrusb2/Makefile
@@ -1,10 +1,6 @@
obj-pvrusb2-sysfs-$(CONFIG_VIDEO_PVRUSB2_SYSFS) := pvrusb2-sysfs.o
obj-pvrusb2-debugifc-$(CONFIG_VIDEO_PVRUSB2_DEBUGIFC) := pvrusb2-debugifc.o
-obj-pvrusb2-24xxx-$(CONFIG_VIDEO_PVRUSB2_24XXX) := \
- pvrusb2-cx2584x-v4l.o \
- pvrusb2-wm8775.o
-
pvrusb2-objs := pvrusb2-i2c-core.o pvrusb2-i2c-cmd-v4l2.o \
pvrusb2-audio.o pvrusb2-i2c-chips-v4l2.o \
pvrusb2-encoder.o pvrusb2-video-v4l.o \
@@ -12,7 +8,7 @@ pvrusb2-objs := pvrusb2-i2c-core.o pvrusb2-i2c-cmd-v4l2.o \
pvrusb2-main.o pvrusb2-hdw.o pvrusb2-v4l2.o \
pvrusb2-ctrl.o pvrusb2-std.o \
pvrusb2-context.o pvrusb2-io.o pvrusb2-ioread.o \
- $(obj-pvrusb2-24xxx-y) \
+ pvrusb2-cx2584x-v4l.o pvrusb2-wm8775.o \
$(obj-pvrusb2-sysfs-y) $(obj-pvrusb2-debugifc-y)
obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2.o
diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.c b/drivers/media/video/pvrusb2/pvrusb2-context.c
index f129f316d20e..cf129746205d 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-context.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-context.c
@@ -45,16 +45,21 @@ static void pvr2_context_trigger_poll(struct pvr2_context *mp)
}
-static void pvr2_context_poll(struct pvr2_context *mp)
+static void pvr2_context_poll(struct work_struct *work)
{
+ struct pvr2_context *mp =
+ container_of(work, struct pvr2_context, workpoll);
pvr2_context_enter(mp); do {
pvr2_hdw_poll(mp->hdw);
} while (0); pvr2_context_exit(mp);
}
-static void pvr2_context_setup(struct pvr2_context *mp)
+static void pvr2_context_setup(struct work_struct *work)
{
+ struct pvr2_context *mp =
+ container_of(work, struct pvr2_context, workinit);
+
pvr2_context_enter(mp); do {
if (!pvr2_hdw_dev_ok(mp->hdw)) break;
pvr2_hdw_setup(mp->hdw);
@@ -92,8 +97,8 @@ struct pvr2_context *pvr2_context_create(
}
mp->workqueue = create_singlethread_workqueue("pvrusb2");
- INIT_WORK(&mp->workinit,(void (*)(void*))pvr2_context_setup,mp);
- INIT_WORK(&mp->workpoll,(void (*)(void*))pvr2_context_poll,mp);
+ INIT_WORK(&mp->workinit, pvr2_context_setup);
+ INIT_WORK(&mp->workpoll, pvr2_context_poll);
queue_work(mp->workqueue,&mp->workinit);
done:
return mp;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
index fb6198f1df98..c77de859cc8e 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
@@ -43,12 +43,17 @@ int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *cptr,int mask,int val)
if (cptr->info->type == pvr2_ctl_bitmask) {
mask &= cptr->info->def.type_bitmask.valid_bits;
} else if (cptr->info->type == pvr2_ctl_int) {
- if (val < cptr->info->def.type_int.min_value) {
- break;
+ int lim;
+ lim = cptr->info->def.type_int.min_value;
+ if (cptr->info->get_min_value) {
+ cptr->info->get_min_value(cptr,&lim);
}
- if (val > cptr->info->def.type_int.max_value) {
- break;
+ if (val < lim) break;
+ lim = cptr->info->def.type_int.max_value;
+ if (cptr->info->get_max_value) {
+ cptr->info->get_max_value(cptr,&lim);
}
+ if (val > lim) break;
} else if (cptr->info->type == pvr2_ctl_enum) {
if (val >= cptr->info->def.type_enum.count) {
break;
@@ -91,7 +96,9 @@ int pvr2_ctrl_get_max(struct pvr2_ctrl *cptr)
int ret = 0;
if (!cptr) return 0;
LOCK_TAKE(cptr->hdw->big_lock); do {
- if (cptr->info->type == pvr2_ctl_int) {
+ if (cptr->info->get_max_value) {
+ cptr->info->get_max_value(cptr,&ret);
+ } else if (cptr->info->type == pvr2_ctl_int) {
ret = cptr->info->def.type_int.max_value;
}
} while(0); LOCK_GIVE(cptr->hdw->big_lock);
@@ -105,7 +112,9 @@ int pvr2_ctrl_get_min(struct pvr2_ctrl *cptr)
int ret = 0;
if (!cptr) return 0;
LOCK_TAKE(cptr->hdw->big_lock); do {
- if (cptr->info->type == pvr2_ctl_int) {
+ if (cptr->info->get_min_value) {
+ cptr->info->get_min_value(cptr,&ret);
+ } else if (cptr->info->type == pvr2_ctl_int) {
ret = cptr->info->def.type_int.min_value;
}
} while(0); LOCK_GIVE(cptr->hdw->big_lock);
diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
index c80c26be6e4d..848fb233d808 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
@@ -260,6 +260,22 @@ int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *hdw,
sizeof(decoder_ops[0]))) - 1;
hdw->decoder_ctrl = &ctxt->ctrl;
cp->handler = &ctxt->handler;
+ {
+ /*
+ Mike Isely <isely@pobox.com> 19-Nov-2006 - This bit
+ of nuttiness for cx25840 causes that module to
+ correctly set up its video scaling. This is really
+ a problem in the cx25840 module itself, but we work
+ around it here. The problem has not been seen in
+ ivtv because there VBI is supported and set up. We
+ don't do VBI here (at least not yet) and thus we
+ never attempted to even set it up.
+ */
+ struct v4l2_format fmt;
+ memset(&fmt,0,sizeof(fmt));
+ fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
+ pvr2_i2c_client_cmd(ctxt->client,VIDIOC_S_FMT,&fmt);
+ }
pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x cx2584x V4L2 handler set up",
cp->client->addr);
return !0;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/drivers/media/video/pvrusb2/pvrusb2-encoder.c
index 18a7073501c6..c94f97b79392 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-encoder.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-encoder.c
@@ -317,7 +317,7 @@ int pvr2_encoder_configure(struct pvr2_hdw *hdw)
if (ret) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "Failed to configure cx32416");
+ "Failed to configure cx23416");
return ret;
}
@@ -337,7 +337,7 @@ int pvr2_encoder_configure(struct pvr2_hdw *hdw)
if (ret) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "Failed to initialize cx32416 video input");
+ "Failed to initialize cx23416 video input");
return ret;
}
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
index 0d6dc33ca320..34b08fbcc6ea 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
@@ -33,7 +33,6 @@
*/
-#include <linux/config.h>
#include <linux/videodev2.h>
#include <linux/i2c.h>
#include <linux/mutex.h>
@@ -41,32 +40,6 @@
#include "pvrusb2-io.h"
#include <media/cx2341x.h>
-/* Legal values for the SRATE state variable */
-#define PVR2_CVAL_SRATE_48 0
-#define PVR2_CVAL_SRATE_44_1 1
-
-/* Legal values for the AUDIOBITRATE state variable */
-#define PVR2_CVAL_AUDIOBITRATE_384 0
-#define PVR2_CVAL_AUDIOBITRATE_320 1
-#define PVR2_CVAL_AUDIOBITRATE_256 2
-#define PVR2_CVAL_AUDIOBITRATE_224 3
-#define PVR2_CVAL_AUDIOBITRATE_192 4
-#define PVR2_CVAL_AUDIOBITRATE_160 5
-#define PVR2_CVAL_AUDIOBITRATE_128 6
-#define PVR2_CVAL_AUDIOBITRATE_112 7
-#define PVR2_CVAL_AUDIOBITRATE_96 8
-#define PVR2_CVAL_AUDIOBITRATE_80 9
-#define PVR2_CVAL_AUDIOBITRATE_64 10
-#define PVR2_CVAL_AUDIOBITRATE_56 11
-#define PVR2_CVAL_AUDIOBITRATE_48 12
-#define PVR2_CVAL_AUDIOBITRATE_32 13
-#define PVR2_CVAL_AUDIOBITRATE_VBR 14
-
-/* Legal values for the AUDIOEMPHASIS state variable */
-#define PVR2_CVAL_AUDIOEMPHASIS_NONE 0
-#define PVR2_CVAL_AUDIOEMPHASIS_50_15 1
-#define PVR2_CVAL_AUDIOEMPHASIS_CCITT 2
-
/* Legal values for PVR2_CID_HSM */
#define PVR2_CVAL_HSM_FAIL 0
#define PVR2_CVAL_HSM_FULL 1
@@ -107,6 +80,8 @@ struct pvr2_ctl_info {
/* Control's implementation */
pvr2_ctlf_get_value get_value; /* Get its value */
+ pvr2_ctlf_get_value get_min_value; /* Get minimum allowed value */
+ pvr2_ctlf_get_value get_max_value; /* Get maximum allowed value */
pvr2_ctlf_set_value set_value; /* Set its value */
pvr2_ctlf_val_to_sym val_to_sym; /* Custom convert value->symbol */
pvr2_ctlf_sym_to_val sym_to_val; /* Custom convert symbol->value */
@@ -193,9 +168,7 @@ struct pvr2_decoder_ctrl {
/* Known major hardware variants, keyed from device ID */
#define PVR2_HDW_TYPE_29XXX 0
-#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
#define PVR2_HDW_TYPE_24XXX 1
-#endif
typedef int (*pvr2_i2c_func)(struct pvr2_hdw *,u8,u8 *,u16,u8 *, u16);
#define PVR2_I2C_FUNC_CNT 128
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
index be1e5cc78081..d2004965187b 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -24,6 +24,7 @@
#include <linux/slab.h>
#include <linux/firmware.h>
#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
#include <asm/semaphore.h>
#include "pvrusb2.h"
#include "pvrusb2-std.h"
@@ -38,9 +39,7 @@
struct usb_device_id pvr2_device_table[] = {
[PVR2_HDW_TYPE_29XXX] = { USB_DEVICE(0x2040, 0x2900) },
-#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
[PVR2_HDW_TYPE_24XXX] = { USB_DEVICE(0x2040, 0x2400) },
-#endif
{ }
};
@@ -48,9 +47,7 @@ MODULE_DEVICE_TABLE(usb, pvr2_device_table);
static const char *pvr2_device_names[] = {
[PVR2_HDW_TYPE_29XXX] = "WinTV PVR USB2 Model Category 29xxxx",
-#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
[PVR2_HDW_TYPE_24XXX] = "WinTV PVR USB2 Model Category 24xxxx",
-#endif
};
struct pvr2_string_table {
@@ -58,14 +55,12 @@ struct pvr2_string_table {
unsigned int cnt;
};
-#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
// Names of other client modules to request for 24xxx model hardware
static const char *pvr2_client_24xxx[] = {
"cx25840",
"tuner",
"wm8775",
};
-#endif
// Names of other client modules to request for 29xxx model hardware
static const char *pvr2_client_29xxx[] = {
@@ -79,12 +74,10 @@ static struct pvr2_string_table pvr2_client_lists[] = {
pvr2_client_29xxx,
sizeof(pvr2_client_29xxx)/sizeof(pvr2_client_29xxx[0]),
},
-#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
[PVR2_HDW_TYPE_24XXX] = {
pvr2_client_24xxx,
sizeof(pvr2_client_24xxx)/sizeof(pvr2_client_24xxx[0]),
},
-#endif
};
static struct pvr2_hdw *unit_pointers[PVR_NUM] = {[ 0 ... PVR_NUM-1 ] = NULL};
@@ -221,14 +214,15 @@ static const struct pvr2_mpeg_ids mpeg_ids[] = {
};
#define MPEGDEF_COUNT (sizeof(mpeg_ids)/sizeof(mpeg_ids[0]))
+
static const char *control_values_srate[] = {
- [PVR2_CVAL_SRATE_48] = "48KHz",
- [PVR2_CVAL_SRATE_44_1] = "44.1KHz",
+ [V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100] = "44.1 kHz",
+ [V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000] = "48 kHz",
+ [V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000] = "32 kHz",
};
-
static const char *control_values_input[] = {
[PVR2_CVAL_INPUT_TV] = "television", /*xawtv needs this name*/
[PVR2_CVAL_INPUT_RADIO] = "radio",
@@ -362,6 +356,28 @@ static int ctrl_freq_set(struct pvr2_ctrl *cptr,int m,int v)
return 0;
}
+static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp)
+{
+ /* Actual maximum depends on the video standard in effect. */
+ if (cptr->hdw->std_mask_cur & V4L2_STD_525_60) {
+ *vp = 480;
+ } else {
+ *vp = 576;
+ }
+ return 0;
+}
+
+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) {
+ *vp = 75;
+ } else {
+ *vp = 17;
+ }
+ return 0;
+}
+
static int ctrl_cx2341x_is_dirty(struct pvr2_ctrl *cptr)
{
return cptr->hdw->enc_stale != 0;
@@ -719,19 +735,23 @@ static const struct pvr2_ctl_info control_defs[] = {
.internal_id = PVR2_CID_HRES,
.default_value = 720,
DEFREF(res_hor),
- DEFINT(320,720),
+ DEFINT(19,720),
},{
.desc = "Vertical capture resolution",
.name = "resolution_ver",
.internal_id = PVR2_CID_VRES,
.default_value = 480,
DEFREF(res_ver),
- DEFINT(200,625),
+ DEFINT(17,576),
+ /* Hook in check for video standard and adjust maximum
+ depending on the standard. */
+ .get_max_value = ctrl_vres_max_get,
+ .get_min_value = ctrl_vres_min_get,
},{
.v4l_id = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
- .desc = "Sample rate",
+ .default_value = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
+ .desc = "Audio Sampling Frequency",
.name = "srate",
- .default_value = PVR2_CVAL_SRATE_48,
DEFREF(srate),
DEFENUM(control_values_srate),
},{
@@ -935,22 +955,18 @@ static int pvr2_upload_firmware1(struct pvr2_hdw *hdw)
static const char *fw_files_29xxx[] = {
"v4l-pvrusb2-29xxx-01.fw",
};
-#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
static const char *fw_files_24xxx[] = {
"v4l-pvrusb2-24xxx-01.fw",
};
-#endif
static const struct pvr2_string_table fw_file_defs[] = {
[PVR2_HDW_TYPE_29XXX] = {
fw_files_29xxx,
sizeof(fw_files_29xxx)/sizeof(fw_files_29xxx[0]),
},
-#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
[PVR2_HDW_TYPE_24XXX] = {
fw_files_24xxx,
sizeof(fw_files_24xxx)/sizeof(fw_files_24xxx[0]),
},
-#endif
};
hdw->fw1_state = FW1_STATE_FAILED; // default result
@@ -1911,8 +1927,8 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
return hdw;
fail:
if (hdw) {
- if (hdw->ctl_read_urb) usb_free_urb(hdw->ctl_read_urb);
- if (hdw->ctl_write_urb) usb_free_urb(hdw->ctl_write_urb);
+ usb_free_urb(hdw->ctl_read_urb);
+ usb_free_urb(hdw->ctl_write_urb);
if (hdw->ctl_read_buffer) kfree(hdw->ctl_read_buffer);
if (hdw->ctl_write_buffer) kfree(hdw->ctl_write_buffer);
if (hdw->controls) kfree(hdw->controls);
@@ -2237,11 +2253,14 @@ static int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw)
}
if (hdw->std_dirty ||
+ hdw->enc_stale ||
+ hdw->srate_dirty ||
+ hdw->res_ver_dirty ||
+ hdw->res_hor_dirty ||
0) {
/* If any of this changes, then the encoder needs to be
reconfigured, and we need to reset the stream. */
stale_subsys_mask |= (1<<PVR2_SUBSYS_B_ENC_CFG);
- stale_subsys_mask |= hdw->subsys_stream_mask;
}
if (hdw->srate_dirty) {
@@ -2507,7 +2526,7 @@ void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *hdw,int v)
}
-static void pvr2_ctl_write_complete(struct urb *urb, struct pt_regs *regs)
+static void pvr2_ctl_write_complete(struct urb *urb)
{
struct pvr2_hdw *hdw = urb->context;
hdw->ctl_write_pend_flag = 0;
@@ -2516,7 +2535,7 @@ static void pvr2_ctl_write_complete(struct urb *urb, struct pt_regs *regs)
}
-static void pvr2_ctl_read_complete(struct urb *urb, struct pt_regs *regs)
+static void pvr2_ctl_read_complete(struct urb *urb)
{
struct pvr2_hdw *hdw = urb->context;
hdw->ctl_read_pend_flag = 0;
@@ -2530,12 +2549,10 @@ static void pvr2_ctl_timeout(unsigned long data)
struct pvr2_hdw *hdw = (struct pvr2_hdw *)data;
if (hdw->ctl_write_pend_flag || hdw->ctl_read_pend_flag) {
hdw->ctl_timeout_flag = !0;
- if (hdw->ctl_write_pend_flag && hdw->ctl_write_urb) {
+ if (hdw->ctl_write_pend_flag)
usb_unlink_urb(hdw->ctl_write_urb);
- }
- if (hdw->ctl_read_pend_flag && hdw->ctl_read_urb) {
+ if (hdw->ctl_read_pend_flag)
usb_unlink_urb(hdw->ctl_read_urb);
- }
}
}
@@ -3087,6 +3104,42 @@ static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw)
}
+int pvr2_hdw_register_access(struct pvr2_hdw *hdw,
+ u32 chip_id,unsigned long reg_id,
+ int setFl,u32 *val_ptr)
+{
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ struct list_head *item;
+ struct pvr2_i2c_client *cp;
+ struct v4l2_register req;
+ int stat = 0;
+ int okFl = 0;
+
+ req.i2c_id = chip_id;
+ req.reg = reg_id;
+ if (setFl) req.val = *val_ptr;
+ mutex_lock(&hdw->i2c_list_lock); do {
+ list_for_each(item,&hdw->i2c_clients) {
+ cp = list_entry(item,struct pvr2_i2c_client,list);
+ if (cp->client->driver->id != chip_id) continue;
+ stat = pvr2_i2c_client_cmd(
+ cp,(setFl ? VIDIOC_INT_S_REGISTER :
+ VIDIOC_INT_G_REGISTER),&req);
+ if (!setFl) *val_ptr = req.val;
+ okFl = !0;
+ break;
+ }
+ } while (0); mutex_unlock(&hdw->i2c_list_lock);
+ if (okFl) {
+ return stat;
+ }
+ return -EINVAL;
+#else
+ return -ENOSYS;
+#endif
+}
+
+
/*
Stuff for Emacs to see, in order to encourage consistent editing style:
*** Local Variables: ***
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h
index fd931b5da490..29979bb2a768 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h
@@ -211,6 +211,14 @@ int pvr2_hdw_v4l_get_minor_number(struct pvr2_hdw *);
/* Store the v4l minor device number */
void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *,int);
+/* Direct read/write access to chip's registers:
+ chip_id - unique id of chip (e.g. I2C_DRIVERD_xxxx)
+ reg_id - register number to access
+ setFl - true to set the register, false to read it
+ val_ptr - storage location for source / result. */
+int pvr2_hdw_register_access(struct pvr2_hdw *,
+ u32 chip_id,unsigned long reg_id,
+ int setFl,u32 *val_ptr);
/* The following entry points are all lower level things you normally don't
want to worry about. */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
index fbe6039aeb6a..05121666b9ba 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
@@ -19,6 +19,7 @@
*
*/
+#include <linux/kernel.h>
#include "pvrusb2-i2c-core.h"
#include "pvrusb2-hdw-internal.h"
#include "pvrusb2-debug.h"
@@ -26,10 +27,8 @@
#include "pvrusb2-audio.h"
#include "pvrusb2-tuner.h"
#include "pvrusb2-video-v4l.h"
-#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
#include "pvrusb2-cx2584x-v4l.h"
#include "pvrusb2-wm8775.h"
-#endif
#define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__)
@@ -71,7 +70,6 @@ void pvr2_i2c_probe(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
return;
}
}
-#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
if (id == I2C_DRIVERID_CX25840) {
if (pvr2_i2c_cx2584x_v4l_setup(hdw,cp)) {
return;
@@ -82,7 +80,6 @@ void pvr2_i2c_probe(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
return;
}
}
-#endif
if (id == I2C_DRIVERID_SAA711X) {
if (pvr2_i2c_decoder_v4l_setup(hdw,cp)) {
return;
@@ -93,7 +90,8 @@ void pvr2_i2c_probe(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
const struct pvr2_i2c_op *pvr2_i2c_get_op(unsigned int idx)
{
- if (idx >= sizeof(ops)/sizeof(ops[0])) return 0;
+ if (idx >= ARRAY_SIZE(ops))
+ return NULL;
return ops[idx];
}
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c
index 8a9933dec912..05ea17afe903 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c
@@ -31,7 +31,7 @@ static void set_standard(struct pvr2_hdw *hdw)
v4l2_std_id vs;
vs = hdw->std_mask_cur;
pvr2_trace(PVR2_TRACE_CHIPS,
- "i2c v4l2 set_standard(0x%llx)",(__u64)vs);
+ "i2c v4l2 set_standard(0x%llx)",(long long unsigned)vs);
pvr2_i2c_core_cmd(hdw,VIDIOC_S_STD,&vs);
}
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
index 7fca47982277..f9bb41d8f4f3 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
@@ -185,7 +185,78 @@ static int pvr2_i2c_basic_op(struct pvr2_hdw *hdw,
}
}
-#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
+
+/* This is a special entry point for cases of I2C transaction attempts to
+ the IR receiver. The implementation here simulates the IR receiver by
+ issuing a command to the FX2 firmware and using that response to return
+ what the real I2C receiver would have returned. We use this for 24xxx
+ devices, where the IR receiver chip has been removed and replaced with
+ FX2 related logic. */
+static int i2c_24xxx_ir(struct pvr2_hdw *hdw,
+ u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen)
+{
+ u8 dat[4];
+ unsigned int stat;
+
+ if (!(rlen || wlen)) {
+ /* This is a probe attempt. Just let it succeed. */
+ return 0;
+ }
+
+ /* We don't understand this kind of transaction */
+ if ((wlen != 0) || (rlen == 0)) return -EIO;
+
+ if (rlen < 3) {
+ /* Mike Isely <isely@pobox.com> Appears to be a probe
+ attempt from lirc. Just fill in zeroes and return. If
+ we try instead to do the full transaction here, then bad
+ things seem to happen within the lirc driver module
+ (version 0.8.0-7 sources from Debian, when run under
+ vanilla 2.6.17.6 kernel) - and I don't have the patience
+ to chase it down. */
+ if (rlen > 0) rdata[0] = 0;
+ if (rlen > 1) rdata[1] = 0;
+ return 0;
+ }
+
+ /* Issue a command to the FX2 to read the IR receiver. */
+ LOCK_TAKE(hdw->ctl_lock); do {
+ hdw->cmd_buffer[0] = 0xec;
+ stat = pvr2_send_request(hdw,
+ hdw->cmd_buffer,1,
+ hdw->cmd_buffer,4);
+ dat[0] = hdw->cmd_buffer[0];
+ dat[1] = hdw->cmd_buffer[1];
+ dat[2] = hdw->cmd_buffer[2];
+ dat[3] = hdw->cmd_buffer[3];
+ } while (0); LOCK_GIVE(hdw->ctl_lock);
+
+ /* Give up if that operation failed. */
+ if (stat != 0) return stat;
+
+ /* Mangle the results into something that looks like the real IR
+ receiver. */
+ rdata[2] = 0xc1;
+ if (dat[0] != 1) {
+ /* No code received. */
+ rdata[0] = 0;
+ rdata[1] = 0;
+ } else {
+ u16 val;
+ /* Mash the FX2 firmware-provided IR code into something
+ that the normal i2c chip-level driver expects. */
+ val = dat[1];
+ val <<= 8;
+ val |= dat[2];
+ val >>= 1;
+ val &= ~0x0003;
+ val |= 0x8000;
+ rdata[0] = (val >> 8) & 0xffu;
+ rdata[1] = val & 0xffu;
+ }
+
+ return 0;
+}
/* This is a special entry point that is entered if an I2C operation is
attempted to a wm8775 chip on model 24xxx hardware. Autodetect of this
@@ -289,8 +360,6 @@ static int i2c_hack_cx25840(struct pvr2_hdw *hdw,
return -EIO;
}
-#endif /* CONFIG_VIDEO_PVRUSB2_24XXX */
-
/* This is a very, very limited I2C adapter implementation. We can only
support what we actually know will work on the device... */
static int pvr2_i2c_xfer(struct i2c_adapter *i2c_adap,
@@ -891,20 +960,18 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
{
unsigned int idx;
- // The default action for all possible I2C addresses is just to do
- // the transfer normally.
+ /* The default action for all possible I2C addresses is just to do
+ the transfer normally. */
for (idx = 0; idx < PVR2_I2C_FUNC_CNT; idx++) {
hdw->i2c_func[idx] = pvr2_i2c_basic_op;
}
-#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
- // If however we're dealing with new hardware, insert some hacks in
- // the I2C transfer stack to let things work better.
+ /* However, deal with various special cases for 24xxx hardware. */
if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) {
hdw->i2c_func[0x1b] = i2c_hack_wm8775;
hdw->i2c_func[0x44] = i2c_hack_cx25840;
+ hdw->i2c_func[0x18] = i2c_24xxx_ir;
}
-#endif
// Configure the adapter and set up everything else related to it.
memcpy(&hdw->i2c_adap,&pvr2_i2c_adap_template,sizeof(hdw->i2c_adap));
diff --git a/drivers/media/video/pvrusb2/pvrusb2-io.c b/drivers/media/video/pvrusb2/pvrusb2-io.c
index 1e393762546c..57fb32033543 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-io.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-io.c
@@ -289,7 +289,7 @@ static void pvr2_buffer_done(struct pvr2_buffer *bp)
pvr2_buffer_set_none(bp);
bp->signature = 0;
bp->stream = NULL;
- if (bp->purb) usb_free_urb(bp->purb);
+ usb_free_urb(bp->purb);
pvr2_trace(PVR2_TRACE_BUF_POOL,"/*---TRACE_FLOW---*/"
" bufferDone %p",bp);
}
@@ -429,7 +429,7 @@ static void pvr2_stream_done(struct pvr2_stream *sp)
} while (0); mutex_unlock(&sp->mutex);
}
-static void buffer_complete(struct urb *urb, struct pt_regs *regs)
+static void buffer_complete(struct urb *urb)
{
struct pvr2_buffer *bp = urb->context;
struct pvr2_stream *sp;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-main.c b/drivers/media/video/pvrusb2/pvrusb2-main.c
index 8f1a5afdd34e..e976c484c058 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-main.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-main.c
@@ -20,7 +20,6 @@
*
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/slab.h>
diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
index d1dda5caf406..c294f46db9b9 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
@@ -19,7 +19,6 @@
*
*/
-#include <linux/config.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <asm/semaphore.h>
@@ -40,8 +39,6 @@ struct pvr2_sysfs {
#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
struct pvr2_sysfs_ctl_item *item_first;
struct pvr2_sysfs_ctl_item *item_last;
- struct sysfs_ops kops;
- struct kobj_type ktype;
struct class_device_attribute attr_v4l_minor_number;
struct class_device_attribute attr_unit_number;
int v4l_minor_number_created_ok;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
index 0caf70b8c0de..bb40e9085977 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
@@ -29,27 +29,17 @@
#include "pvrusb2-v4l2.h"
#include "pvrusb2-ioread.h"
#include <linux/videodev2.h>
+#include <media/v4l2-dev.h>
#include <media/v4l2-common.h>
struct pvr2_v4l2_dev;
struct pvr2_v4l2_fh;
struct pvr2_v4l2;
-/* V4L no longer provide the ability to set / get a private context pointer
- (i.e. video_get_drvdata / video_set_drvdata), which means we have to
- concoct our own context locating mechanism. Supposedly this is intended
- to simplify driver implementation. It's not clear to me how that can
- possibly be true. Our solution here is to maintain a lookup table of
- our context instances, indexed by the minor device number of the V4L
- device. See pvr2_v4l2_open() for some implications of this approach. */
-static struct pvr2_v4l2_dev *devices[256];
-static DEFINE_MUTEX(device_lock);
-
struct pvr2_v4l2_dev {
+ struct video_device devbase; /* MUST be first! */
struct pvr2_v4l2 *v4lp;
- struct video_device *vdev;
struct pvr2_context_stream *stream;
- int ctxt_idx;
enum pvr2_config config;
};
@@ -74,7 +64,7 @@ struct pvr2_v4l2 {
struct v4l2_prio_state prio;
/* streams */
- struct pvr2_v4l2_dev video_dev;
+ struct pvr2_v4l2_dev *vdev;
};
static int video_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
@@ -459,18 +449,26 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
ret = 0;
switch(vf->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
+ int lmin,lmax;
+ struct pvr2_ctrl *hcp,*vcp;
int h = vf->fmt.pix.height;
int w = vf->fmt.pix.width;
-
- if (h < 200) {
- h = 200;
- } else if (h > 625) {
- h = 625;
+ hcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES);
+ vcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES);
+
+ lmin = pvr2_ctrl_get_min(hcp);
+ lmax = pvr2_ctrl_get_max(hcp);
+ if (w < lmin) {
+ w = lmin;
+ } else if (w > lmax) {
+ w = lmax;
}
- if (w < 320) {
- w = 320;
- } else if (w > 720) {
- w = 720;
+ lmin = pvr2_ctrl_get_min(vcp);
+ lmax = pvr2_ctrl_get_max(vcp);
+ if (h < lmin) {
+ h = lmin;
+ } else if (h > lmax) {
+ h = lmax;
}
memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
@@ -479,14 +477,8 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
vf->fmt.pix.height = h;
if (cmd == VIDIOC_S_FMT) {
- pvr2_ctrl_set_value(
- pvr2_hdw_get_ctrl_by_id(hdw,
- PVR2_CID_HRES),
- vf->fmt.pix.width);
- pvr2_ctrl_set_value(
- pvr2_hdw_get_ctrl_by_id(hdw,
- PVR2_CID_VRES),
- vf->fmt.pix.height);
+ pvr2_ctrl_set_value(hcp,vf->fmt.pix.width);
+ pvr2_ctrl_set_value(vcp,vf->fmt.pix.height);
}
} break;
case V4L2_BUF_TYPE_VBI_CAPTURE:
@@ -669,6 +661,20 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
ret = 0;
break;
}
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ case VIDIOC_INT_G_REGISTER:
+ case VIDIOC_INT_S_REGISTER:
+ {
+ u32 val;
+ struct v4l2_register *req = (struct v4l2_register *)arg;
+ if (cmd == VIDIOC_INT_S_REGISTER) val = req->val;
+ ret = pvr2_hdw_register_access(
+ hdw,req->i2c_id,req->reg,
+ cmd == VIDIOC_INT_S_REGISTER,&val);
+ if (cmd == VIDIOC_INT_G_REGISTER) req->val = val;
+ break;
+ }
+#endif
default :
ret = v4l_compat_translate_ioctl(inode,file,cmd,
@@ -702,21 +708,22 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
{
printk(KERN_INFO "pvrusb2: unregistering device video%d [%s]\n",
- dip->vdev->minor,pvr2_config_get_name(dip->config));
- if (dip->ctxt_idx >= 0) {
- mutex_lock(&device_lock);
- devices[dip->ctxt_idx] = NULL;
- dip->ctxt_idx = -1;
- mutex_unlock(&device_lock);
- }
- video_unregister_device(dip->vdev);
+ dip->devbase.minor,pvr2_config_get_name(dip->config));
+
+ /* Paranoia */
+ dip->v4lp = NULL;
+ dip->stream = NULL;
+
+ /* Actual deallocation happens later when all internal references
+ are gone. */
+ video_unregister_device(&dip->devbase);
}
static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
{
pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,-1);
- pvr2_v4l2_dev_destroy(&vp->video_dev);
+ pvr2_v4l2_dev_destroy(vp->vdev);
pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
pvr2_channel_done(&vp->channel);
@@ -724,6 +731,14 @@ static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
}
+static void pvr2_video_device_release(struct video_device *vdev)
+{
+ struct pvr2_v4l2_dev *dev;
+ dev = container_of(vdev,struct pvr2_v4l2_dev,devbase);
+ kfree(dev);
+}
+
+
static void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
{
struct pvr2_v4l2 *vp;
@@ -795,40 +810,12 @@ static int pvr2_v4l2_release(struct inode *inode, struct file *file)
static int pvr2_v4l2_open(struct inode *inode, struct file *file)
{
- struct pvr2_v4l2_dev *dip = NULL; /* Our own context pointer */
+ struct pvr2_v4l2_dev *dip; /* Our own context pointer */
struct pvr2_v4l2_fh *fhp;
struct pvr2_v4l2 *vp;
struct pvr2_hdw *hdw;
- mutex_lock(&device_lock);
- /* MCI 7-Jun-2006 Even though we're just doing what amounts to an
- atomic read of the device mapping array here, we still need the
- mutex. The problem is that there is a tiny race possible when
- we register the device. We can't update the device mapping
- array until after the device has been registered, owing to the
- fact that we can't know the minor device number until after the
- registration succeeds. And if another thread tries to open the
- device in the window of time after registration but before the
- map is updated, then it will get back an erroneous null pointer
- and the open will result in a spurious failure. The only way to
- prevent that is to (a) be inside the mutex here before we access
- the array, and (b) cover the entire registration process later
- on with this same mutex. Thus if we get inside the mutex here,
- then we can be assured that the registration process actually
- completed correctly. This is an unhappy complication from the
- use of global data in a driver that lives in a preemptible
- environment. It sure would be nice if the video device itself
- had a means for storing and retrieving a local context pointer.
- Oh wait. It did. But now it's gone. Silly me. */
- {
- unsigned int midx = iminor(file->f_dentry->d_inode);
- if (midx < sizeof(devices)/sizeof(devices[0])) {
- dip = devices[midx];
- }
- }
- mutex_unlock(&device_lock);
-
- if (!dip) return -ENODEV; /* Should be impossible but I'm paranoid */
+ dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase);
vp = dip->v4lp;
hdw = vp->channel.hdw;
@@ -1058,38 +1045,24 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
return;
}
- dip->vdev = video_device_alloc();
- if (!dip->vdev) {
- err("Alloc of pvrusb2 v4l video device failed");
- return;
- }
-
- memcpy(dip->vdev,&vdev_template,sizeof(vdev_template));
- dip->vdev->release = video_device_release;
- mutex_lock(&device_lock);
+ memcpy(&dip->devbase,&vdev_template,sizeof(vdev_template));
+ dip->devbase.release = pvr2_video_device_release;
mindevnum = -1;
unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw);
if ((unit_number >= 0) && (unit_number < PVR_NUM)) {
mindevnum = video_nr[unit_number];
}
- if ((video_register_device(dip->vdev, v4l_type, mindevnum) < 0) &&
- (video_register_device(dip->vdev, v4l_type, -1) < 0)) {
+ if ((video_register_device(&dip->devbase, v4l_type, mindevnum) < 0) &&
+ (video_register_device(&dip->devbase, v4l_type, -1) < 0)) {
err("Failed to register pvrusb2 v4l video device");
} else {
printk(KERN_INFO "pvrusb2: registered device video%d [%s]\n",
- dip->vdev->minor,pvr2_config_get_name(dip->config));
- }
-
- if ((dip->vdev->minor < sizeof(devices)/sizeof(devices[0])) &&
- (devices[dip->vdev->minor] == NULL)) {
- dip->ctxt_idx = dip->vdev->minor;
- devices[dip->ctxt_idx] = dip;
+ dip->devbase.minor,pvr2_config_get_name(dip->config));
}
- mutex_unlock(&device_lock);
pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,
- dip->vdev->minor);
+ dip->devbase.minor);
}
@@ -1100,15 +1073,19 @@ struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
vp = kmalloc(sizeof(*vp),GFP_KERNEL);
if (!vp) return vp;
memset(vp,0,sizeof(*vp));
- vp->video_dev.ctxt_idx = -1;
+ vp->vdev = kmalloc(sizeof(*vp->vdev),GFP_KERNEL);
+ if (!vp->vdev) {
+ kfree(vp);
+ return NULL;
+ }
+ memset(vp->vdev,0,sizeof(*vp->vdev));
pvr2_channel_init(&vp->channel,mnp);
pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
vp->channel.check_func = pvr2_v4l2_internal_check;
/* register streams */
- pvr2_v4l2_dev_init(&vp->video_dev,vp,pvr2_config_mpeg);
-
+ pvr2_v4l2_dev_init(vp->vdev,vp,pvr2_config_mpeg);
return vp;
}