diff options
author | Mauro Carvalho Chehab <mchehab@infradead.org> | 2006-06-28 15:27:45 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2006-06-28 15:27:45 -0300 |
commit | 6bf77e770ed9aaba385261c18ec5c8f16a160e20 (patch) | |
tree | e5376cf1e1c8a9c07221f424e05dc22609427c91 /linux/drivers/media/video | |
parent | c265cca51af88f5caff789df5ead7de8662ccc0f (diff) | |
parent | 1719eff8a6f088e48ed02067ff1a00577f53d1aa (diff) | |
download | mediapointer-dvb-s2-6bf77e770ed9aaba385261c18ec5c8f16a160e20.tar.gz mediapointer-dvb-s2-6bf77e770ed9aaba385261c18ec5c8f16a160e20.tar.bz2 |
merge: http://linuxtv.org/hg/~hverkuil/tda9887
From: Mauro Carvalho Chehab <mchehab@infradead.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'linux/drivers/media/video')
30 files changed, 935 insertions, 511 deletions
diff --git a/linux/drivers/media/video/bt8xx/bttv-cards.c b/linux/drivers/media/video/bt8xx/bttv-cards.c index 584d91f1c..4b1ccf817 100644 --- a/linux/drivers/media/video/bt8xx/bttv-cards.c +++ b/linux/drivers/media/video/bt8xx/bttv-cards.c @@ -3580,11 +3580,6 @@ void __devinit bttv_init_card2(struct bttv *btv) /* Hybrid DVB card, DOES have a tda9887 */ if (btv->c.type == BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE) tda9887 = 1; - if((btv->tuner_type == TUNER_PHILIPS_FM1216ME_MK3) || - (btv->tuner_type == TUNER_PHILIPS_FM1236_MK3) || - (btv->tuner_type == TUNER_PHILIPS_FM1256_IH3) || - tda9887) - request_module("tda9887"); if (btv->tuner_type != UNSET) request_module("tuner"); } @@ -4942,7 +4937,7 @@ static void picolo_tetra_muxsel (struct bttv* btv, unsigned int input) * * The IVC120G security card has 4 i2c controlled TDA8540 matrix * swichers to provide 16 channels to MUX0. The TDA8540's have - * 4 indepedant outputs and as such the IVC120G also has the + * 4 independent outputs and as such the IVC120G also has the * optional "Monitor Out" bus. This allows the card to be looking * at one input while the monitor is looking at another. * diff --git a/linux/drivers/media/video/cx2341x.c b/linux/drivers/media/video/cx2341x.c index ae37d0513..f4da970a0 100644 --- a/linux/drivers/media/video/cx2341x.c +++ b/linux/drivers/media/video/cx2341x.c @@ -605,7 +605,7 @@ static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params) } int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, - struct v4l2_ext_controls *ctrls, int cmd) + struct v4l2_ext_controls *ctrls, unsigned int cmd) { int err = 0; int i; @@ -851,22 +851,22 @@ invalid: return "<invalid>"; } -void cx2341x_log_status(struct cx2341x_mpeg_params *p, int card_id) +void cx2341x_log_status(struct cx2341x_mpeg_params *p, const char *prefix) { int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1; /* Stream */ - printk(KERN_INFO "cx2341x-%d: Stream: %s\n", - card_id, + printk(KERN_INFO "%s: Stream: %s\n", + prefix, cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_TYPE)); /* Video */ - printk(KERN_INFO "cx2341x-%d: Video: %dx%d, %d fps\n", - card_id, + printk(KERN_INFO "%s: Video: %dx%d, %d fps\n", + prefix, p->width / (is_mpeg1 ? 2 : 1), p->height / (is_mpeg1 ? 2 : 1), p->is_50hz ? 25 : 30); - printk(KERN_INFO "cx2341x-%d: Video: %s, %s, %s, %d", - card_id, + printk(KERN_INFO "%s: Video: %s, %s, %s, %d", + prefix, cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ENCODING), cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ASPECT), cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_BITRATE_MODE), @@ -875,19 +875,19 @@ void cx2341x_log_status(struct cx2341x_mpeg_params *p, int card_id) printk(", Peak %d", p->video_bitrate_peak); } printk("\n"); - printk(KERN_INFO "cx2341x-%d: Video: GOP Size %d, %d B-Frames, %sGOP Closure, %s3:2 Pulldown\n", - card_id, + printk(KERN_INFO "%s: Video: GOP Size %d, %d B-Frames, %sGOP Closure, %s3:2 Pulldown\n", + prefix, p->video_gop_size, p->video_b_frames, p->video_gop_closure ? "" : "No ", p->video_pulldown ? "" : "No "); if (p->video_temporal_decimation) { - printk(KERN_INFO "cx2341x-%d: Video: Temporal Decimation %d\n", - card_id, p->video_temporal_decimation); + printk(KERN_INFO "%s: Video: Temporal Decimation %d\n", + prefix, p->video_temporal_decimation); } /* Audio */ - printk(KERN_INFO "cx2341x-%d: Audio: %s, %s, %s, %s", - card_id, + printk(KERN_INFO "%s: Audio: %s, %s, %s, %s", + prefix, cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ), cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING), cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_L2_BITRATE), @@ -901,18 +901,18 @@ void cx2341x_log_status(struct cx2341x_mpeg_params *p, int card_id) cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_CRC)); /* Encoding filters */ - printk(KERN_INFO "cx2341x-%d: Spatial Filter: %s, Luma %s, Chroma %s, %d\n", - card_id, + printk(KERN_INFO "%s: Spatial Filter: %s, Luma %s, Chroma %s, %d\n", + prefix, cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE), cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE), cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE), p->video_spatial_filter); - printk(KERN_INFO "cx2341x-%d: Temporal Filter: %s, %d\n", - card_id, + printk(KERN_INFO "%s: Temporal Filter: %s, %d\n", + prefix, cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE), p->video_temporal_filter); - printk(KERN_INFO "cx2341x-%d: Median Filter: %s, Luma [%d, %d], Chroma [%d, %d]\n", - card_id, + printk(KERN_INFO "%s: Median Filter: %s, Luma [%d, %d], Chroma [%d, %d]\n", + prefix, cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE), p->video_luma_median_filter_bottom, p->video_luma_median_filter_top, diff --git a/linux/drivers/media/video/cx88/cx88-alsa.c b/linux/drivers/media/video/cx88/cx88-alsa.c index 7085192bc..5fd27d3bf 100644 --- a/linux/drivers/media/video/cx88/cx88-alsa.c +++ b/linux/drivers/media/video/cx88/cx88-alsa.c @@ -710,7 +710,7 @@ static struct snd_kcontrol_new snd_cx88_capture_volume = { * Only boards with eeprom and byte 1 at eeprom=1 have it */ -static struct pci_device_id cx88_audio_pci_tbl[] = { +static struct pci_device_id cx88_audio_pci_tbl[] __devinitdata = { {0x14f1,0x8801,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, {0x14f1,0x8811,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, {0, } diff --git a/linux/drivers/media/video/cx88/cx88-blackbird.c b/linux/drivers/media/video/cx88/cx88-blackbird.c index 06cb07bba..cdc4e76fe 100644 --- a/linux/drivers/media/video/cx88/cx88-blackbird.c +++ b/linux/drivers/media/video/cx88/cx88-blackbird.c @@ -705,6 +705,39 @@ static struct videobuf_queue_ops blackbird_qops = { /* ------------------------------------------------------------------ */ +static const u32 *ctrl_classes[] = { + cx88_user_ctrls, + cx2341x_mpeg_ctrls, + NULL +}; + +static int blackbird_queryctrl(struct cx8802_dev *dev, struct v4l2_queryctrl *qctrl) +{ + qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id); + if (qctrl->id == 0) + return -EINVAL; + + /* Standard V4L2 controls */ + if (cx8800_ctrl_query(qctrl) == 0) + return 0; + + /* MPEG V4L2 controls */ + if (cx2341x_ctrl_query(&dev->params, qctrl)) + qctrl->flags |= V4L2_CTRL_FLAG_DISABLED; + return 0; +} + +static int blackbird_querymenu(struct cx8802_dev *dev, struct v4l2_querymenu *qmenu) +{ + struct v4l2_queryctrl qctrl; + + qctrl.id = qmenu->id; + blackbird_queryctrl(dev, &qctrl); + return v4l2_ctrl_query_menu(qmenu, &qctrl, cx2341x_ctrl_get_menu(qmenu->id)); +} + +/* ------------------------------------------------------------------ */ + static int mpeg_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg) { @@ -886,6 +919,29 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file, fh->mpegq.field); return 0; } + case VIDIOC_LOG_STATUS: + { + char name[32 + 2]; + + snprintf(name, sizeof(name), "%s/2", core->name); + printk("%s/2: ============ START LOG STATUS ============\n", + core->name); + cx88_call_i2c_clients(core, VIDIOC_LOG_STATUS, 0); + cx2341x_log_status(&dev->params, name); + printk("%s/2: ============= END LOG STATUS =============\n", + core->name); + return 0; + } + case VIDIOC_QUERYMENU: + return blackbird_querymenu(dev, arg); + case VIDIOC_QUERYCTRL: + { + struct v4l2_queryctrl *c = arg; + + if (blackbird_queryctrl(dev, c) == 0) + return 0; + return cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, mpeg_do_ioctl); + } default: return cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, mpeg_do_ioctl); diff --git a/linux/drivers/media/video/cx88/cx88-video.c b/linux/drivers/media/video/cx88/cx88-video.c index 9c2f0dd39..48c67d656 100644 --- a/linux/drivers/media/video/cx88/cx88-video.c +++ b/linux/drivers/media/video/cx88/cx88-video.c @@ -350,6 +350,51 @@ static struct cx88_ctrl cx8800_ctls[] = { }; static const int CX8800_CTLS = ARRAY_SIZE(cx8800_ctls); +const u32 cx88_user_ctrls[] = { + V4L2_CID_USER_CLASS, + V4L2_CID_BRIGHTNESS, + V4L2_CID_CONTRAST, + V4L2_CID_SATURATION, + V4L2_CID_HUE, + V4L2_CID_AUDIO_VOLUME, + V4L2_CID_AUDIO_BALANCE, + V4L2_CID_AUDIO_MUTE, + 0 +}; +EXPORT_SYMBOL(cx88_user_ctrls); + +static const u32 *ctrl_classes[] = { + cx88_user_ctrls, + NULL +}; + +int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl) +{ + int i; + + if (qctrl->id < V4L2_CID_BASE || + qctrl->id >= V4L2_CID_LASTP1) + return -EINVAL; + for (i = 0; i < CX8800_CTLS; i++) + if (cx8800_ctls[i].v.id == qctrl->id) + break; + if (i == CX8800_CTLS) { + *qctrl = no_ctl; + return 0; + } + *qctrl = cx8800_ctls[i].v; + return 0; +} +EXPORT_SYMBOL(cx8800_ctrl_query); + +static int cx88_queryctrl(struct v4l2_queryctrl *qctrl) +{ + qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id); + if (qctrl->id == 0) + return -EINVAL; + return cx8800_ctrl_query(qctrl); +} + /* ------------------------------------------------------------------- */ /* resource management */ @@ -517,8 +562,7 @@ static int restart_video_queue(struct cx8800_dev *dev, return 0; buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue); if (NULL == prev) { - list_del(&buf->vb.queue); - list_add_tail(&buf->vb.queue,&q->active); + list_move_tail(&buf->vb.queue, &q->active); start_video_dma(dev, q, buf); buf->vb.state = STATE_ACTIVE; buf->count = q->count++; @@ -529,8 +573,7 @@ static int restart_video_queue(struct cx8800_dev *dev, } else if (prev->vb.width == buf->vb.width && prev->vb.height == buf->vb.height && prev->fmt == buf->fmt) { - list_del(&buf->vb.queue); - list_add_tail(&buf->vb.queue,&q->active); + list_move_tail(&buf->vb.queue, &q->active); buf->vb.state = STATE_ACTIVE; buf->count = q->count++; prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); @@ -1652,20 +1695,8 @@ int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, case VIDIOC_QUERYCTRL: { struct v4l2_queryctrl *c = arg; - int i; - if (c->id < V4L2_CID_BASE || - c->id >= V4L2_CID_LASTP1) - return -EINVAL; - for (i = 0; i < CX8800_CTLS; i++) - if (cx8800_ctls[i].v.id == c->id) - break; - if (i == CX8800_CTLS) { - *c = no_ctl; - return 0; - } - *c = cx8800_ctls[i].v; - return 0; + return cx88_queryctrl(c); } case VIDIOC_G_CTRL: return get_control(core,arg); @@ -2191,8 +2222,6 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, /* load and configure helper modules */ if (TUNER_ABSENT != core->tuner_type) request_module("tuner"); - if (core->tda9887_conf) - request_module("tda9887"); /* register v4l devices */ dev->video_dev = cx88_vdev_init(core,dev->pci, diff --git a/linux/drivers/media/video/cx88/cx88.h b/linux/drivers/media/video/cx88/cx88.h index 86859f62c..dda58d2be 100644 --- a/linux/drivers/media/video/cx88/cx88.h +++ b/linux/drivers/media/video/cx88/cx88.h @@ -630,6 +630,8 @@ int cx8802_resume_common(struct pci_dev *pci_dev); extern int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, struct cx88_core *core, unsigned int cmd, void *arg, v4l2_kioctl driver_ioctl); +extern const u32 cx88_user_ctrls[]; +extern int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl); /* * Local variables: diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 33fe987dd..e7a104098 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -1679,8 +1679,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, request_module("tvp5150"); if (dev->has_tuner) request_module("tuner"); - if (dev->tda9887_conf) - request_module("tda9887"); #endif errCode = em28xx_config(dev); if (errCode) { diff --git a/linux/drivers/media/video/msp3400-driver.h b/linux/drivers/media/video/msp3400-driver.h index eeaafc5b4..33eac394d 100644 --- a/linux/drivers/media/video/msp3400-driver.h +++ b/linux/drivers/media/video/msp3400-driver.h @@ -94,8 +94,8 @@ struct msp_state { struct semaphore *notify; int rmmod:1; #endif - int restart:1; - int watch_stereo:1; + unsigned int restart:1; + unsigned int watch_stereo:1; }; /* msp3400-driver.c */ diff --git a/linux/drivers/media/video/pvrusb2/Kconfig b/linux/drivers/media/video/pvrusb2/Kconfig index 298b1c71a..7e727fe14 100644 --- a/linux/drivers/media/video/pvrusb2/Kconfig +++ b/linux/drivers/media/video/pvrusb2/Kconfig @@ -35,7 +35,7 @@ config VIDEO_PVRUSB2_24XXX warned. config VIDEO_PVRUSB2_SYSFS - bool "pvrusb2 sysfs support" + bool "pvrusb2 sysfs support (EXPERIMENTAL)" default y depends on VIDEO_PVRUSB2 && SYSFS && EXPERIMENTAL ---help--- diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-ctrl.c b/linux/drivers/media/video/pvrusb2/pvrusb2-ctrl.c index e55f43e44..20a1c7af7 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-ctrl.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-ctrl.c @@ -58,6 +58,8 @@ int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *cptr,int mask,int val) if (val >= cptr->info->def.type_enum.count) { break; } + } else if (cptr->info->type != pvr2_ctl_bool) { + break; } ret = cptr->info->set_value(cptr,mask,val); } else { @@ -217,6 +219,32 @@ int pvr2_ctrl_get_valname(struct pvr2_ctrl *cptr,int val, } +/* Return V4L ID for this control or zero if none */ +int pvr2_ctrl_get_v4lid(struct pvr2_ctrl *cptr) +{ + if (!cptr) return 0; + return cptr->info->v4l_id; +} + + +unsigned int pvr2_ctrl_get_v4lflags(struct pvr2_ctrl *cptr) +{ + unsigned int flags = 0; + + if (cptr->info->get_v4lflags) { + flags = cptr->info->get_v4lflags(cptr); + } + + if (cptr->info->set_value) { + flags &= ~V4L2_CTRL_FLAG_READ_ONLY; + } else { + flags |= V4L2_CTRL_FLAG_READ_ONLY; + } + + return flags; +} + + /* Return true if control is writable */ int pvr2_ctrl_is_writable(struct pvr2_ctrl *cptr) { @@ -313,6 +341,14 @@ static unsigned int gen_bitmask_string(int msk,int val,int msk_only, } +static const char *boolNames[] = { + "false", + "true", + "no", + "yes", +}; + + static int parse_token(const char *ptr,unsigned int len, int *valptr, const char **names,unsigned int namecnt) @@ -343,7 +379,7 @@ static int parse_token(const char *ptr,unsigned int len, *valptr = simple_strtol(buf,&p2,0); if (negfl) *valptr = -(*valptr); if (*p2) return -EINVAL; - return 0; + return 1; } @@ -458,21 +494,31 @@ int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr, LOCK_TAKE(cptr->hdw->big_lock); do { if (cptr->info->type == pvr2_ctl_int) { ret = parse_token(ptr,len,valptr,0,0); - if ((ret == 0) && + if ((ret >= 0) && ((*valptr < cptr->info->def.type_int.min_value) || (*valptr > cptr->info->def.type_int.max_value))) { - ret = -EINVAL; + ret = -ERANGE; } if (maskptr) *maskptr = ~0; + } else if (cptr->info->type == pvr2_ctl_bool) { + ret = parse_token( + ptr,len,valptr,boolNames, + sizeof(boolNames)/sizeof(boolNames[0])); + if (ret == 1) { + *valptr = *valptr ? !0 : 0; + } else if (ret == 0) { + *valptr = (*valptr & 1) ? !0 : 0; + } + if (maskptr) *maskptr = 1; } else if (cptr->info->type == pvr2_ctl_enum) { ret = parse_token( ptr,len,valptr, cptr->info->def.type_enum.value_names, cptr->info->def.type_enum.count); - if ((ret == 0) && + if ((ret >= 0) && ((*valptr < 0) || (*valptr >= cptr->info->def.type_enum.count))) { - ret = -EINVAL; + ret = -ERANGE; } if (maskptr) *maskptr = ~0; } else if (cptr->info->type == pvr2_ctl_bitmask) { @@ -498,6 +544,9 @@ int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl *cptr, if (cptr->info->type == pvr2_ctl_int) { *len = scnprintf(buf,maxlen,"%d",val); ret = 0; + } else if (cptr->info->type == pvr2_ctl_bool) { + *len = scnprintf(buf,maxlen,"%s",val ? "true" : "false"); + ret = 0; } else if (cptr->info->type == pvr2_ctl_enum) { const char **names; names = cptr->info->def.type_enum.value_names; diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-ctrl.h b/linux/drivers/media/video/pvrusb2/pvrusb2-ctrl.h index 9d74151a3..c1680053c 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-ctrl.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-ctrl.h @@ -27,6 +27,7 @@ enum pvr2_ctl_type { pvr2_ctl_int = 0, pvr2_ctl_enum = 1, pvr2_ctl_bitmask = 2, + pvr2_ctl_bool = 3, }; @@ -70,6 +71,13 @@ int pvr2_ctrl_get_valname(struct pvr2_ctrl *,int,char *,unsigned int, /* Return true if control is writable */ int pvr2_ctrl_is_writable(struct pvr2_ctrl *); +/* Return V4L flags value for control (or zero if there is no v4l control + actually under this control) */ +unsigned int pvr2_ctrl_get_v4lflags(struct pvr2_ctrl *); + +/* Return V4L ID for this control or zero if none */ +int pvr2_ctrl_get_v4lid(struct pvr2_ctrl *); + /* Return true if control has custom symbolic representation */ int pvr2_ctrl_has_custom_symbols(struct pvr2_ctrl *); diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c index 47e7f5dbd..27eadaff7 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c @@ -104,12 +104,15 @@ static void set_audio(struct pvr2_v4l_cx2584x *ctxt) hdw->srate_val); switch (hdw->srate_val) { default: - case PVR2_CVAL_SRATE_48: + case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000: val = 48000; break; - case PVR2_CVAL_SRATE_44_1: + case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100: val = 44100; break; + case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000: + val = 32000; + break; } pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_AUDIO_CLOCK_FREQ,&val); } diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c index 958500466..b6ee5b112 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c @@ -23,41 +23,11 @@ #include "compat.h" #include <linux/device.h> // for linux/firmware.h #include <linux/firmware.h> -#include <linux/videodev2.h> -#include <media/cx2341x.h> #include "pvrusb2-util.h" #include "pvrusb2-encoder.h" #include "pvrusb2-hdw-internal.h" #include "pvrusb2-debug.h" -static u32 pvr_tbl_emphasis [] = { - [PVR2_CVAL_AUDIOEMPHASIS_NONE] = 0x0 << 12, - [PVR2_CVAL_AUDIOEMPHASIS_50_15] = 0x1 << 12, - [PVR2_CVAL_AUDIOEMPHASIS_CCITT] = 0x3 << 12, -}; - -static u32 pvr_tbl_srate[] = { - [PVR2_CVAL_SRATE_48] = 0x01, - [PVR2_CVAL_SRATE_44_1] = 0x00, -}; - -static u32 pvr_tbl_audiobitrate[] = { - [PVR2_CVAL_AUDIOBITRATE_384] = 0xe << 4, - [PVR2_CVAL_AUDIOBITRATE_320] = 0xd << 4, - [PVR2_CVAL_AUDIOBITRATE_256] = 0xc << 4, - [PVR2_CVAL_AUDIOBITRATE_224] = 0xb << 4, - [PVR2_CVAL_AUDIOBITRATE_192] = 0xa << 4, - [PVR2_CVAL_AUDIOBITRATE_160] = 0x9 << 4, - [PVR2_CVAL_AUDIOBITRATE_128] = 0x8 << 4, - [PVR2_CVAL_AUDIOBITRATE_112] = 0x7 << 4, - [PVR2_CVAL_AUDIOBITRATE_96] = 0x6 << 4, - [PVR2_CVAL_AUDIOBITRATE_80] = 0x5 << 4, - [PVR2_CVAL_AUDIOBITRATE_64] = 0x4 << 4, - [PVR2_CVAL_AUDIOBITRATE_56] = 0x3 << 4, - [PVR2_CVAL_AUDIOBITRATE_48] = 0x2 << 4, - [PVR2_CVAL_AUDIOBITRATE_32] = 0x1 << 4, - [PVR2_CVAL_AUDIOBITRATE_VBR] = 0x0 << 4, -}; /* Firmware mailbox flags - definitions found from ivtv */ @@ -66,7 +36,7 @@ static u32 pvr_tbl_audiobitrate[] = { #define IVTV_MBOX_DRIVER_BUSY 0x00000001 -static int pvr2_write_encoder_words(struct pvr2_hdw *hdw, +static int pvr2_encoder_write_words(struct pvr2_hdw *hdw, const u32 *data, unsigned int dlen) { unsigned int idx; @@ -107,7 +77,7 @@ static int pvr2_write_encoder_words(struct pvr2_hdw *hdw, } -static int pvr2_read_encoder_words(struct pvr2_hdw *hdw,int statusFl, +static int pvr2_encoder_read_words(struct pvr2_hdw *hdw,int statusFl, u32 *data, unsigned int dlen) { unsigned int idx; @@ -148,15 +118,46 @@ static int pvr2_read_encoder_words(struct pvr2_hdw *hdw,int statusFl, } -static int pvr2_write_encoder_vcmd (struct pvr2_hdw *hdw, u8 cmd, - int args, ...) +/* This prototype is set up to be compatible with the + cx2341x_mbox_func prototype in cx2341x.h, which should be in + kernels 2.6.18 or later. We do this so that we can enable + cx2341x.ko to write to our encoder (by handing it a pointer to this + function). For earlier kernels this doesn't really matter. */ +static int pvr2_encoder_cmd(void *ctxt, + int cmd, + int arg_cnt_send, + int arg_cnt_recv, + u32 *argp) { unsigned int poll_count; int ret = 0; - va_list vl; unsigned int idx; + /* These sizes look to be limited by the FX2 firmware implementation */ u32 wrData[16]; - u32 rdData[32]; + u32 rdData[16]; + struct pvr2_hdw *hdw = (struct pvr2_hdw *)ctxt; + +#if 0 + { + char buf[150]; + unsigned int ccnt,bcnt; + + bcnt = scnprintf(buf,sizeof(buf),"Encoder Cmd %02x (",cmd); + for (idx = 0; idx < arg_cnt_send; idx++) { + if (idx) { + ccnt = scnprintf(buf+bcnt, + sizeof(buf)-bcnt," "); + bcnt += ccnt; + } + ccnt = scnprintf(buf+bcnt,sizeof(buf)-bcnt, + "0x%x",argp[idx]); + bcnt += ccnt; + } + ccnt = scnprintf(buf+bcnt,sizeof(buf)-bcnt,")"); + bcnt += ccnt; + pvr2_trace(PVR2_TRACE_ENCODER,"%.*s",bcnt,buf); + } +#endif /* @@ -190,6 +191,28 @@ static int pvr2_write_encoder_vcmd (struct pvr2_hdw *hdw, u8 cmd, */ + if (arg_cnt_send > (sizeof(wrData)/sizeof(wrData[0]))-4) { + pvr2_trace( + PVR2_TRACE_ERROR_LEGS, + "Failed to write cx23416 command" + " - too many input arguments" + " (was given %u limit %u)", + arg_cnt_send, + (unsigned int)(sizeof(wrData)/sizeof(wrData[0])) - 4); + return -EINVAL; + } + + if (arg_cnt_recv > (sizeof(rdData)/sizeof(rdData[0]))-4) { + pvr2_trace( + PVR2_TRACE_ERROR_LEGS, + "Failed to write cx23416 command" + " - too many return arguments" + " (was given %u limit %u)", + arg_cnt_recv, + (unsigned int)(sizeof(rdData)/sizeof(rdData[0])) - 4); + return -EINVAL; + } + LOCK_TAKE(hdw->ctl_lock); do { @@ -197,25 +220,22 @@ static int pvr2_write_encoder_vcmd (struct pvr2_hdw *hdw, u8 cmd, wrData[1] = cmd; wrData[2] = 0; wrData[3] = 0x00060000; - va_start(vl, args); - for (idx = 0; idx < args; idx++) { - wrData[idx+4] = va_arg(vl, u32); + for (idx = 0; idx < arg_cnt_send; idx++) { + wrData[idx+4] = argp[idx]; } - va_end(vl); - args += 4; - while (args < sizeof(wrData)/sizeof(wrData[0])) { - wrData[args++] = 0; + for (; idx < (sizeof(wrData)/sizeof(wrData[0]))-4; idx++) { + wrData[idx+4] = 0; } - ret = pvr2_write_encoder_words(hdw,wrData,args); + ret = pvr2_encoder_write_words(hdw,wrData,idx); if (ret) break; wrData[0] = IVTV_MBOX_DRIVER_DONE|IVTV_MBOX_DRIVER_BUSY; - ret = pvr2_write_encoder_words(hdw,wrData,1); + ret = pvr2_encoder_write_words(hdw,wrData,1); if (ret) break; poll_count = 0; while (1) { if (poll_count < 10000000) poll_count++; - ret = pvr2_read_encoder_words(hdw,!0,rdData,1); + ret = pvr2_encoder_read_words(hdw,!0,rdData,1); if (ret) break; if (rdData[0] & IVTV_MBOX_FIRMWARE_DONE) { break; @@ -229,7 +249,7 @@ static int pvr2_write_encoder_vcmd (struct pvr2_hdw *hdw, u8 cmd, pvr2_trace( PVR2_TRACE_ERROR_LEGS, "Encoder command: 0x%02x",cmd); - for (idx = 4; idx < args; idx++) { + for (idx = 4; idx < arg_cnt_send; idx++) { pvr2_trace( PVR2_TRACE_ERROR_LEGS, "Encoder arg%d: 0x%08x", @@ -246,8 +266,11 @@ static int pvr2_write_encoder_vcmd (struct pvr2_hdw *hdw, u8 cmd, } if (ret) break; wrData[0] = 0x7; - ret = pvr2_read_encoder_words(hdw,0,rdData,16); + ret = pvr2_encoder_read_words( + hdw,0,rdData, + sizeof(rdData)/sizeof(rdData[0])); if (ret) break; +#if 0 for (idx = 0; idx < args; idx++) { if (rdData[idx] != wrData[idx]) { pvr2_trace( @@ -257,9 +280,13 @@ static int pvr2_write_encoder_vcmd (struct pvr2_hdw *hdw, u8 cmd, idx,wrData[idx],rdData[idx]); } } +#endif + for (idx = 0; idx < arg_cnt_recv; idx++) { + argp[idx] = rdData[idx+4]; + } wrData[0] = 0x0; - ret = pvr2_write_encoder_words(hdw,wrData,1); + ret = pvr2_encoder_write_words(hdw,wrData,1); if (ret) break; } while(0); LOCK_GIVE(hdw->ctl_lock); @@ -267,176 +294,94 @@ static int pvr2_write_encoder_vcmd (struct pvr2_hdw *hdw, u8 cmd, return ret; } -int pvr2_encoder_configure(struct pvr2_hdw *hdw) + +static int pvr2_encoder_vcmd(struct pvr2_hdw *hdw, int cmd, + int args, ...) { - int ret = 0, audio, i; - v4l2_std_id vd_std = hdw->std_mask_cur; - int height = hdw->res_ver_val; - int width = hdw->res_hor_val; - int height_full = !hdw->interlace_val; - - int is_30fps, is_ntsc; - - if (vd_std & V4L2_STD_NTSC) { - is_ntsc=1; - is_30fps=1; - } else if (vd_std & V4L2_STD_PAL_M) { - is_ntsc=0; - is_30fps=1; - } else { - is_ntsc=0; - is_30fps=0; + va_list vl; + unsigned int idx; + u32 data[12]; + + if (args > sizeof(data)/sizeof(data[0])) { + pvr2_trace( + PVR2_TRACE_ERROR_LEGS, + "Failed to write cx23416 command" + " - too many arguments" + " (was given %u limit %u)", + args,(unsigned int)(sizeof(data)/sizeof(data[0]))); + return -EINVAL; } - pvr2_trace(PVR2_TRACE_ENCODER,"pvr2_encoder_configure"); - - /* set stream output port. Some notes here: The ivtv-derived - encoder documentation says that this command only gets a - single argument. However the Windows driver for the model - 29xxx series hardware has been sending 0x01 as a second - argument, while the Windows driver for the model 24xxx - series hardware has been sending 0x02 as a second argument. - Confusing matters further are the observations that 0x01 - for that second argument simply won't work on the 24xxx - hardware, while 0x02 will work on the 29xxx - except that - when we use 0x02 then xawtv breaks due to a loss of - synchronization with the mpeg packet headers. While xawtv - should be fixed to let it resync better (I did try to - contact Gerd about this but he has not answered), it has - also been determined that sending 0x00 as this mystery - second argument seems to work on both hardware models AND - xawtv works again. So we're going to send 0x00. */ - ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_OUTPUT_PORT, 2, - 0x01, 0x00); - - /* set the Program Index Information. We want I,P,B frames (max 400) */ - ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_PGM_INDEX_INFO, 2, - 0x07, 0x0190); - - /* NOTE : windows driver sends these */ - /* Mike Isely <isely@pobox.com> 7-Mar-2006 The windows driver - sends the following commands but if we do the same then - many apps are no longer able to read the video stream. - Leaving these out seems to do no harm at all, so they're - commented out for that reason. */ -#ifdef notdef - ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 5,0,0,0); - ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 3,1,0,0); - ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 8,0,0,0); - ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 4,1,0,0); - ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 0,3,0,0); - ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_MISC,4,15,0,0,0); -#endif + va_start(vl, args); + for (idx = 0; idx < args; idx++) { + data[idx] = va_arg(vl, u32); + } + va_end(vl); - /* Strange compared to ivtv data. */ -#if 0 - ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, - 0x0120, 0x0120); - ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, - 0x0131, 0x0131); -#endif - ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, - 0xf0, 0xf0); + return pvr2_encoder_cmd(hdw,cmd,args,0,data); +} - /* setup firmware to notify us about some events (don't know why...) */ - ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_EVENT_NOTIFICATION, 4, - 0, 0, 0x10000000, 0xffffffff); +int pvr2_encoder_configure(struct pvr2_hdw *hdw) +{ + int ret; + pvr2_trace(PVR2_TRACE_ENCODER,"pvr2_encoder_configure" + " (cx2341x module)"); + hdw->enc_ctl_state.port = CX2341X_PORT_STREAMING; + hdw->enc_ctl_state.width = hdw->res_hor_val; + hdw->enc_ctl_state.height = hdw->res_ver_val; + hdw->enc_ctl_state.is_50hz = ((hdw->std_mask_cur & + (V4L2_STD_NTSC|V4L2_STD_PAL_M)) ? + 0 : 1); - /* set fps to 25 or 30 (1 or 0)*/ - ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_FRAME_RATE, 1, - is_30fps ? 0 : 1); + ret = 0; - /* set encoding resolution */ - ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_FRAME_SIZE, 2, - (height_full ? height : (height / 2)), - width); - /* set encoding aspect ratio to 4:3 */ - ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_ASPECT_RATIO, 1, - 0x02); + if (!ret) ret = pvr2_encoder_vcmd( + hdw,CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, + 0xf0, 0xf0); - /* VBI */ + /* setup firmware to notify us about some events (don't know why...) */ + if (!ret) ret = pvr2_encoder_vcmd( + hdw,CX2341X_ENC_SET_EVENT_NOTIFICATION, 4, + 0, 0, 0x10000000, 0xffffffff); + + if (!ret) ret = pvr2_encoder_vcmd( + hdw,CX2341X_ENC_SET_VBI_LINE, 5, + 0xffffffff,0,0,0,0); + + if (ret) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Failed to configure cx32416"); + return ret; + } - if (hdw->config == pvr2_config_vbi) { - int lines = 2 * (is_30fps ? 12 : 18); - int size = (4*((lines*1443+3)/4)) / lines; - ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_VBI_CONFIG, 7, - 0xbd05, 1, 4, - 0x25256262, 0x387f7f7f, - lines , size); -// 0x25256262, 0x13135454, lines , size); - /* select vbi lines */ -#define line_used(l) (is_30fps ? (l >= 10 && l <= 21) : (l >= 6 && l <= 23)) - for (i = 2 ; i <= 24 ; i++){ - ret |= pvr2_write_encoder_vcmd( - hdw,CX2341X_ENC_SET_VBI_LINE, 5, - i-1,line_used(i), 0, 0, 0); - ret |= pvr2_write_encoder_vcmd( - hdw,CX2341X_ENC_SET_VBI_LINE, 5, - (i-1) | (1 << 31), - line_used(i), 0, 0, 0); - } - } else { - ret |= pvr2_write_encoder_vcmd( - hdw,CX2341X_ENC_SET_VBI_LINE, 5, - 0xffffffff,0,0,0,0); + ret = cx2341x_update(hdw,pvr2_encoder_cmd, + (hdw->enc_cur_valid ? &hdw->enc_cur_state : 0), + &hdw->enc_ctl_state); + if (ret) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Error from cx2341x module code=%d",ret); + return ret; } - /* set stream type, depending on resolution. */ - ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_STREAM_TYPE, 1, - height_full ? 0x0a : 0x0b); - /* set video bitrate */ - ret |= pvr2_write_encoder_vcmd( - hdw, CX2341X_ENC_SET_BIT_RATE, 3, - (hdw->vbr_val ? 1 : 0), - hdw->videobitrate_val, - hdw->videopeak_val / 400); - /* setup GOP structure (GOP size = 0f or 0c, 3-1 = 2 B-frames) */ - ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_GOP_PROPERTIES, 2, - is_30fps ? 0x0f : 0x0c, 0x03); - - /* enable 3:2 pulldown */ - ret |= pvr2_write_encoder_vcmd(hdw,CX2341X_ENC_SET_3_2_PULLDOWN,1,0); - - /* set GOP open/close property (open) */ - ret |= pvr2_write_encoder_vcmd(hdw,CX2341X_ENC_SET_GOP_CLOSURE,1,0); - - /* set audio stream properties 0x40b9? 0100 0000 1011 1001 */ - audio = (pvr_tbl_audiobitrate[hdw->audiobitrate_val] | - pvr_tbl_srate[hdw->srate_val] | - hdw->audiolayer_val << 2 | - (hdw->audiocrc_val ? 1 << 14 : 0) | - pvr_tbl_emphasis[hdw->audioemphasis_val]); - - ret |= pvr2_write_encoder_vcmd(hdw,CX2341X_ENC_SET_AUDIO_PROPERTIES,1, - audio); - - /* set dynamic noise reduction filter to manual, Horiz/Vert */ - ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_DNR_FILTER_MODE, 2, - 0, 0x03); - - /* dynamic noise reduction filter param */ - ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_DNR_FILTER_PROPS, 2 - , 0, 0); - - /* dynamic noise reduction median filter */ - ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_CORING_LEVELS, 4, - 0, 0xff, 0, 0xff); - - /* spacial prefiler parameter */ - ret |= pvr2_write_encoder_vcmd(hdw, - CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, 2, - 0x01, 0x01); - - /* initialize video input */ - ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_INITIALIZE_INPUT, 0); - - if (!ret) { - hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_CFG); + ret = 0; + + if (!ret) ret = pvr2_encoder_vcmd( + hdw, CX2341X_ENC_INITIALIZE_INPUT, 0); + + if (ret) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Failed to initialize cx32416 video input"); + return ret; } - return ret; + hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_CFG); + memcpy(&hdw->enc_cur_state,&hdw->enc_ctl_state, + sizeof(struct cx2341x_mpeg_params)); + hdw->enc_cur_valid = !0; + return 0; } + int pvr2_encoder_start(struct pvr2_hdw *hdw) { int status; @@ -449,14 +394,14 @@ int pvr2_encoder_start(struct pvr2_hdw *hdw) pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000); if (hdw->config == pvr2_config_vbi) { - status = pvr2_write_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2, - 0x01,0x14); + status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2, + 0x01,0x14); } else if (hdw->config == pvr2_config_mpeg) { - status = pvr2_write_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2, - 0,0x13); + status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2, + 0,0x13); } else { - status = pvr2_write_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2, - 0,0x13); + status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2, + 0,0x13); } if (!status) { hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_RUN); @@ -472,14 +417,14 @@ int pvr2_encoder_stop(struct pvr2_hdw *hdw) pvr2_write_register(hdw, 0x0048, 0xffffffff); if (hdw->config == pvr2_config_vbi) { - status = pvr2_write_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3, - 0x01,0x01,0x14); + status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3, + 0x01,0x01,0x14); } else if (hdw->config == pvr2_config_mpeg) { - status = pvr2_write_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3, - 0x01,0,0x13); + status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3, + 0x01,0,0x13); } else { - status = pvr2_write_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3, - 0x01,0,0x13); + status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3, + 0x01,0,0x13); } /* change some GPIO data */ diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index 0d527abb5..cfec4d37c 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -44,6 +44,7 @@ #endif #include "pvrusb2-hdw.h" #include "pvrusb2-io.h" +#include <media/cx2341x.h> /* Legal values for the SRATE state variable */ #define PVR2_CVAL_SRATE_48 0 @@ -98,6 +99,7 @@ typedef int (*pvr2_ctlf_val_to_sym)(struct pvr2_ctrl *,int msk,int val, typedef int (*pvr2_ctlf_sym_to_val)(struct pvr2_ctrl *, const char *,unsigned int, int *mskp,int *valp); +typedef unsigned int (*pvr2_ctlf_get_v4lflags)(struct pvr2_ctrl *); /* This structure describes a specific control. A table of these is set up in pvrusb2-hdw.c. */ @@ -115,6 +117,7 @@ struct pvr2_ctl_info { pvr2_ctlf_sym_to_val sym_to_val; /* Custom convert symbol->value */ pvr2_ctlf_is_dirty is_dirty; /* Return true if dirty */ pvr2_ctlf_clear_dirty clear_dirty; /* Clear dirty state */ + pvr2_ctlf_get_v4lflags get_v4lflags;/* Retrieve v4l flags */ /* Control's type (int, enum, bitmask) */ enum pvr2_ctl_type type; @@ -149,6 +152,13 @@ struct pvr2_ctl_info { }; +/* Same as pvr2_ctl_info, but includes storage for the control description */ +#define PVR2_CTLD_INFO_DESC_SIZE 32 +struct pvr2_ctld_info { + struct pvr2_ctl_info info; + char desc[PVR2_CTLD_INFO_DESC_SIZE]; +}; + struct pvr2_ctrl { const struct pvr2_ctl_info *info; struct pvr2_hdw *hdw; @@ -329,6 +339,14 @@ struct pvr2_hdw { int flag_bilingual; struct pvr2_audio_stat *audio_stat; + /* Control state needed for cx2341x module */ + struct cx2341x_mpeg_params enc_cur_state; + struct cx2341x_mpeg_params enc_ctl_state; + /* True if an encoder attribute has changed */ + int enc_stale; + /* True if enc_cur_state is valid */ + int enc_cur_valid; + /* Control state */ #define VCREATE_DATA(lab) int lab##_val; int lab##_dirty VCREATE_DATA(brightness); @@ -340,22 +358,17 @@ struct pvr2_hdw { VCREATE_DATA(bass); VCREATE_DATA(treble); VCREATE_DATA(mute); - VCREATE_DATA(srate); - VCREATE_DATA(audiobitrate); - VCREATE_DATA(audiocrc); - VCREATE_DATA(audioemphasis); - VCREATE_DATA(vbr); - VCREATE_DATA(videobitrate); - VCREATE_DATA(videopeak); VCREATE_DATA(input); VCREATE_DATA(audiomode); VCREATE_DATA(res_hor); VCREATE_DATA(res_ver); - VCREATE_DATA(interlace); - VCREATE_DATA(audiolayer); + VCREATE_DATA(srate); #undef VCREATE_DATA + struct pvr2_ctld_info *mpeg_ctrl_info; + struct pvr2_ctrl *controls; + unsigned int control_cnt; }; int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw); diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 409343097..72eedc937 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -24,9 +24,8 @@ #include <linux/string.h> #include <linux/slab.h> #include <linux/firmware.h> -#include <asm/semaphore.h> #include <linux/videodev2.h> -#include <media/cx2341x.h> +#include <asm/semaphore.h> #include "pvrusb2.h" #include "pvrusb2-std.h" #include "pvrusb2-util.h" @@ -132,36 +131,105 @@ MODULE_PARM_DESC(tolerance,"specify stream error tolerance"); /* size of a firmware chunk */ #define FIRMWARE_CHUNK_SIZE 0x2000 +/* Define the list of additional controls we'll dynamically construct based + on query of the cx2341x module. */ +struct pvr2_mpeg_ids { + const char *strid; + int id; +}; +static const struct pvr2_mpeg_ids mpeg_ids[] = { + { + .strid = "audio_layer", + .id = V4L2_CID_MPEG_AUDIO_ENCODING, + },{ + .strid = "audio_bitrate", + .id = V4L2_CID_MPEG_AUDIO_L2_BITRATE, + },{ + /* Already using audio_mode elsewhere :-( */ + .strid = "mpeg_audio_mode", + .id = V4L2_CID_MPEG_AUDIO_MODE, + },{ + .strid = "mpeg_audio_mode_extension", + .id = V4L2_CID_MPEG_AUDIO_MODE_EXTENSION, + },{ + .strid = "audio_emphasis", + .id = V4L2_CID_MPEG_AUDIO_EMPHASIS, + },{ + .strid = "audio_crc", + .id = V4L2_CID_MPEG_AUDIO_CRC, + },{ + .strid = "video_aspect", + .id = V4L2_CID_MPEG_VIDEO_ASPECT, + },{ + .strid = "video_b_frames", + .id = V4L2_CID_MPEG_VIDEO_B_FRAMES, + },{ + .strid = "video_gop_size", + .id = V4L2_CID_MPEG_VIDEO_GOP_SIZE, + },{ + .strid = "video_gop_closure", + .id = V4L2_CID_MPEG_VIDEO_GOP_CLOSURE, + },{ + .strid = "video_pulldown", + .id = V4L2_CID_MPEG_VIDEO_PULLDOWN, + },{ + .strid = "video_bitrate_mode", + .id = V4L2_CID_MPEG_VIDEO_BITRATE_MODE, + },{ + .strid = "video_bitrate", + .id = V4L2_CID_MPEG_VIDEO_BITRATE, + },{ + .strid = "video_bitrate_peak", + .id = V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, + },{ + .strid = "video_temporal_decimation", + .id = V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION, + },{ + .strid = "stream_type", + .id = V4L2_CID_MPEG_STREAM_TYPE, + },{ + .strid = "video_spatial_filter_mode", + .id = V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE, + },{ + .strid = "video_spatial_filter", + .id = V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER, + },{ + .strid = "video_luma_spatial_filter_type", + .id = V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE, + },{ + .strid = "video_chroma_spatial_filter_type", + .id = V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE, + },{ + .strid = "video_temporal_filter_mode", + .id = V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE, + },{ + .strid = "video_temporal_filter", + .id = V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER, + },{ + .strid = "video_median_filter_type", + .id = V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE, + },{ + .strid = "video_luma_median_filter_top", + .id = V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP, + },{ + .strid = "video_luma_median_filter_bottom", + .id = V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM, + },{ + .strid = "video_chroma_median_filter_top", + .id = V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP, + },{ + .strid = "video_chroma_median_filter_bottom", + .id = V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM, + } +}; +#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", }; -static const char *control_values_audiobitrate[] = { - [PVR2_CVAL_AUDIOBITRATE_384] = "384kb/s", - [PVR2_CVAL_AUDIOBITRATE_320] = "320kb/s", - [PVR2_CVAL_AUDIOBITRATE_256] = "256kb/s", - [PVR2_CVAL_AUDIOBITRATE_224] = "224kb/s", - [PVR2_CVAL_AUDIOBITRATE_192] = "192kb/s", - [PVR2_CVAL_AUDIOBITRATE_160] = "160kb/s", - [PVR2_CVAL_AUDIOBITRATE_128] = "128kb/s", - [PVR2_CVAL_AUDIOBITRATE_112] = "112kb/s", - [PVR2_CVAL_AUDIOBITRATE_96] = "96kb/s", - [PVR2_CVAL_AUDIOBITRATE_80] = "80kb/s", - [PVR2_CVAL_AUDIOBITRATE_64] = "64kb/s", - [PVR2_CVAL_AUDIOBITRATE_56] = "56kb/s", - [PVR2_CVAL_AUDIOBITRATE_48] = "48kb/s", - [PVR2_CVAL_AUDIOBITRATE_32] = "32kb/s", - [PVR2_CVAL_AUDIOBITRATE_VBR] = "VBR", -}; - - -static const char *control_values_audioemphasis[] = { - [PVR2_CVAL_AUDIOEMPHASIS_NONE] = "None", - [PVR2_CVAL_AUDIOEMPHASIS_50_15] = "50/15us", - [PVR2_CVAL_AUDIOEMPHASIS_CCITT] = "CCITT J.17", -}; static const char *control_values_input[] = { @@ -278,6 +346,76 @@ static int ctrl_freq_set(struct pvr2_ctrl *cptr,int m,int v) return 0; } +static int ctrl_cx2341x_is_dirty(struct pvr2_ctrl *cptr) +{ + return cptr->hdw->enc_stale != 0; +} + +static void ctrl_cx2341x_clear_dirty(struct pvr2_ctrl *cptr) +{ + cptr->hdw->enc_stale = 0; +} + +static int ctrl_cx2341x_get(struct pvr2_ctrl *cptr,int *vp) +{ + int ret; + struct v4l2_ext_controls cs; + struct v4l2_ext_control c1; + memset(&cs,0,sizeof(cs)); + memset(&c1,0,sizeof(c1)); + cs.controls = &c1; + cs.count = 1; + c1.id = cptr->info->v4l_id; + ret = cx2341x_ext_ctrls(&cptr->hdw->enc_ctl_state,&cs, + VIDIOC_G_EXT_CTRLS); + if (ret) return ret; + *vp = c1.value; + return 0; +} + +static int ctrl_cx2341x_set(struct pvr2_ctrl *cptr,int m,int v) +{ + int ret; + struct v4l2_ext_controls cs; + struct v4l2_ext_control c1; + memset(&cs,0,sizeof(cs)); + memset(&c1,0,sizeof(c1)); + cs.controls = &c1; + cs.count = 1; + c1.id = cptr->info->v4l_id; + c1.value = v; + ret = cx2341x_ext_ctrls(&cptr->hdw->enc_ctl_state,&cs, + VIDIOC_S_EXT_CTRLS); + if (ret) return ret; + cptr->hdw->enc_stale = !0; + return 0; +} + +static unsigned int ctrl_cx2341x_getv4lflags(struct pvr2_ctrl *cptr) +{ + struct v4l2_queryctrl qctrl; + struct pvr2_ctl_info *info; + qctrl.id = cptr->info->v4l_id; + cx2341x_ctrl_query(&cptr->hdw->enc_ctl_state,&qctrl); + /* Strip out the const so we can adjust a function pointer. It's + OK to do this here because we know this is a dynamically created + control, so the underlying storage for the info pointer is (a) + private to us, and (b) not in read-only storage. Either we do + this or we significantly complicate the underlying control + implementation. */ + info = (struct pvr2_ctl_info *)(cptr->info); + if (qctrl.flags & V4L2_CTRL_FLAG_READ_ONLY) { + if (info->set_value) { + info->set_value = 0; + } + } else { + if (!(info->set_value)) { + info->set_value = ctrl_cx2341x_set; + } + } + return qctrl.flags; +} + static int ctrl_streamingenabled_get(struct pvr2_ctrl *cptr,int *vp) { *vp = cptr->hdw->flag_streaming_enabled; @@ -437,6 +575,9 @@ static void ctrl_stdenumcur_clear_dirty(struct pvr2_ctrl *cptr) .def.type_enum.count = (sizeof(tab)/sizeof((tab)[0])), \ .def.type_enum.value_names = tab +#define DEFBOOL \ + .type = pvr2_ctl_bool + #define DEFMASK(msk,tab) \ .type = pvr2_ctl_bitmask, \ .def.type_bitmask.valid_bits = msk, \ @@ -468,19 +609,11 @@ VCREATE_FUNCS(balance) VCREATE_FUNCS(bass) VCREATE_FUNCS(treble) VCREATE_FUNCS(mute) -VCREATE_FUNCS(srate) -VCREATE_FUNCS(audiobitrate) -VCREATE_FUNCS(audiocrc) -VCREATE_FUNCS(audioemphasis) -VCREATE_FUNCS(vbr) -VCREATE_FUNCS(videobitrate) -VCREATE_FUNCS(videopeak) VCREATE_FUNCS(input) VCREATE_FUNCS(audiomode) VCREATE_FUNCS(res_hor) VCREATE_FUNCS(res_ver) -VCREATE_FUNCS(interlace) -VCREATE_FUNCS(audiolayer) +VCREATE_FUNCS(srate) #define MIN_FREQ 55250000L #define MAX_FREQ 850000000L @@ -549,69 +682,7 @@ static const struct pvr2_ctl_info control_defs[] = { .name = "mute", .default_value = 0, DEFREF(mute), - DEFINT(0,1), - },{ - .v4l_id = V4L2_CID_PVR_SRATE, - .desc = "Sample rate", - .name = "srate", - .default_value = PVR2_CVAL_SRATE_48, - DEFREF(srate), - DEFENUM(control_values_srate), - },{ - .v4l_id = V4L2_CID_PVR_AUDIOBITRATE, - .desc = "Audio Bitrate", - .name = "audio_bitrate", - .default_value = PVR2_CVAL_AUDIOBITRATE_224, - DEFREF(audiobitrate), - DEFENUM(control_values_audiobitrate), - },{ - .v4l_id = V4L2_CID_PVR_AUDIOCRC, - .desc = "Audio CRC", - .name = "audio_crc", - .default_value = 1, - DEFREF(audiocrc), - DEFINT(0,1), - },{ - .desc = "Audio Layer", - .name = "audio_layer", - .default_value = 2, - DEFREF(audiolayer), - DEFINT(0,3), - },{ - .v4l_id = V4L2_CID_PVR_AUDIOEMPHASIS, - .desc = "Audio Emphasis", - .name = "audio_emphasis", - .default_value = PVR2_CVAL_AUDIOEMPHASIS_NONE, - DEFREF(audioemphasis), - DEFENUM(control_values_audioemphasis), - },{ - .desc = "Interlace mode", - .name = "interlace", - .internal_id = PVR2_CID_INTERLACE, - .default_value = 0, - DEFREF(interlace), - DEFINT(0,1), - },{ - .v4l_id = V4L2_CID_PVR_VBR, - .desc = "Variable video bitrate", - .name = "vbr", - .default_value = 0, - DEFREF(vbr), - DEFINT(0,1), - },{ - .v4l_id = V4L2_CID_PVR_VIDEOBITRATE, - .desc = "Average video bitrate", - .name = "video_average_bitrate", - .default_value = 6000000, - DEFREF(videobitrate), - DEFINT(500000,20000000), - },{ - .v4l_id = V4L2_CID_PVR_VIDEOPEAK, - .desc = "Peak video bitrate", - .name = "video_peak_bitrate", - .default_value = 6000000, - DEFREF(videopeak), - DEFINT(500000,20000000), + DEFBOOL, },{ .desc = "Video Source", .name = "input", @@ -627,6 +698,27 @@ static const struct pvr2_ctl_info control_defs[] = { DEFREF(audiomode), DEFENUM(control_values_audiomode), },{ + .desc = "Horizontal capture resolution", + .name = "resolution_hor", + .internal_id = PVR2_CID_HRES, + .default_value = 720, + DEFREF(res_hor), + DEFINT(320,720), + },{ + .desc = "Vertical capture resolution", + .name = "resolution_ver", + .internal_id = PVR2_CID_VRES, + .default_value = 480, + DEFREF(res_ver), + DEFINT(200,625), + },{ + .v4l_id = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ, + .desc = "Sample rate", + .name = "srate", + .default_value = PVR2_CVAL_SRATE_48, + DEFREF(srate), + DEFENUM(control_values_srate), + },{ .desc = "Tuner Frequency (Hz)", .name = "frequency", .internal_id = PVR2_CID_FREQUENCY, @@ -655,24 +747,10 @@ static const struct pvr2_ctl_info control_defs[] = { .get_value = ctrl_channelprog_get, DEFINT(0,FREQTABLE_SIZE), },{ - .desc = "Horizontal capture resolution", - .name = "resolution_hor", - .internal_id = PVR2_CID_HRES, - .default_value = 720, - DEFREF(res_hor), - DEFINT(320,720), - },{ - .desc = "Vertical capture resolution", - .name = "resolution_ver", - .internal_id = PVR2_CID_VRES, - .default_value = 480, - DEFREF(res_ver), - DEFINT(200,625), - },{ .desc = "Streaming Enabled", .name = "streaming_enabled", .get_value = ctrl_streamingenabled_get, - DEFINT(0,1), + DEFBOOL, },{ .desc = "USB Speed", .name = "usb_speed", @@ -682,7 +760,7 @@ static const struct pvr2_ctl_info control_defs[] = { .desc = "Signal Present", .name = "signal_present", .get_value = ctrl_signal_get, - DEFINT(0,1), + DEFBOOL, },{ .desc = "Video Standards Available Mask", .name = "video_standard_mask_available", @@ -732,7 +810,7 @@ static const struct pvr2_ctl_info control_defs[] = { } }; -#define CTRL_COUNT (sizeof(control_defs)/sizeof(control_defs[0])) +#define CTRLDEF_COUNT (sizeof(control_defs)/sizeof(control_defs[0])) const char *pvr2_config_get_name(enum pvr2_config cfg) @@ -956,6 +1034,10 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw) if (ret < 0) return ret; fwidx = ret; ret = 0; + /* Since we're about to completely reinitialize the encoder, + invalidate our cached copy of its configuration state. Next + time we configure the encoder, then we'll fully configure it. */ + hdw->enc_cur_valid = 0; /* First prepare firmware loading */ ret |= pvr2_write_register(hdw, 0x0048, 0xffffffff); /*interrupt mask*/ @@ -1096,12 +1178,13 @@ void pvr2_hdw_subsys_bit_chg_no_lock(struct pvr2_hdw *hdw, if (!hdw->flag_ok) return; msk &= PVR2_SUBSYS_ALL; + nmsk = (hdw->subsys_enabled_mask & ~msk) | (val & msk); + nmsk &= PVR2_SUBSYS_ALL; for (;;) { tryCount++; - vmsk = hdw->subsys_enabled_mask & PVR2_SUBSYS_ALL; - nmsk = (vmsk & ~msk) | (val & msk); - if (!(nmsk ^ vmsk)) break; + if (!((nmsk ^ hdw->subsys_enabled_mask) & + PVR2_SUBSYS_ALL)) break; if (tryCount > 4) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, "Too many retries when configuring device;" @@ -1450,7 +1533,7 @@ static void pvr2_hdw_setup_std(struct pvr2_hdw *hdw) return; } - pvr2_trace(PVR2_TRACE_EEPROM, + pvr2_trace(PVR2_TRACE_ERROR_LEGS, "Unable to select a viable initial video standard"); } @@ -1509,7 +1592,7 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) pvr2_i2c_core_init(hdw); if (!pvr2_hdw_dev_ok(hdw)) return; - for (idx = 0; idx < CTRL_COUNT; idx++) { + for (idx = 0; idx < CTRLDEF_COUNT; idx++) { cptr = hdw->controls + idx; if (cptr->info->skip_init) continue; if (!cptr->info->set_value) continue; @@ -1651,6 +1734,8 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, int valid_std_mask; struct pvr2_ctrl *cptr; __u8 ifnum; + struct v4l2_queryctrl qctrl; + struct pvr2_ctl_info *ciptr; hdw_type = devid - pvr2_device_table; if (hdw_type >= @@ -1665,22 +1750,74 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, hdw,pvr2_device_names[hdw_type]); if (!hdw) goto fail; memset(hdw,0,sizeof(*hdw)); + cx2341x_fill_defaults(&hdw->enc_ctl_state); - hdw->controls = kmalloc(sizeof(struct pvr2_ctrl) * CTRL_COUNT, + hdw->control_cnt = CTRLDEF_COUNT; + hdw->control_cnt += MPEGDEF_COUNT; + hdw->controls = kmalloc(sizeof(struct pvr2_ctrl) * hdw->control_cnt, GFP_KERNEL); if (!hdw->controls) goto fail; - memset(hdw->controls,0,sizeof(struct pvr2_ctrl) * CTRL_COUNT); + memset(hdw->controls,0,sizeof(struct pvr2_ctrl) * hdw->control_cnt); hdw->hdw_type = hdw_type; - + for (idx = 0; idx < hdw->control_cnt; idx++) { + cptr = hdw->controls + idx; + cptr->hdw = hdw; + } for (idx = 0; idx < 32; idx++) { hdw->std_mask_ptrs[idx] = hdw->std_mask_names[idx]; } - - for (idx = 0; idx < CTRL_COUNT; idx++) { + for (idx = 0; idx < CTRLDEF_COUNT; idx++) { cptr = hdw->controls + idx; - cptr->hdw = hdw; cptr->info = control_defs+idx; } + /* Define and configure additional controls from cx2341x module. */ + hdw->mpeg_ctrl_info = kmalloc( + sizeof(*(hdw->mpeg_ctrl_info)) * MPEGDEF_COUNT, GFP_KERNEL); + if (!hdw->mpeg_ctrl_info) goto fail; + memset(hdw->mpeg_ctrl_info,0, + sizeof(*(hdw->mpeg_ctrl_info)) * MPEGDEF_COUNT); + for (idx = 0; idx < MPEGDEF_COUNT; idx++) { + cptr = hdw->controls + idx + CTRLDEF_COUNT; + ciptr = &(hdw->mpeg_ctrl_info[idx].info); + ciptr->desc = hdw->mpeg_ctrl_info[idx].desc; + ciptr->name = mpeg_ids[idx].strid; + ciptr->v4l_id = mpeg_ids[idx].id; + ciptr->skip_init = !0; + ciptr->get_value = ctrl_cx2341x_get; + ciptr->get_v4lflags = ctrl_cx2341x_getv4lflags; + ciptr->is_dirty = ctrl_cx2341x_is_dirty; + if (!idx) ciptr->clear_dirty = ctrl_cx2341x_clear_dirty; + qctrl.id = ciptr->v4l_id; + cx2341x_ctrl_query(&hdw->enc_ctl_state,&qctrl); + if (!(qctrl.flags & V4L2_CTRL_FLAG_READ_ONLY)) { + ciptr->set_value = ctrl_cx2341x_set; + } + strncpy(hdw->mpeg_ctrl_info[idx].desc,qctrl.name, + PVR2_CTLD_INFO_DESC_SIZE); + hdw->mpeg_ctrl_info[idx].desc[PVR2_CTLD_INFO_DESC_SIZE-1] = 0; + ciptr->default_value = qctrl.default_value; + switch (qctrl.type) { + default: + case V4L2_CTRL_TYPE_INTEGER: + ciptr->type = pvr2_ctl_int; + ciptr->def.type_int.min_value = qctrl.minimum; + ciptr->def.type_int.max_value = qctrl.maximum; + break; + case V4L2_CTRL_TYPE_BOOLEAN: + ciptr->type = pvr2_ctl_bool; + break; + case V4L2_CTRL_TYPE_MENU: + ciptr->type = pvr2_ctl_enum; + ciptr->def.type_enum.value_names = + cx2341x_ctrl_get_menu(ciptr->v4l_id); + for (cnt1 = 0; + ciptr->def.type_enum.value_names[cnt1] != NULL; + cnt1++) { } + ciptr->def.type_enum.count = cnt1; + break; + } + cptr->info = ciptr; + } // Initialize video standard enum dynamic control cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDENUM); @@ -1783,6 +1920,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, 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); + if (hdw->mpeg_ctrl_info) kfree(hdw->mpeg_ctrl_info); kfree(hdw); } return 0; @@ -1847,7 +1985,8 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw) unit_pointers[hdw->unit_number] = 0; } } while (0); up(&pvr2_unit_sem); - kfree(hdw->controls); + if (hdw->controls) kfree(hdw->controls); + if (hdw->mpeg_ctrl_info) kfree(hdw->mpeg_ctrl_info); if (hdw->std_defs) kfree(hdw->std_defs); if (hdw->std_enum_names) kfree(hdw->std_enum_names); kfree(hdw); @@ -1953,7 +2092,7 @@ int pvr2_hdw_get_stdenum_value(struct pvr2_hdw *hdw, /* Get the number of defined controls */ unsigned int pvr2_hdw_get_ctrl_count(struct pvr2_hdw *hdw) { - return CTRL_COUNT; + return hdw->control_cnt; } @@ -1961,7 +2100,7 @@ unsigned int pvr2_hdw_get_ctrl_count(struct pvr2_hdw *hdw) struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_index(struct pvr2_hdw *hdw, unsigned int idx) { - if (idx >= CTRL_COUNT) return 0; + if (idx >= hdw->control_cnt) return 0; return hdw->controls + idx; } @@ -1975,7 +2114,7 @@ struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_id(struct pvr2_hdw *hdw, int i; /* This could be made a lot more efficient, but for now... */ - for (idx = 0; idx < CTRL_COUNT; idx++) { + for (idx = 0; idx < hdw->control_cnt; idx++) { cptr = hdw->controls + idx; i = cptr->info->internal_id; if (i && (i == ctl_id)) return cptr; @@ -1984,7 +2123,7 @@ struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_id(struct pvr2_hdw *hdw, } -/* Given an ID, retrieve the control structure associated with it. */ +/* Given a V4L ID, retrieve the control structure associated with it. */ struct pvr2_ctrl *pvr2_hdw_get_ctrl_v4l(struct pvr2_hdw *hdw,unsigned int ctl_id) { struct pvr2_ctrl *cptr; @@ -1992,7 +2131,7 @@ struct pvr2_ctrl *pvr2_hdw_get_ctrl_v4l(struct pvr2_hdw *hdw,unsigned int ctl_id int i; /* This could be made a lot more efficient, but for now... */ - for (idx = 0; idx < CTRL_COUNT; idx++) { + for (idx = 0; idx < hdw->control_cnt; idx++) { cptr = hdw->controls + idx; i = cptr->info->v4l_id; if (i && (i == ctl_id)) return cptr; @@ -2001,11 +2140,36 @@ struct pvr2_ctrl *pvr2_hdw_get_ctrl_v4l(struct pvr2_hdw *hdw,unsigned int ctl_id } +/* Given a V4L ID for its immediate predecessor, retrieve the control + structure associated with it. */ +struct pvr2_ctrl *pvr2_hdw_get_ctrl_nextv4l(struct pvr2_hdw *hdw, + unsigned int ctl_id) +{ + struct pvr2_ctrl *cptr,*cp2; + unsigned int idx; + int i; + + /* This could be made a lot more efficient, but for now... */ + cp2 = 0; + for (idx = 0; idx < hdw->control_cnt; idx++) { + cptr = hdw->controls + idx; + i = cptr->info->v4l_id; + if (!i) continue; + if (i <= ctl_id) continue; + if (cp2 && (cp2->info->v4l_id < i)) continue; + cp2 = cptr; + } + return cp2; + return 0; +} + + static const char *get_ctrl_typename(enum pvr2_ctl_type tp) { switch (tp) { case pvr2_ctl_int: return "integer"; case pvr2_ctl_enum: return "enum"; + case pvr2_ctl_bool: return "boolean"; case pvr2_ctl_bitmask: return "bitmask"; } return ""; @@ -2030,7 +2194,7 @@ int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw) char buf[100]; unsigned int bcnt,ccnt; - for (idx = 0; idx < CTRL_COUNT; idx++) { + for (idx = 0; idx < hdw->control_cnt; idx++) { cptr = hdw->controls + idx; if (cptr->info->is_dirty == 0) continue; if (!cptr->info->is_dirty(cptr)) continue; @@ -2074,37 +2238,45 @@ int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw) hdw->res_ver_val = nvres; hdw->res_ver_dirty = !0; } - if (!hdw->interlace_val) { - hdw->interlace_val = 0; - hdw->interlace_dirty = !0; - } } if (hdw->std_dirty || +#if 0 /* Don't toggle encoder for now - seems to work better this way */ + hdw->enc_stale || + hdw->srate_dirty || hdw->res_ver_dirty || hdw->res_hor_dirty || - hdw->interlace_dirty || - hdw->vbr_dirty || - hdw->videobitrate_dirty || - hdw->videopeak_dirty || - hdw->audiobitrate_dirty || - hdw->srate_dirty || - hdw->audiolayer_dirty || - hdw->audiocrc_dirty || - hdw->audioemphasis_dirty) { +#endif + 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) { + /* Write new sample rate into control structure since + * the master copy is stale. We must track srate + * separate from the mpeg control structure because + * other logic also uses this value. */ + struct v4l2_ext_controls cs; + struct v4l2_ext_control c1; + memset(&cs,0,sizeof(cs)); + memset(&c1,0,sizeof(c1)); + cs.controls = &c1; + cs.count = 1; + c1.id = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ; + c1.value = hdw->srate_val; + cx2341x_ext_ctrls(&hdw->enc_ctl_state,&cs,VIDIOC_S_EXT_CTRLS); + } + /* Scan i2c core at this point - before we clear all the dirty bits. Various parts of the i2c core will notice dirty bits as appropriate and arrange to broadcast or directly send updates to the client drivers in order to keep everything in sync */ pvr2_i2c_core_check_stale(hdw); - for (idx = 0; idx < CTRL_COUNT; idx++) { + for (idx = 0; idx < hdw->control_cnt; idx++) { cptr = hdw->controls + idx; if (!cptr->info->clear_dirty) continue; cptr->info->clear_dirty(cptr); @@ -2234,11 +2406,16 @@ struct pvr2_stream *pvr2_hdw_get_video_stream(struct pvr2_hdw *hp) void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw) { + int nr = pvr2_hdw_get_unit_number(hdw); LOCK_TAKE(hdw->big_lock); do { hdw->log_requested = !0; + printk(KERN_INFO "pvrusb2: ================= START STATUS CARD #%d =================\n", nr); pvr2_i2c_core_check_stale(hdw); hdw->log_requested = 0; pvr2_i2c_core_sync(hdw); + pvr2_trace(PVR2_TRACE_INFO,"cx2341x config:"); + cx2341x_log_status(&hdw->enc_ctl_state, "pvrusb2"); + printk(KERN_INFO "pvrusb2: ================== END STATUS CARD #%d ==================\n", nr); } while (0); LOCK_GIVE(hdw->big_lock); } diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h index ba70f5d48..310fe9d3d 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h @@ -27,16 +27,6 @@ #include "pvrusb2-io.h" #include "pvrusb2-ctrl.h" -/* Private V4L2-compatible controls available in this driver, look these up - with pvr2_hdw_get_ctrl_v4l(). */ -#define V4L2_CID_PVR_SRATE (V4L2_CID_PRIVATE_BASE) -#define V4L2_CID_PVR_AUDIOBITRATE (V4L2_CID_PRIVATE_BASE+1) -#define V4L2_CID_PVR_AUDIOCRC (V4L2_CID_PRIVATE_BASE+2) -#define V4L2_CID_PVR_AUDIOEMPHASIS (V4L2_CID_PRIVATE_BASE+3) -#define V4L2_CID_PVR_VBR (V4L2_CID_PRIVATE_BASE+4) -#define V4L2_CID_PVR_VIDEOBITRATE (V4L2_CID_PRIVATE_BASE+5) -#define V4L2_CID_PVR_VIDEOPEAK (V4L2_CID_PRIVATE_BASE+6) -#define V4L2_CID_PVR_VIDEOSTANDARD (V4L2_CID_PRIVATE_BASE+7) /* Private internal control ids, look these up with pvr2_hdw_get_ctrl_by_id() - these are NOT visible in V4L */ @@ -48,7 +38,6 @@ #define PVR2_CID_FREQUENCY 6 #define PVR2_CID_HRES 7 #define PVR2_CID_VRES 8 -#define PVR2_CID_INTERLACE 9 /* Legal values for the INPUT state variable */ #define PVR2_CVAL_INPUT_TV 0 @@ -154,6 +143,10 @@ struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_id(struct pvr2_hdw *,unsigned int); /* Retrieve a control handle given its V4L ID (if any) */ struct pvr2_ctrl *pvr2_hdw_get_ctrl_v4l(struct pvr2_hdw *,unsigned int ctl_id); +/* Retrieve a control handle given its immediate predecessor V4L ID (if any) */ +struct pvr2_ctrl *pvr2_hdw_get_ctrl_nextv4l(struct pvr2_hdw *, + unsigned int ctl_id); + /* Commit all control changes made up to this point */ int pvr2_hdw_commit_ctl(struct pvr2_hdw *); diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-main.c b/linux/drivers/media/video/pvrusb2/pvrusb2-main.c index 245f7a36d..b81b5a62e 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-main.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-main.c @@ -47,14 +47,6 @@ PVR2_TRACE_INFO| \ PVR2_TRACE_TOLERANCE| \ PVR2_TRACE_TRAP| \ - PVR2_TRACE_FIRMWARE| \ - PVR2_TRACE_EEPROM | \ - PVR2_TRACE_INIT | \ - PVR2_TRACE_I2C | \ - PVR2_TRACE_CHIPS | \ - PVR2_TRACE_START_STOP | \ - PVR2_TRACE_CTL | \ - PVR2_TRACE_DEBUGIFC | \ 0) int pvrusb2_debug = DEFAULT_DEBUG_MASK; diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-std.c b/linux/drivers/media/video/pvrusb2/pvrusb2-std.c index 64ba223c2..134063693 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-std.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-std.c @@ -21,6 +21,8 @@ #include "pvrusb2-std.h" #include "pvrusb2-debug.h" +#include <asm/string.h> +#include <linux/slab.h> struct std_name { const char *name; diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index 075882877..812a779c8 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c @@ -56,6 +56,7 @@ struct pvr2_sysfs_debugifc { struct pvr2_sysfs_ctl_item { struct class_device_attribute attr_name; + struct class_device_attribute attr_type; struct class_device_attribute attr_min; struct class_device_attribute attr_max; struct class_device_attribute attr_enum; @@ -65,7 +66,7 @@ struct pvr2_sysfs_ctl_item { struct pvr2_ctrl *cptr; struct pvr2_sysfs *chptr; struct pvr2_sysfs_ctl_item *item_next; - struct attribute *attr_gen[6]; + struct attribute *attr_gen[7]; struct attribute_group grp; char name[80]; }; @@ -93,6 +94,33 @@ static ssize_t show_name(int id,struct class_device *class_dev,char *buf) return scnprintf(buf,PAGE_SIZE,"%s\n",name); } +static ssize_t show_type(int id,struct class_device *class_dev,char *buf) +{ + struct pvr2_ctrl *cptr; + struct pvr2_sysfs *sfp; + const char *name; + enum pvr2_ctl_type tp; + + sfp = (struct pvr2_sysfs *)class_dev->class_data; + if (!sfp) return -EINVAL; + cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); + if (!cptr) return -EINVAL; + + tp = pvr2_ctrl_get_type(cptr); + switch (tp) { + case pvr2_ctl_int: name = "integer"; break; + case pvr2_ctl_enum: name = "enum"; break; + case pvr2_ctl_bitmask: name = "bitmask"; break; + case pvr2_ctl_bool: name = "boolean"; break; + default: name = "?"; break; + } + pvr2_sysfs_trace("pvr2_sysfs(%p) show_type(cid=%d) is %s",sfp,id,name); + + if (!name) return -EINVAL; + + return scnprintf(buf,PAGE_SIZE,"%s\n",name); +} + static ssize_t show_min(int id,struct class_device *class_dev,char *buf) { struct pvr2_ctrl *cptr; @@ -190,6 +218,7 @@ static ssize_t show_enum(int id,struct class_device *class_dev,char *buf) bcnt = 0; for (val = 0; val < ecnt; val++) { pvr2_ctrl_get_valname(cptr,val,buf+bcnt,PAGE_SIZE-bcnt,&ccnt); + if (!ccnt) continue; bcnt += ccnt; if (bcnt >= PAGE_SIZE) break; buf[bcnt] = '\n'; @@ -289,6 +318,7 @@ static ssize_t sf_name##_##ctl_id(struct class_device *class_dev,const char *buf #define CREATE_BATCH(ctl_id) \ CREATE_SHOW_INSTANCE(show_name,ctl_id) \ +CREATE_SHOW_INSTANCE(show_type,ctl_id) \ CREATE_SHOW_INSTANCE(show_min,ctl_id) \ CREATE_SHOW_INSTANCE(show_max,ctl_id) \ CREATE_SHOW_INSTANCE(show_val_norm,ctl_id) \ @@ -332,9 +362,36 @@ CREATE_BATCH(30) CREATE_BATCH(31) CREATE_BATCH(32) CREATE_BATCH(33) +CREATE_BATCH(34) +CREATE_BATCH(35) +CREATE_BATCH(36) +CREATE_BATCH(37) +CREATE_BATCH(38) +CREATE_BATCH(39) +CREATE_BATCH(40) +CREATE_BATCH(41) +CREATE_BATCH(42) +CREATE_BATCH(43) +CREATE_BATCH(44) +CREATE_BATCH(45) +CREATE_BATCH(46) +CREATE_BATCH(47) +CREATE_BATCH(48) +CREATE_BATCH(49) +CREATE_BATCH(50) +CREATE_BATCH(51) +CREATE_BATCH(52) +CREATE_BATCH(53) +CREATE_BATCH(54) +CREATE_BATCH(55) +CREATE_BATCH(56) +CREATE_BATCH(57) +CREATE_BATCH(58) +CREATE_BATCH(59) struct pvr2_sysfs_func_set { ssize_t (*show_name)(struct class_device *,char *); + ssize_t (*show_type)(struct class_device *,char *); ssize_t (*show_min)(struct class_device *,char *); ssize_t (*show_max)(struct class_device *,char *); ssize_t (*show_enum)(struct class_device *,char *); @@ -350,6 +407,7 @@ struct pvr2_sysfs_func_set { #define INIT_BATCH(ctl_id) \ [ctl_id] = { \ .show_name = show_name_##ctl_id, \ + .show_type = show_type_##ctl_id, \ .show_min = show_min_##ctl_id, \ .show_max = show_max_##ctl_id, \ .show_enum = show_enum_##ctl_id, \ @@ -395,6 +453,32 @@ static struct pvr2_sysfs_func_set funcs[] = { INIT_BATCH(31), INIT_BATCH(32), INIT_BATCH(33), + INIT_BATCH(34), + INIT_BATCH(35), + INIT_BATCH(36), + INIT_BATCH(37), + INIT_BATCH(38), + INIT_BATCH(39), + INIT_BATCH(40), + INIT_BATCH(41), + INIT_BATCH(42), + INIT_BATCH(43), + INIT_BATCH(44), + INIT_BATCH(45), + INIT_BATCH(46), + INIT_BATCH(47), + INIT_BATCH(48), + INIT_BATCH(49), + INIT_BATCH(50), + INIT_BATCH(51), + INIT_BATCH(52), + INIT_BATCH(53), + INIT_BATCH(54), + INIT_BATCH(55), + INIT_BATCH(56), + INIT_BATCH(57), + INIT_BATCH(58), + INIT_BATCH(59), }; @@ -434,6 +518,11 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id) cip->attr_name.attr.mode = S_IRUGO; cip->attr_name.show = fp->show_name; + cip->attr_type.attr.owner = THIS_MODULE; + cip->attr_type.attr.name = "type"; + cip->attr_type.attr.mode = S_IRUGO; + cip->attr_type.show = fp->show_type; + cip->attr_min.attr.owner = THIS_MODULE; cip->attr_min.attr.name = "min_val"; cip->attr_min.attr.mode = S_IRUGO; @@ -469,6 +558,7 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id) acnt = 0; cip->attr_gen[acnt++] = &cip->attr_name.attr; + cip->attr_gen[acnt++] = &cip->attr_type.attr; cip->attr_gen[acnt++] = &cip->attr_val.attr; cip->attr_val.show = fp->show_val_norm; cip->attr_val.store = fp->store_val_norm; diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index 78cdd01c8..e1ac2c386 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -22,6 +22,7 @@ #include "compat.h" #include <linux/kernel.h> +#include <linux/version.h> #include "pvrusb2-context.h" #include "pvrusb2-hdw.h" #include "pvrusb2.h" @@ -450,12 +451,6 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, vf->fmt.pix.width = val; val = 0; pvr2_ctrl_get_value( - pvr2_hdw_get_ctrl_by_id(hdw, - PVR2_CID_INTERLACE), - &val); - if (val) vf->fmt.pix.width /= 2; - val = 0; - pvr2_ctrl_get_value( pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES), &val); vf->fmt.pix.height = val; @@ -482,25 +477,22 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, case V4L2_BUF_TYPE_VIDEO_CAPTURE: { int h = vf->fmt.pix.height; int w = vf->fmt.pix.width; - int vd_std, hf, hh; - vd_std = 0; - pvr2_ctrl_get_value( - pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR), - &vd_std); - if (vd_std & V4L2_STD_525_60) { - hf=480; - } else { - hf=576; + if (h < 200) { + h = 200; + } else if (h > 625) { + h = 625; + } + if (w < 320) { + w = 320; + } else if (w > 720) { + w = 720; } - hh = (int) (hf / 2); memcpy(vf, &pvr_format[PVR_FORMAT_PIX], sizeof(struct v4l2_format)); - if (w > 720) - vf->fmt.pix.width = 720; - vf->fmt.pix.width &= 0xff0; - vf->fmt.pix.height = (h > hh) ? hf : hh; + vf->fmt.pix.width = w; + vf->fmt.pix.height = h; if (cmd == VIDIOC_S_FMT) { pvr2_ctrl_set_value( @@ -511,10 +503,6 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES), vf->fmt.pix.height); - pvr2_ctrl_set_value( - pvr2_hdw_get_ctrl_by_id( - hdw,PVR2_CID_INTERLACE), - vf->fmt.pix.height != hf); } } break; case V4L2_BUF_TYPE_VBI_CAPTURE: @@ -547,13 +535,27 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, struct pvr2_ctrl *cptr; struct v4l2_queryctrl *vc = (struct v4l2_queryctrl *)arg; ret = 0; - cptr = pvr2_hdw_get_ctrl_v4l(hdw,vc->id); + if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) { + cptr = pvr2_hdw_get_ctrl_nextv4l( + hdw,(vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL)); + if (cptr) vc->id = pvr2_ctrl_get_v4lid(cptr); + } else { + cptr = pvr2_hdw_get_ctrl_v4l(hdw,vc->id); + } if (!cptr) { + pvr2_trace(PVR2_TRACE_V4LIOCTL, + "QUERYCTRL id=0x%x not implemented here", + vc->id); ret = -EINVAL; break; } - strlcpy(vc->name,pvr2_ctrl_get_name(cptr),sizeof(vc->name)); + pvr2_trace(PVR2_TRACE_V4LIOCTL, + "QUERYCTRL id=0x%x mapping name=%s (%s)", + vc->id,pvr2_ctrl_get_name(cptr), + pvr2_ctrl_get_desc(cptr)); + strlcpy(vc->name,pvr2_ctrl_get_desc(cptr),sizeof(vc->name)); + vc->flags = pvr2_ctrl_get_v4lflags(cptr); vc->default_value = pvr2_ctrl_get_def(cptr); switch (pvr2_ctrl_get_type(cptr)) { case pvr2_ctl_enum: @@ -562,6 +564,12 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1; vc->step = 1; break; + case pvr2_ctl_bool: + vc->type = V4L2_CTRL_TYPE_BOOLEAN; + vc->minimum = 0; + vc->maximum = 1; + vc->step = 1; + break; case pvr2_ctl_int: vc->type = V4L2_CTRL_TYPE_INTEGER; vc->minimum = pvr2_ctrl_get_min(cptr); @@ -569,6 +577,9 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, vc->step = 1; break; default: + pvr2_trace(PVR2_TRACE_V4LIOCTL, + "QUERYCTRL id=0x%x name=%s not mappable", + vc->id,pvr2_ctrl_get_name(cptr)); ret = -EINVAL; break; } @@ -605,13 +616,72 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, break; } - case VIDIOC_LOG_STATUS: + case VIDIOC_G_EXT_CTRLS: + { + struct v4l2_ext_controls *ctls = + (struct v4l2_ext_controls *)arg; + struct v4l2_ext_control *ctrl; + unsigned int idx; + int val; + for (idx = 0; idx < ctls->count; idx++) { + ctrl = ctls->controls + idx; + ret = pvr2_ctrl_get_value( + pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),&val); + if (ret) { + ctls->error_idx = idx; + break; + } + /* Ensure that if read as a 64 bit value, the user + will still get a hopefully sane value */ + ctrl->value64 = 0; + ctrl->value = val; + } + break; + } + + case VIDIOC_S_EXT_CTRLS: + { + struct v4l2_ext_controls *ctls = + (struct v4l2_ext_controls *)arg; + struct v4l2_ext_control *ctrl; + unsigned int idx; + for (idx = 0; idx < ctls->count; idx++) { + ctrl = ctls->controls + idx; + ret = pvr2_ctrl_set_value( + pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id), + ctrl->value); + if (ret) { + ctls->error_idx = idx; + break; + } + } + break; + } + + case VIDIOC_TRY_EXT_CTRLS: { - int nr = pvr2_hdw_get_unit_number(hdw); + struct v4l2_ext_controls *ctls = + (struct v4l2_ext_controls *)arg; + struct v4l2_ext_control *ctrl; + struct pvr2_ctrl *pctl; + unsigned int idx; + /* For the moment just validate that the requested control + actually exists. */ + for (idx = 0; idx < ctls->count; idx++) { + ctrl = ctls->controls + idx; + pctl = pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id); + if (!pctl) { + ret = -EINVAL; + ctls->error_idx = idx; + break; + } + } + break; + } - printk(KERN_INFO "pvrusb2: ================= START STATUS CARD #%d =================\n", nr); + case VIDIOC_LOG_STATUS: + { pvr2_hdw_trigger_module_log(hdw); - printk(KERN_INFO "pvrusb2: ================== END STATUS CARD #%d ==================\n", nr); ret = 0; break; } @@ -625,11 +695,11 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, if (ret < 0) { if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, + pvr2_trace(PVR2_TRACE_V4LIOCTL, "pvr2_v4l2_do_ioctl failure, ret=%d",ret); } else { - if (pvrusb2_debug & PVR2_TRACE_ERROR_LEGS) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, + if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) { + pvr2_trace(PVR2_TRACE_V4LIOCTL, "pvr2_v4l2_do_ioctl failure, ret=%d" " command was:",ret); v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw), diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c index 4127c82f7..e4ec7f251 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c @@ -91,12 +91,15 @@ static void set_audio(struct pvr2_v4l_decoder *ctxt) hdw->srate_val); switch (hdw->srate_val) { default: - case PVR2_CVAL_SRATE_48: + case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000: val = 48000; break; - case PVR2_CVAL_SRATE_44_1: + case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100: val = 44100; break; + case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000: + val = 32000; + break; } pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_AUDIO_CLOCK_FREQ,&val); } diff --git a/linux/drivers/media/video/saa7134/saa6752hs.c b/linux/drivers/media/video/saa7134/saa6752hs.c index 0422e10e6..f89e6d070 100644 --- a/linux/drivers/media/video/saa7134/saa6752hs.c +++ b/linux/drivers/media/video/saa7134/saa6752hs.c @@ -443,10 +443,10 @@ static void saa6752hs_old_set_params(struct i2c_client* client, } static int handle_ctrl(struct saa6752hs_mpeg_params *params, - struct v4l2_ext_control *ctrl, int cmd) + struct v4l2_ext_control *ctrl, unsigned int cmd) { int old = 0, new; - int set = cmd == VIDIOC_S_EXT_CTRLS; + int set = (cmd == VIDIOC_S_EXT_CTRLS); new = ctrl->value; switch (ctrl->id) { diff --git a/linux/drivers/media/video/saa7134/saa7134-core.c b/linux/drivers/media/video/saa7134/saa7134-core.c index bdaf6c10b..8d1aa8cd0 100644 --- a/linux/drivers/media/video/saa7134/saa7134-core.c +++ b/linux/drivers/media/video/saa7134/saa7134-core.c @@ -1012,8 +1012,6 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, /* load i2c helpers */ if (TUNER_ABSENT != dev->tuner_type) request_module("tuner"); - if (dev->tda9887_conf) - request_module("tda9887"); if (card_is_empress(dev)) { request_module("saa6752hs"); request_module_depend("saa7134-empress",&need_empress); diff --git a/linux/drivers/media/video/stradis.c b/linux/drivers/media/video/stradis.c index 40ebe8adf..1e8bf1b99 100644 --- a/linux/drivers/media/video/stradis.c +++ b/linux/drivers/media/video/stradis.c @@ -2191,7 +2191,7 @@ static struct pci_driver stradis_driver = { .remove = __devexit_p(stradis_remove) }; -int __init stradis_init(void) +static int __init stradis_init(void) { int retval; @@ -2204,7 +2204,7 @@ int __init stradis_init(void) return retval; } -void __exit stradis_exit(void) +static void __exit stradis_exit(void) { pci_unregister_driver(&stradis_driver); printk(KERN_INFO "stradis: module cleanup complete\n"); diff --git a/linux/drivers/media/video/tda9887.c b/linux/drivers/media/video/tda9887.c index 0d8e5842a..4568916f6 100644 --- a/linux/drivers/media/video/tda9887.c +++ b/linux/drivers/media/video/tda9887.c @@ -26,11 +26,11 @@ */ #define tda9887_info(fmt, arg...) do {\ - printk(KERN_INFO "%s %d-%04x (tda9887): " fmt, t->i2c.name, \ + printk(KERN_INFO "%s %d-%04x: " fmt, t->i2c.name, \ i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) #define tda9887_dbg(fmt, arg...) do {\ if (tuner_debug) \ - printk(KERN_INFO "%s %d-%04x (tda9887): " fmt, t->i2c.name, \ + printk(KERN_INFO "%s %d-%04x: " fmt, t->i2c.name, \ i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index 7ff9fb327..606d8fabd 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -47,7 +47,6 @@ static unsigned int no_autodetect = 0; static unsigned int show_i2c = 0; /* insmod options used at runtime => read/write */ -static unsigned int tuner_debug_old = 0; int tuner_debug = 0; static unsigned int tv_range[2] = { 44, 958 }; @@ -66,15 +65,12 @@ MODULE_PARM(tv_range,"2i"); MODULE_PARM(radio_range,"2i"); MODULE_PARM(no_autodetect, "i"); MODULE_PARM(tuner_debug, "i"); -MODULE_PARM(tuner_debug_old, "i"); MODULE_PARM(addr, "i"); MODULE_PARM(show_i2c, "i"); #else module_param(addr, int, 0444); module_param(no_autodetect, int, 0444); module_param(show_i2c, int, 0444); -/* Note: tuner_debug is deprecated and will be removed in 2.6.17 */ -module_param_named(tuner_debug,tuner_debug_old, int, 0444); module_param_named(debug,tuner_debug, int, 0644); module_param_string(pal, pal, sizeof(pal), 0644); module_param_string(secam, secam, sizeof(secam), 0644); @@ -489,11 +485,6 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, t->audmode = V4L2_TUNER_MODE_STEREO; t->mode_mask = T_UNINITIALIZED; t->tuner_status = tuner_status; - if (tuner_debug_old) { - tuner_debug = tuner_debug_old; - printk(KERN_ERR "tuner: tuner_debug is deprecated and will be removed in 2.6.17.\n"); - printk(KERN_ERR "tuner: use the debug option instead.\n"); - } if (show_i2c) { unsigned char buffer[16]; diff --git a/linux/drivers/media/video/usbvideo/konicawc.c b/linux/drivers/media/video/usbvideo/konicawc.c index c11f5d46b..1feaf5f0b 100644 --- a/linux/drivers/media/video/usbvideo/konicawc.c +++ b/linux/drivers/media/video/usbvideo/konicawc.c @@ -15,8 +15,13 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> +#include "compat.h" +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) #include <linux/input.h> #include <linux/usb_input.h> +#else +#include <linux/usb/input.h> +#endif #include "usbvideo.h" diff --git a/linux/drivers/media/video/usbvideo/quickcam_messenger.c b/linux/drivers/media/video/usbvideo/quickcam_messenger.c index 3f3182a24..66e750336 100644 --- a/linux/drivers/media/video/usbvideo/quickcam_messenger.c +++ b/linux/drivers/media/video/usbvideo/quickcam_messenger.c @@ -33,7 +33,12 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/input.h> +#include "compat.h" +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) #include <linux/usb_input.h> +#else +#include <linux/usb/input.h> +#endif #include "usbvideo.h" #include "quickcam_messenger.h" diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index 40fea5a05..96c778596 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -1134,7 +1134,7 @@ const char **v4l2_ctrl_get_menu(u32 id) }; static const char *mpeg_stream_vbi_fmt[] = { "No VBI", - "VBI in private packets, IVTV format", + "Private packet, IVTV format", NULL }; diff --git a/linux/drivers/media/video/videocodec.h b/linux/drivers/media/video/videocodec.h index 3f968eb7b..1b40df14f 100644 --- a/linux/drivers/media/video/videocodec.h +++ b/linux/drivers/media/video/videocodec.h @@ -223,14 +223,14 @@ M zr36055[1] 0001 0000c001 00000000 (zr36050[1]) /* ========================= */ struct vfe_polarity { - int vsync_pol:1; - int hsync_pol:1; - int field_pol:1; - int blank_pol:1; - int subimg_pol:1; - int poe_pol:1; - int pvalid_pol:1; - int vclk_pol:1; + unsigned int vsync_pol:1; + unsigned int hsync_pol:1; + unsigned int field_pol:1; + unsigned int blank_pol:1; + unsigned int subimg_pol:1; + unsigned int poe_pol:1; + unsigned int pvalid_pol:1; + unsigned int vclk_pol:1; }; struct vfe_settings { |