mirror of https://gitee.com/openkylin/linux.git
V4L/DVB (5057): Pvrusb2: Stream configuration cleanups
Clean up and tighten logic involving stream configuration. This mainly involves changes to pvrusb2-v4l2.c, where we better clarify how we use the stream configuration enum and implement a cleaner means to control streaming for a given device node. Signed-off-by: Mike Isely <isely@pobox.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
This commit is contained in:
parent
f13ed249ed
commit
16eb40d37d
|
@ -363,15 +363,19 @@ int pvr2_encoder_start(struct pvr2_hdw *hdw)
|
||||||
pvr2_encoder_vcmd(hdw,CX2341X_ENC_MUTE_VIDEO,1,
|
pvr2_encoder_vcmd(hdw,CX2341X_ENC_MUTE_VIDEO,1,
|
||||||
hdw->input_val == PVR2_CVAL_INPUT_RADIO ? 1 : 0);
|
hdw->input_val == PVR2_CVAL_INPUT_RADIO ? 1 : 0);
|
||||||
|
|
||||||
if (hdw->config == pvr2_config_vbi) {
|
switch (hdw->config) {
|
||||||
|
case pvr2_config_vbi:
|
||||||
status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
|
status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
|
||||||
0x01,0x14);
|
0x01,0x14);
|
||||||
} else if (hdw->config == pvr2_config_mpeg) {
|
break;
|
||||||
|
case pvr2_config_mpeg:
|
||||||
status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
|
status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
|
||||||
0,0x13);
|
0,0x13);
|
||||||
} else {
|
break;
|
||||||
|
default: /* Unhandled cases for now */
|
||||||
status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
|
status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
|
||||||
0,0x13);
|
0,0x13);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (!status) {
|
if (!status) {
|
||||||
hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_RUN);
|
hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_RUN);
|
||||||
|
@ -386,15 +390,19 @@ int pvr2_encoder_stop(struct pvr2_hdw *hdw)
|
||||||
/* mask all interrupts */
|
/* mask all interrupts */
|
||||||
pvr2_write_register(hdw, 0x0048, 0xffffffff);
|
pvr2_write_register(hdw, 0x0048, 0xffffffff);
|
||||||
|
|
||||||
if (hdw->config == pvr2_config_vbi) {
|
switch (hdw->config) {
|
||||||
|
case pvr2_config_vbi:
|
||||||
status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
|
status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
|
||||||
0x01,0x01,0x14);
|
0x01,0x01,0x14);
|
||||||
} else if (hdw->config == pvr2_config_mpeg) {
|
break;
|
||||||
|
case pvr2_config_mpeg:
|
||||||
status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
|
status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
|
||||||
0x01,0,0x13);
|
0x01,0,0x13);
|
||||||
} else {
|
break;
|
||||||
|
default: /* Unhandled cases for now */
|
||||||
status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
|
status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
|
||||||
0x01,0,0x13);
|
0x01,0,0x13);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* change some GPIO data */
|
/* change some GPIO data */
|
||||||
|
|
|
@ -957,7 +957,8 @@ const char *pvr2_config_get_name(enum pvr2_config cfg)
|
||||||
case pvr2_config_empty: return "empty";
|
case pvr2_config_empty: return "empty";
|
||||||
case pvr2_config_mpeg: return "mpeg";
|
case pvr2_config_mpeg: return "mpeg";
|
||||||
case pvr2_config_vbi: return "vbi";
|
case pvr2_config_vbi: return "vbi";
|
||||||
case pvr2_config_radio: return "radio";
|
case pvr2_config_pcm: return "pcm";
|
||||||
|
case pvr2_config_rawvideo: return "raw video";
|
||||||
}
|
}
|
||||||
return "<unknown>";
|
return "<unknown>";
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,10 +72,11 @@
|
||||||
PVR2_SUBSYS_RUN_ALL )
|
PVR2_SUBSYS_RUN_ALL )
|
||||||
|
|
||||||
enum pvr2_config {
|
enum pvr2_config {
|
||||||
pvr2_config_empty,
|
pvr2_config_empty, /* No configuration */
|
||||||
pvr2_config_mpeg,
|
pvr2_config_mpeg, /* Encoded / compressed video */
|
||||||
pvr2_config_vbi,
|
pvr2_config_vbi, /* Standard vbi info */
|
||||||
pvr2_config_radio,
|
pvr2_config_pcm, /* Audio raw pcm stream */
|
||||||
|
pvr2_config_rawvideo, /* Video raw frames */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum pvr2_v4l_type {
|
enum pvr2_v4l_type {
|
||||||
|
|
|
@ -40,7 +40,10 @@ struct pvr2_v4l2_dev {
|
||||||
struct video_device devbase; /* MUST be first! */
|
struct video_device devbase; /* MUST be first! */
|
||||||
struct pvr2_v4l2 *v4lp;
|
struct pvr2_v4l2 *v4lp;
|
||||||
struct pvr2_context_stream *stream;
|
struct pvr2_context_stream *stream;
|
||||||
enum pvr2_config config;
|
/* Information about this device: */
|
||||||
|
enum pvr2_config config; /* Expected stream format */
|
||||||
|
int v4l_type; /* V4L defined type for this device node */
|
||||||
|
enum pvr2_v4l_type minor_type; /* pvr2-understood minor device type */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pvr2_v4l2_fh {
|
struct pvr2_v4l2_fh {
|
||||||
|
@ -163,6 +166,18 @@ static struct v4l2_format pvr_format [] = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static const char *get_v4l_name(int v4l_type)
|
||||||
|
{
|
||||||
|
switch (v4l_type) {
|
||||||
|
case VFL_TYPE_GRABBER: return "video";
|
||||||
|
case VFL_TYPE_RADIO: return "radio";
|
||||||
|
case VFL_TYPE_VBI: return "vbi";
|
||||||
|
default: return "?";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* pvr_ioctl()
|
* pvr_ioctl()
|
||||||
*
|
*
|
||||||
|
@ -521,6 +536,13 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
|
||||||
|
|
||||||
case VIDIOC_STREAMON:
|
case VIDIOC_STREAMON:
|
||||||
{
|
{
|
||||||
|
if (!fh->dev_info->stream) {
|
||||||
|
/* No stream defined for this node. This means
|
||||||
|
that we're not currently allowed to stream from
|
||||||
|
this node. */
|
||||||
|
ret = -EPERM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
ret = pvr2_hdw_set_stream_type(hdw,dev_info->config);
|
ret = pvr2_hdw_set_stream_type(hdw,dev_info->config);
|
||||||
if (ret < 0) return ret;
|
if (ret < 0) return ret;
|
||||||
ret = pvr2_hdw_set_streaming(hdw,!0);
|
ret = pvr2_hdw_set_streaming(hdw,!0);
|
||||||
|
@ -529,6 +551,13 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
|
||||||
|
|
||||||
case VIDIOC_STREAMOFF:
|
case VIDIOC_STREAMOFF:
|
||||||
{
|
{
|
||||||
|
if (!fh->dev_info->stream) {
|
||||||
|
/* No stream defined for this node. This means
|
||||||
|
that we're not currently allowed to stream from
|
||||||
|
this node. */
|
||||||
|
ret = -EPERM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
ret = pvr2_hdw_set_streaming(hdw,0);
|
ret = pvr2_hdw_set_streaming(hdw,0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -734,26 +763,12 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
|
||||||
|
|
||||||
static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
|
static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
|
||||||
{
|
{
|
||||||
enum pvr2_config cfg = dip->config;
|
|
||||||
int minor_id = dip->devbase.minor;
|
int minor_id = dip->devbase.minor;
|
||||||
enum pvr2_v4l_type pvt;
|
|
||||||
struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw;
|
struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw;
|
||||||
|
enum pvr2_config cfg = dip->config;
|
||||||
|
int v4l_type = dip->v4l_type;
|
||||||
|
|
||||||
switch (cfg) {
|
pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1);
|
||||||
case pvr2_config_mpeg:
|
|
||||||
pvt = pvr2_v4l_type_video;
|
|
||||||
break;
|
|
||||||
case pvr2_config_vbi:
|
|
||||||
pvt = pvr2_v4l_type_vbi;
|
|
||||||
break;
|
|
||||||
case pvr2_config_radio:
|
|
||||||
pvt = pvr2_v4l_type_radio;
|
|
||||||
break;
|
|
||||||
default: /* paranoia */
|
|
||||||
pvt = pvr2_v4l_type_video;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
pvr2_hdw_v4l_store_minor_number(hdw,pvt,-1);
|
|
||||||
|
|
||||||
/* Paranoia */
|
/* Paranoia */
|
||||||
dip->v4lp = NULL;
|
dip->v4lp = NULL;
|
||||||
|
@ -763,25 +778,9 @@ static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
|
||||||
are gone. */
|
are gone. */
|
||||||
video_unregister_device(&dip->devbase);
|
video_unregister_device(&dip->devbase);
|
||||||
|
|
||||||
switch (cfg) {
|
printk(KERN_INFO "pvrusb2: unregistered device %s%u [%s]\n",
|
||||||
case pvr2_config_mpeg:
|
get_v4l_name(v4l_type),minor_id & 0x1f,
|
||||||
printk(KERN_INFO "pvrusb2: unregistered device video%d [%s]\n",
|
pvr2_config_get_name(cfg));
|
||||||
minor_id & 0x1f,
|
|
||||||
pvr2_config_get_name(cfg));
|
|
||||||
break;
|
|
||||||
case pvr2_config_radio:
|
|
||||||
printk(KERN_INFO "pvrusb2: unregistered device radio%d [%s]\n",
|
|
||||||
minor_id & 0x1f,
|
|
||||||
pvr2_config_get_name(cfg));
|
|
||||||
break;
|
|
||||||
case pvr2_config_vbi:
|
|
||||||
printk(KERN_INFO "pvrusb2: unregistered device vbi%d [%s]\n",
|
|
||||||
minor_id & 0x1f,
|
|
||||||
pvr2_config_get_name(cfg));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -852,17 +851,6 @@ static int pvr2_v4l2_release(struct inode *inode, struct file *file)
|
||||||
fhp->rhp = NULL;
|
fhp->rhp = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fhp->dev_info->config == pvr2_config_radio) {
|
|
||||||
int ret;
|
|
||||||
struct pvr2_hdw *hdw;
|
|
||||||
hdw = fhp->channel.mc_head->hdw;
|
|
||||||
if ((ret = pvr2_ctrl_set_value(
|
|
||||||
pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
|
|
||||||
PVR2_CVAL_INPUT_TV))) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
v4l2_prio_close(&vp->prio, &fhp->prio);
|
v4l2_prio_close(&vp->prio, &fhp->prio);
|
||||||
file->private_data = NULL;
|
file->private_data = NULL;
|
||||||
|
|
||||||
|
@ -929,7 +917,7 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file)
|
||||||
So execute that here. Note that you can get the
|
So execute that here. Note that you can get the
|
||||||
IDENTICAL effect merely by opening the normal video
|
IDENTICAL effect merely by opening the normal video
|
||||||
device and setting the input appropriately. */
|
device and setting the input appropriately. */
|
||||||
if (dip->config == pvr2_config_radio) {
|
if (dip->v4l_type == VFL_TYPE_RADIO) {
|
||||||
pvr2_ctrl_set_value(
|
pvr2_ctrl_set_value(
|
||||||
pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
|
pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
|
||||||
PVR2_CVAL_INPUT_RADIO);
|
PVR2_CVAL_INPUT_RADIO);
|
||||||
|
@ -968,6 +956,12 @@ static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
|
||||||
struct pvr2_hdw *hdw;
|
struct pvr2_hdw *hdw;
|
||||||
if (fh->rhp) return 0;
|
if (fh->rhp) return 0;
|
||||||
|
|
||||||
|
if (!fh->dev_info->stream) {
|
||||||
|
/* No stream defined for this node. This means that we're
|
||||||
|
not currently allowed to stream from this node. */
|
||||||
|
return -EPERM;
|
||||||
|
}
|
||||||
|
|
||||||
/* First read() attempt. Try to claim the stream and start
|
/* First read() attempt. Try to claim the stream and start
|
||||||
it... */
|
it... */
|
||||||
if ((ret = pvr2_channel_claim_stream(&fh->channel,
|
if ((ret = pvr2_channel_claim_stream(&fh->channel,
|
||||||
|
@ -1032,12 +1026,6 @@ static ssize_t pvr2_v4l2_read(struct file *file,
|
||||||
return tcnt;
|
return tcnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fh->dev_info->config == pvr2_config_radio) {
|
|
||||||
/* Radio device nodes on this device
|
|
||||||
cannot be read or written. */
|
|
||||||
return -EPERM;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fh->rhp) {
|
if (!fh->rhp) {
|
||||||
ret = pvr2_v4l2_iosetup(fh);
|
ret = pvr2_v4l2_iosetup(fh);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -1072,12 +1060,6 @@ static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait)
|
||||||
return mask;
|
return mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fh->dev_info->config == pvr2_config_radio) {
|
|
||||||
/* Radio device nodes on this device
|
|
||||||
cannot be read or written. */
|
|
||||||
return -EPERM;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fh->rhp) {
|
if (!fh->rhp) {
|
||||||
ret = pvr2_v4l2_iosetup(fh);
|
ret = pvr2_v4l2_iosetup(fh);
|
||||||
if (ret) return POLLERR;
|
if (ret) return POLLERR;
|
||||||
|
@ -1119,29 +1101,31 @@ static struct video_device vdev_template = {
|
||||||
|
|
||||||
static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
|
static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
|
||||||
struct pvr2_v4l2 *vp,
|
struct pvr2_v4l2 *vp,
|
||||||
enum pvr2_config cfg)
|
int v4l_type)
|
||||||
{
|
{
|
||||||
int mindevnum;
|
int mindevnum;
|
||||||
int unit_number;
|
int unit_number;
|
||||||
int v4l_type;
|
int *nr_ptr = 0;
|
||||||
enum pvr2_v4l_type pvt;
|
|
||||||
dip->v4lp = vp;
|
dip->v4lp = vp;
|
||||||
dip->config = cfg;
|
|
||||||
|
|
||||||
|
|
||||||
switch (dip->config) {
|
dip->v4l_type = v4l_type;
|
||||||
case pvr2_config_mpeg:
|
switch (v4l_type) {
|
||||||
v4l_type = VFL_TYPE_GRABBER;
|
case VFL_TYPE_GRABBER:
|
||||||
pvt = pvr2_v4l_type_video;
|
|
||||||
dip->stream = &vp->channel.mc_head->video_stream;
|
dip->stream = &vp->channel.mc_head->video_stream;
|
||||||
|
dip->config = pvr2_config_mpeg;
|
||||||
|
dip->minor_type = pvr2_v4l_type_video;
|
||||||
|
nr_ptr = video_nr;
|
||||||
break;
|
break;
|
||||||
case pvr2_config_vbi:
|
case VFL_TYPE_VBI:
|
||||||
v4l_type = VFL_TYPE_VBI;
|
dip->config = pvr2_config_vbi;
|
||||||
pvt = pvr2_v4l_type_vbi;
|
dip->minor_type = pvr2_v4l_type_vbi;
|
||||||
|
nr_ptr = vbi_nr;
|
||||||
break;
|
break;
|
||||||
case pvr2_config_radio:
|
case VFL_TYPE_RADIO:
|
||||||
v4l_type = VFL_TYPE_RADIO;
|
dip->config = pvr2_config_pcm;
|
||||||
pvt = pvr2_v4l_type_radio;
|
dip->minor_type = pvr2_v4l_type_radio;
|
||||||
|
nr_ptr = radio_nr;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* Bail out (this should be impossible) */
|
/* Bail out (this should be impossible) */
|
||||||
|
@ -1151,7 +1135,7 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* radio device doesn 't need its own stream */
|
/* radio device doesn 't need its own stream */
|
||||||
if (!dip->stream && dip->config != pvr2_config_radio) {
|
if (!dip->stream && dip->v4l_type == VFL_TYPE_GRABBER) {
|
||||||
err("Failed to set up pvrusb2 v4l dev"
|
err("Failed to set up pvrusb2 v4l dev"
|
||||||
" due to missing stream instance");
|
" due to missing stream instance");
|
||||||
return;
|
return;
|
||||||
|
@ -1162,46 +1146,22 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
|
||||||
|
|
||||||
mindevnum = -1;
|
mindevnum = -1;
|
||||||
unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw);
|
unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw);
|
||||||
if ((unit_number >= 0) && (unit_number < PVR_NUM)) {
|
if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) {
|
||||||
switch (v4l_type) {
|
mindevnum = nr_ptr[unit_number];
|
||||||
case VFL_TYPE_VBI:
|
|
||||||
mindevnum = vbi_nr[unit_number];
|
|
||||||
break;
|
|
||||||
case VFL_TYPE_RADIO:
|
|
||||||
mindevnum = radio_nr[unit_number];
|
|
||||||
break;
|
|
||||||
case VFL_TYPE_GRABBER:
|
|
||||||
default:
|
|
||||||
mindevnum = video_nr[unit_number];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if ((video_register_device(&dip->devbase, v4l_type, mindevnum) < 0) &&
|
if ((video_register_device(&dip->devbase,
|
||||||
(video_register_device(&dip->devbase, v4l_type, -1) < 0)) {
|
dip->v4l_type, mindevnum) < 0) &&
|
||||||
|
(video_register_device(&dip->devbase,
|
||||||
|
dip->v4l_type, -1) < 0)) {
|
||||||
err("Failed to register pvrusb2 v4l device");
|
err("Failed to register pvrusb2 v4l device");
|
||||||
}
|
}
|
||||||
switch (dip->config) {
|
|
||||||
case pvr2_config_mpeg:
|
printk(KERN_INFO "pvrusb2: registered device %s%u [%s]\n",
|
||||||
printk(KERN_INFO "pvrusb2: registered device video%d [%s]\n",
|
get_v4l_name(dip->v4l_type),dip->devbase.minor & 0x1f,
|
||||||
dip->devbase.minor & 0x1f,
|
pvr2_config_get_name(dip->config));
|
||||||
pvr2_config_get_name(dip->config));
|
|
||||||
break;
|
|
||||||
case pvr2_config_radio:
|
|
||||||
printk(KERN_INFO "pvrusb2: registered device radio%d [%s]\n",
|
|
||||||
dip->devbase.minor & 0x1f,
|
|
||||||
pvr2_config_get_name(dip->config));
|
|
||||||
break;
|
|
||||||
case pvr2_config_vbi:
|
|
||||||
printk(KERN_INFO "pvrusb2: registered device vbi%d [%s]\n",
|
|
||||||
dip->devbase.minor & 0x1f,
|
|
||||||
pvr2_config_get_name(dip->config));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,
|
pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,
|
||||||
pvt,dip->devbase.minor);
|
dip->minor_type,dip->devbase.minor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1228,8 +1188,8 @@ struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
|
||||||
vp->channel.check_func = pvr2_v4l2_internal_check;
|
vp->channel.check_func = pvr2_v4l2_internal_check;
|
||||||
|
|
||||||
/* register streams */
|
/* register streams */
|
||||||
pvr2_v4l2_dev_init(vp->dev_video,vp,pvr2_config_mpeg);
|
pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER);
|
||||||
pvr2_v4l2_dev_init(vp->dev_radio,vp,pvr2_config_radio);
|
pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
|
||||||
|
|
||||||
return vp;
|
return vp;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue