diff options
-rw-r--r-- | drivers/media/video/bt8xx/bttv-driver.c | 120 |
1 files changed, 83 insertions, 37 deletions
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index c8f958151677..ddca21d9c948 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c | |||
@@ -785,15 +785,15 @@ static const struct v4l2_queryctrl bttv_ctls[] = { | |||
785 | 785 | ||
786 | 786 | ||
787 | }; | 787 | }; |
788 | static const int BTTV_CTLS = ARRAY_SIZE(bttv_ctls); | ||
789 | 788 | ||
790 | static const struct v4l2_queryctrl *ctrl_by_id(int id) | 789 | static const struct v4l2_queryctrl *ctrl_by_id(int id) |
791 | { | 790 | { |
792 | int i; | 791 | int i; |
793 | 792 | ||
794 | for (i = 0; i < BTTV_CTLS; i++) | 793 | for (i = 0; i < ARRAY_SIZE(bttv_ctls); i++) |
795 | if (bttv_ctls[i].id == id) | 794 | if (bttv_ctls[i].id == id) |
796 | return bttv_ctls+i; | 795 | return bttv_ctls+i; |
796 | |||
797 | return NULL; | 797 | return NULL; |
798 | } | 798 | } |
799 | 799 | ||
@@ -2479,6 +2479,7 @@ static int bttv_try_fmt_cap(struct file *file, void *priv, | |||
2479 | struct bttv *btv = fh->btv; | 2479 | struct bttv *btv = fh->btv; |
2480 | enum v4l2_field field; | 2480 | enum v4l2_field field; |
2481 | __s32 width, height; | 2481 | __s32 width, height; |
2482 | int rc; | ||
2482 | 2483 | ||
2483 | fmt = format_by_fourcc(f->fmt.pix.pixelformat); | 2484 | fmt = format_by_fourcc(f->fmt.pix.pixelformat); |
2484 | if (NULL == fmt) | 2485 | if (NULL == fmt) |
@@ -2515,6 +2516,14 @@ static int bttv_try_fmt_cap(struct file *file, void *priv, | |||
2515 | width = f->fmt.pix.width; | 2516 | width = f->fmt.pix.width; |
2516 | height = f->fmt.pix.height; | 2517 | height = f->fmt.pix.height; |
2517 | 2518 | ||
2519 | rc = limit_scaled_size(fh, &width, &height, field, | ||
2520 | /* width_mask: 4 pixels */ ~3, | ||
2521 | /* width_bias: nearest */ 2, | ||
2522 | /* adjust_size */ 1, | ||
2523 | /* adjust_crop */ 0); | ||
2524 | if (0 != rc) | ||
2525 | return rc; | ||
2526 | |||
2518 | /* update data for the application */ | 2527 | /* update data for the application */ |
2519 | f->fmt.pix.field = field; | 2528 | f->fmt.pix.field = field; |
2520 | pix_format_set_size(&f->fmt.pix, fmt, width, height); | 2529 | pix_format_set_size(&f->fmt.pix, fmt, width, height); |
@@ -2539,6 +2548,8 @@ static int bttv_s_fmt_cap(struct file *file, void *priv, | |||
2539 | const struct bttv_format *fmt; | 2548 | const struct bttv_format *fmt; |
2540 | struct bttv_fh *fh = priv; | 2549 | struct bttv_fh *fh = priv; |
2541 | struct bttv *btv = fh->btv; | 2550 | struct bttv *btv = fh->btv; |
2551 | __s32 width, height; | ||
2552 | enum v4l2_field field; | ||
2542 | 2553 | ||
2543 | retval = bttv_switch_type(fh, f->type); | 2554 | retval = bttv_switch_type(fh, f->type); |
2544 | if (0 != retval) | 2555 | if (0 != retval) |
@@ -2548,6 +2559,20 @@ static int bttv_s_fmt_cap(struct file *file, void *priv, | |||
2548 | if (0 != retval) | 2559 | if (0 != retval) |
2549 | return retval; | 2560 | return retval; |
2550 | 2561 | ||
2562 | width = f->fmt.pix.width; | ||
2563 | height = f->fmt.pix.height; | ||
2564 | field = f->fmt.pix.field; | ||
2565 | |||
2566 | retval = limit_scaled_size(fh, &width, &height, f->fmt.pix.field, | ||
2567 | /* width_mask: 4 pixels */ ~3, | ||
2568 | /* width_bias: nearest */ 2, | ||
2569 | /* adjust_size */ 1, | ||
2570 | /* adjust_crop */ 1); | ||
2571 | if (0 != retval) | ||
2572 | return retval; | ||
2573 | |||
2574 | f->fmt.pix.field = field; | ||
2575 | |||
2551 | fmt = format_by_fourcc(f->fmt.pix.pixelformat); | 2576 | fmt = format_by_fourcc(f->fmt.pix.pixelformat); |
2552 | 2577 | ||
2553 | /* update our state informations */ | 2578 | /* update our state informations */ |
@@ -2571,8 +2596,10 @@ static int bttv_s_fmt_overlay(struct file *file, void *priv, | |||
2571 | struct bttv_fh *fh = priv; | 2596 | struct bttv_fh *fh = priv; |
2572 | struct bttv *btv = fh->btv; | 2597 | struct bttv *btv = fh->btv; |
2573 | 2598 | ||
2574 | if (no_overlay > 0) | 2599 | if (no_overlay > 0) { |
2600 | printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n"); | ||
2575 | return -EINVAL; | 2601 | return -EINVAL; |
2602 | } | ||
2576 | 2603 | ||
2577 | return setup_window(fh, btv, &f->fmt.win, 1); | 2604 | return setup_window(fh, btv, &f->fmt.win, 1); |
2578 | } | 2605 | } |
@@ -2645,15 +2672,32 @@ static int bttv_enum_fmt_vbi(struct file *file, void *priv, | |||
2645 | return 0; | 2672 | return 0; |
2646 | } | 2673 | } |
2647 | 2674 | ||
2675 | static int bttv_enum_fmt_cap_ovr(struct v4l2_fmtdesc *f) | ||
2676 | { | ||
2677 | int index = -1, i; | ||
2678 | |||
2679 | for (i = 0; i < FORMATS; i++) { | ||
2680 | if (formats[i].fourcc != -1) | ||
2681 | index++; | ||
2682 | if ((unsigned int)index == f->index) | ||
2683 | break; | ||
2684 | } | ||
2685 | if (FORMATS == i) | ||
2686 | return -EINVAL; | ||
2687 | |||
2688 | f->pixelformat = formats[i].fourcc; | ||
2689 | strlcpy(f->description, formats[i].name, sizeof(f->description)); | ||
2690 | |||
2691 | return i; | ||
2692 | } | ||
2693 | |||
2648 | static int bttv_enum_fmt_cap(struct file *file, void *priv, | 2694 | static int bttv_enum_fmt_cap(struct file *file, void *priv, |
2649 | struct v4l2_fmtdesc *f) | 2695 | struct v4l2_fmtdesc *f) |
2650 | { | 2696 | { |
2651 | if (f->index >= FORMATS) | 2697 | int rc = bttv_enum_fmt_cap_ovr(f); |
2652 | return -EINVAL; | ||
2653 | 2698 | ||
2654 | strlcpy(f->description, formats[f->index].name, | 2699 | if (rc < 0) |
2655 | sizeof(f->description)); | 2700 | return rc; |
2656 | f->pixelformat = formats[f->index].fourcc; | ||
2657 | 2701 | ||
2658 | return 0; | 2702 | return 0; |
2659 | } | 2703 | } |
@@ -2661,18 +2705,20 @@ static int bttv_enum_fmt_cap(struct file *file, void *priv, | |||
2661 | static int bttv_enum_fmt_overlay(struct file *file, void *priv, | 2705 | static int bttv_enum_fmt_overlay(struct file *file, void *priv, |
2662 | struct v4l2_fmtdesc *f) | 2706 | struct v4l2_fmtdesc *f) |
2663 | { | 2707 | { |
2708 | int rc; | ||
2709 | |||
2664 | if (no_overlay > 0) { | 2710 | if (no_overlay > 0) { |
2665 | printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n"); | 2711 | printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n"); |
2666 | return -EINVAL; | 2712 | return -EINVAL; |
2667 | } | 2713 | } |
2668 | 2714 | ||
2669 | if (f->index >= FORMATS) | 2715 | rc = bttv_enum_fmt_cap_ovr(f); |
2670 | return -EINVAL; | ||
2671 | 2716 | ||
2672 | strlcpy(f->description, formats[f->index].name, | 2717 | if (rc < 0) |
2673 | sizeof(f->description)); | 2718 | return rc; |
2674 | 2719 | ||
2675 | f->pixelformat = formats[f->index].fourcc; | 2720 | if (!(formats[rc].flags & FORMAT_FLAGS_PACKED)) |
2721 | return -EINVAL; | ||
2676 | 2722 | ||
2677 | return 0; | 2723 | return 0; |
2678 | } | 2724 | } |
@@ -2871,12 +2917,13 @@ static int bttv_queryctrl(struct file *file, void *priv, | |||
2871 | c->id >= V4L2_CID_PRIVATE_LASTP1)) | 2917 | c->id >= V4L2_CID_PRIVATE_LASTP1)) |
2872 | return -EINVAL; | 2918 | return -EINVAL; |
2873 | 2919 | ||
2874 | ctrl = ctrl_by_id(c->id); | 2920 | if (!btv->volume_gpio && (c->id == V4L2_CID_AUDIO_VOLUME)) |
2875 | *c = (NULL != ctrl) ? *ctrl : no_ctl; | 2921 | *c = no_ctl; |
2922 | else { | ||
2923 | ctrl = ctrl_by_id(c->id); | ||
2876 | 2924 | ||
2877 | if (!btv->volume_gpio && | 2925 | *c = (NULL != ctrl) ? *ctrl : no_ctl; |
2878 | (ctrl->id == V4L2_CID_AUDIO_VOLUME)) | 2926 | } |
2879 | * c = no_ctl; | ||
2880 | 2927 | ||
2881 | return 0; | 2928 | return 0; |
2882 | } | 2929 | } |
@@ -3306,9 +3353,6 @@ static const struct file_operations bttv_fops = | |||
3306 | 3353 | ||
3307 | static struct video_device bttv_video_template = | 3354 | static struct video_device bttv_video_template = |
3308 | { | 3355 | { |
3309 | .name = "UNSET", | ||
3310 | .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER| | ||
3311 | VID_TYPE_CLIPPING|VID_TYPE_SCALES, | ||
3312 | .fops = &bttv_fops, | 3356 | .fops = &bttv_fops, |
3313 | .minor = -1, | 3357 | .minor = -1, |
3314 | .vidioc_querycap = bttv_querycap, | 3358 | .vidioc_querycap = bttv_querycap, |
@@ -3364,14 +3408,6 @@ static struct video_device bttv_video_template = | |||
3364 | .current_norm = V4L2_STD_PAL, | 3408 | .current_norm = V4L2_STD_PAL, |
3365 | }; | 3409 | }; |
3366 | 3410 | ||
3367 | static struct video_device bttv_vbi_template = | ||
3368 | { | ||
3369 | .name = "bt848/878 vbi", | ||
3370 | .type = VID_TYPE_TUNER|VID_TYPE_TELETEXT, | ||
3371 | .fops = &bttv_fops, | ||
3372 | .minor = -1, | ||
3373 | }; | ||
3374 | |||
3375 | /* ----------------------------------------------------------------------- */ | 3411 | /* ----------------------------------------------------------------------- */ |
3376 | /* radio interface */ | 3412 | /* radio interface */ |
3377 | 3413 | ||
@@ -3570,8 +3606,6 @@ static const struct file_operations radio_fops = | |||
3570 | 3606 | ||
3571 | static struct video_device radio_template = | 3607 | static struct video_device radio_template = |
3572 | { | 3608 | { |
3573 | .name = "bt848/878 radio", | ||
3574 | .type = VID_TYPE_TUNER, | ||
3575 | .fops = &radio_fops, | 3609 | .fops = &radio_fops, |
3576 | .minor = -1, | 3610 | .minor = -1, |
3577 | .vidioc_querycap = radio_querycap, | 3611 | .vidioc_querycap = radio_querycap, |
@@ -4109,8 +4143,9 @@ static irqreturn_t bttv_irq(int irq, void *dev_id) | |||
4109 | /* initialitation */ | 4143 | /* initialitation */ |
4110 | 4144 | ||
4111 | static struct video_device *vdev_init(struct bttv *btv, | 4145 | static struct video_device *vdev_init(struct bttv *btv, |
4112 | struct video_device *template, | 4146 | const struct video_device *template, |
4113 | char *type) | 4147 | const char *type_name, |
4148 | const int type) | ||
4114 | { | 4149 | { |
4115 | struct video_device *vfd; | 4150 | struct video_device *vfd; |
4116 | 4151 | ||
@@ -4121,9 +4156,10 @@ static struct video_device *vdev_init(struct bttv *btv, | |||
4121 | vfd->minor = -1; | 4156 | vfd->minor = -1; |
4122 | vfd->dev = &btv->c.pci->dev; | 4157 | vfd->dev = &btv->c.pci->dev; |
4123 | vfd->release = video_device_release; | 4158 | vfd->release = video_device_release; |
4159 | vfd->type = type; | ||
4124 | snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)", | 4160 | snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)", |
4125 | btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "", | 4161 | btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "", |
4126 | type, bttv_tvcards[btv->c.type].name); | 4162 | type_name, bttv_tvcards[btv->c.type].name); |
4127 | return vfd; | 4163 | return vfd; |
4128 | } | 4164 | } |
4129 | 4165 | ||
@@ -4155,6 +4191,11 @@ static void bttv_unregister_video(struct bttv *btv) | |||
4155 | /* register video4linux devices */ | 4191 | /* register video4linux devices */ |
4156 | static int __devinit bttv_register_video(struct bttv *btv) | 4192 | static int __devinit bttv_register_video(struct bttv *btv) |
4157 | { | 4193 | { |
4194 | int video_type = VID_TYPE_CAPTURE | | ||
4195 | VID_TYPE_TUNER | | ||
4196 | VID_TYPE_CLIPPING| | ||
4197 | VID_TYPE_SCALES; | ||
4198 | |||
4158 | if (no_overlay <= 0) { | 4199 | if (no_overlay <= 0) { |
4159 | bttv_video_template.type |= VID_TYPE_OVERLAY; | 4200 | bttv_video_template.type |= VID_TYPE_OVERLAY; |
4160 | } else { | 4201 | } else { |
@@ -4162,7 +4203,9 @@ static int __devinit bttv_register_video(struct bttv *btv) | |||
4162 | } | 4203 | } |
4163 | 4204 | ||
4164 | /* video */ | 4205 | /* video */ |
4165 | btv->video_dev = vdev_init(btv, &bttv_video_template, "video"); | 4206 | btv->video_dev = vdev_init(btv, &bttv_video_template, |
4207 | "video", video_type); | ||
4208 | |||
4166 | if (NULL == btv->video_dev) | 4209 | if (NULL == btv->video_dev) |
4167 | goto err; | 4210 | goto err; |
4168 | if (video_register_device(btv->video_dev,VFL_TYPE_GRABBER,video_nr)<0) | 4211 | if (video_register_device(btv->video_dev,VFL_TYPE_GRABBER,video_nr)<0) |
@@ -4177,7 +4220,9 @@ static int __devinit bttv_register_video(struct bttv *btv) | |||
4177 | } | 4220 | } |
4178 | 4221 | ||
4179 | /* vbi */ | 4222 | /* vbi */ |
4180 | btv->vbi_dev = vdev_init(btv, &bttv_vbi_template, "vbi"); | 4223 | btv->vbi_dev = vdev_init(btv, &bttv_video_template, |
4224 | "vbi", VID_TYPE_TUNER | VID_TYPE_TELETEXT); | ||
4225 | |||
4181 | if (NULL == btv->vbi_dev) | 4226 | if (NULL == btv->vbi_dev) |
4182 | goto err; | 4227 | goto err; |
4183 | if (video_register_device(btv->vbi_dev,VFL_TYPE_VBI,vbi_nr)<0) | 4228 | if (video_register_device(btv->vbi_dev,VFL_TYPE_VBI,vbi_nr)<0) |
@@ -4188,7 +4233,8 @@ static int __devinit bttv_register_video(struct bttv *btv) | |||
4188 | if (!btv->has_radio) | 4233 | if (!btv->has_radio) |
4189 | return 0; | 4234 | return 0; |
4190 | /* radio */ | 4235 | /* radio */ |
4191 | btv->radio_dev = vdev_init(btv, &radio_template, "radio"); | 4236 | btv->radio_dev = vdev_init(btv, &radio_template, |
4237 | "radio", VID_TYPE_TUNER); | ||
4192 | if (NULL == btv->radio_dev) | 4238 | if (NULL == btv->radio_dev) |
4193 | goto err; | 4239 | goto err; |
4194 | if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,radio_nr)<0) | 4240 | if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,radio_nr)<0) |