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) |
