diff options
| -rw-r--r-- | drivers/media/usb/usbtv/usbtv.c | 174 |
1 files changed, 136 insertions, 38 deletions
diff --git a/drivers/media/usb/usbtv/usbtv.c b/drivers/media/usb/usbtv/usbtv.c index 8a505a90d318..6222a4ab1e00 100644 --- a/drivers/media/usb/usbtv/usbtv.c +++ b/drivers/media/usb/usbtv/usbtv.c | |||
| @@ -50,13 +50,8 @@ | |||
| 50 | #define USBTV_ISOC_TRANSFERS 16 | 50 | #define USBTV_ISOC_TRANSFERS 16 |
| 51 | #define USBTV_ISOC_PACKETS 8 | 51 | #define USBTV_ISOC_PACKETS 8 |
| 52 | 52 | ||
| 53 | #define USBTV_WIDTH 720 | ||
| 54 | #define USBTV_HEIGHT 480 | ||
| 55 | |||
| 56 | #define USBTV_CHUNK_SIZE 256 | 53 | #define USBTV_CHUNK_SIZE 256 |
| 57 | #define USBTV_CHUNK 240 | 54 | #define USBTV_CHUNK 240 |
| 58 | #define USBTV_CHUNKS (USBTV_WIDTH * USBTV_HEIGHT \ | ||
| 59 | / 4 / USBTV_CHUNK) | ||
| 60 | 55 | ||
| 61 | /* Chunk header. */ | 56 | /* Chunk header. */ |
| 62 | #define USBTV_MAGIC_OK(chunk) ((be32_to_cpu(chunk[0]) & 0xff000000) \ | 57 | #define USBTV_MAGIC_OK(chunk) ((be32_to_cpu(chunk[0]) & 0xff000000) \ |
| @@ -65,6 +60,27 @@ | |||
| 65 | #define USBTV_ODD(chunk) ((be32_to_cpu(chunk[0]) & 0x0000f000) >> 15) | 60 | #define USBTV_ODD(chunk) ((be32_to_cpu(chunk[0]) & 0x0000f000) >> 15) |
| 66 | #define USBTV_CHUNK_NO(chunk) (be32_to_cpu(chunk[0]) & 0x00000fff) | 61 | #define USBTV_CHUNK_NO(chunk) (be32_to_cpu(chunk[0]) & 0x00000fff) |
| 67 | 62 | ||
| 63 | #define USBTV_TV_STD (V4L2_STD_525_60 | V4L2_STD_PAL) | ||
| 64 | |||
| 65 | /* parameters for supported TV norms */ | ||
| 66 | struct usbtv_norm_params { | ||
| 67 | v4l2_std_id norm; | ||
| 68 | int cap_width, cap_height; | ||
| 69 | }; | ||
| 70 | |||
| 71 | static struct usbtv_norm_params norm_params[] = { | ||
| 72 | { | ||
| 73 | .norm = V4L2_STD_525_60, | ||
| 74 | .cap_width = 720, | ||
| 75 | .cap_height = 480, | ||
| 76 | }, | ||
| 77 | { | ||
| 78 | .norm = V4L2_STD_PAL, | ||
| 79 | .cap_width = 720, | ||
| 80 | .cap_height = 576, | ||
| 81 | } | ||
| 82 | }; | ||
| 83 | |||
| 68 | /* A single videobuf2 frame buffer. */ | 84 | /* A single videobuf2 frame buffer. */ |
| 69 | struct usbtv_buf { | 85 | struct usbtv_buf { |
| 70 | struct vb2_buffer vb; | 86 | struct vb2_buffer vb; |
| @@ -94,11 +110,38 @@ struct usbtv { | |||
| 94 | USBTV_COMPOSITE_INPUT, | 110 | USBTV_COMPOSITE_INPUT, |
| 95 | USBTV_SVIDEO_INPUT, | 111 | USBTV_SVIDEO_INPUT, |
| 96 | } input; | 112 | } input; |
| 113 | v4l2_std_id norm; | ||
| 114 | int width, height; | ||
| 115 | int n_chunks; | ||
| 97 | int iso_size; | 116 | int iso_size; |
| 98 | unsigned int sequence; | 117 | unsigned int sequence; |
| 99 | struct urb *isoc_urbs[USBTV_ISOC_TRANSFERS]; | 118 | struct urb *isoc_urbs[USBTV_ISOC_TRANSFERS]; |
| 100 | }; | 119 | }; |
| 101 | 120 | ||
| 121 | static int usbtv_configure_for_norm(struct usbtv *usbtv, v4l2_std_id norm) | ||
| 122 | { | ||
| 123 | int i, ret = 0; | ||
| 124 | struct usbtv_norm_params *params = NULL; | ||
| 125 | |||
| 126 | for (i = 0; i < ARRAY_SIZE(norm_params); i++) { | ||
| 127 | if (norm_params[i].norm & norm) { | ||
| 128 | params = &norm_params[i]; | ||
| 129 | break; | ||
| 130 | } | ||
| 131 | } | ||
| 132 | |||
| 133 | if (params) { | ||
| 134 | usbtv->width = params->cap_width; | ||
| 135 | usbtv->height = params->cap_height; | ||
| 136 | usbtv->n_chunks = usbtv->width * usbtv->height | ||
| 137 | / 4 / USBTV_CHUNK; | ||
| 138 | usbtv->norm = params->norm; | ||
| 139 | } else | ||
| 140 | ret = -EINVAL; | ||
| 141 | |||
| 142 | return ret; | ||
| 143 | } | ||
| 144 | |||
| 102 | static int usbtv_set_regs(struct usbtv *usbtv, const u16 regs[][2], int size) | 145 | static int usbtv_set_regs(struct usbtv *usbtv, const u16 regs[][2], int size) |
| 103 | { | 146 | { |
| 104 | int ret; | 147 | int ret; |
| @@ -158,6 +201,57 @@ static int usbtv_select_input(struct usbtv *usbtv, int input) | |||
| 158 | return ret; | 201 | return ret; |
| 159 | } | 202 | } |
| 160 | 203 | ||
| 204 | static int usbtv_select_norm(struct usbtv *usbtv, v4l2_std_id norm) | ||
| 205 | { | ||
| 206 | int ret; | ||
| 207 | static const u16 pal[][2] = { | ||
| 208 | { USBTV_BASE + 0x001a, 0x0068 }, | ||
| 209 | { USBTV_BASE + 0x010e, 0x0072 }, | ||
| 210 | { USBTV_BASE + 0x010f, 0x00a2 }, | ||
| 211 | { USBTV_BASE + 0x0112, 0x00b0 }, | ||
| 212 | { USBTV_BASE + 0x0117, 0x0001 }, | ||
| 213 | { USBTV_BASE + 0x0118, 0x002c }, | ||
| 214 | { USBTV_BASE + 0x012d, 0x0010 }, | ||
| 215 | { USBTV_BASE + 0x012f, 0x0020 }, | ||
| 216 | { USBTV_BASE + 0x024f, 0x0002 }, | ||
| 217 | { USBTV_BASE + 0x0254, 0x0059 }, | ||
| 218 | { USBTV_BASE + 0x025a, 0x0016 }, | ||
| 219 | { USBTV_BASE + 0x025b, 0x0035 }, | ||
| 220 | { USBTV_BASE + 0x0263, 0x0017 }, | ||
| 221 | { USBTV_BASE + 0x0266, 0x0016 }, | ||
| 222 | { USBTV_BASE + 0x0267, 0x0036 } | ||
| 223 | }; | ||
| 224 | |||
| 225 | static const u16 ntsc[][2] = { | ||
| 226 | { USBTV_BASE + 0x001a, 0x0079 }, | ||
| 227 | { USBTV_BASE + 0x010e, 0x0068 }, | ||
| 228 | { USBTV_BASE + 0x010f, 0x009c }, | ||
| 229 | { USBTV_BASE + 0x0112, 0x00f0 }, | ||
| 230 | { USBTV_BASE + 0x0117, 0x0000 }, | ||
| 231 | { USBTV_BASE + 0x0118, 0x00fc }, | ||
| 232 | { USBTV_BASE + 0x012d, 0x0004 }, | ||
| 233 | { USBTV_BASE + 0x012f, 0x0008 }, | ||
| 234 | { USBTV_BASE + 0x024f, 0x0001 }, | ||
| 235 | { USBTV_BASE + 0x0254, 0x005f }, | ||
| 236 | { USBTV_BASE + 0x025a, 0x0012 }, | ||
| 237 | { USBTV_BASE + 0x025b, 0x0001 }, | ||
| 238 | { USBTV_BASE + 0x0263, 0x001c }, | ||
| 239 | { USBTV_BASE + 0x0266, 0x0011 }, | ||
| 240 | { USBTV_BASE + 0x0267, 0x0005 } | ||
| 241 | }; | ||
| 242 | |||
| 243 | ret = usbtv_configure_for_norm(usbtv, norm); | ||
| 244 | |||
| 245 | if (!ret) { | ||
| 246 | if (norm & V4L2_STD_525_60) | ||
| 247 | ret = usbtv_set_regs(usbtv, ntsc, ARRAY_SIZE(ntsc)); | ||
| 248 | else if (norm & V4L2_STD_PAL) | ||
| 249 | ret = usbtv_set_regs(usbtv, pal, ARRAY_SIZE(pal)); | ||
| 250 | } | ||
| 251 | |||
| 252 | return ret; | ||
| 253 | } | ||
| 254 | |||
| 161 | static int usbtv_setup_capture(struct usbtv *usbtv) | 255 | static int usbtv_setup_capture(struct usbtv *usbtv) |
| 162 | { | 256 | { |
| 163 | int ret; | 257 | int ret; |
| @@ -225,26 +319,11 @@ static int usbtv_setup_capture(struct usbtv *usbtv) | |||
| 225 | 319 | ||
| 226 | { USBTV_BASE + 0x0284, 0x0088 }, | 320 | { USBTV_BASE + 0x0284, 0x0088 }, |
| 227 | { USBTV_BASE + 0x0003, 0x0004 }, | 321 | { USBTV_BASE + 0x0003, 0x0004 }, |
| 228 | { USBTV_BASE + 0x001a, 0x0079 }, | ||
| 229 | { USBTV_BASE + 0x0100, 0x00d3 }, | 322 | { USBTV_BASE + 0x0100, 0x00d3 }, |
| 230 | { USBTV_BASE + 0x010e, 0x0068 }, | ||
| 231 | { USBTV_BASE + 0x010f, 0x009c }, | ||
| 232 | { USBTV_BASE + 0x0112, 0x00f0 }, | ||
| 233 | { USBTV_BASE + 0x0115, 0x0015 }, | 323 | { USBTV_BASE + 0x0115, 0x0015 }, |
| 234 | { USBTV_BASE + 0x0117, 0x0000 }, | ||
| 235 | { USBTV_BASE + 0x0118, 0x00fc }, | ||
| 236 | { USBTV_BASE + 0x012d, 0x0004 }, | ||
| 237 | { USBTV_BASE + 0x012f, 0x0008 }, | ||
| 238 | { USBTV_BASE + 0x0220, 0x002e }, | 324 | { USBTV_BASE + 0x0220, 0x002e }, |
| 239 | { USBTV_BASE + 0x0225, 0x0008 }, | 325 | { USBTV_BASE + 0x0225, 0x0008 }, |
| 240 | { USBTV_BASE + 0x024e, 0x0002 }, | 326 | { USBTV_BASE + 0x024e, 0x0002 }, |
| 241 | { USBTV_BASE + 0x024f, 0x0001 }, | ||
| 242 | { USBTV_BASE + 0x0254, 0x005f }, | ||
| 243 | { USBTV_BASE + 0x025a, 0x0012 }, | ||
| 244 | { USBTV_BASE + 0x025b, 0x0001 }, | ||
| 245 | { USBTV_BASE + 0x0263, 0x001c }, | ||
| 246 | { USBTV_BASE + 0x0266, 0x0011 }, | ||
| 247 | { USBTV_BASE + 0x0267, 0x0005 }, | ||
| 248 | { USBTV_BASE + 0x024e, 0x0002 }, | 327 | { USBTV_BASE + 0x024e, 0x0002 }, |
| 249 | { USBTV_BASE + 0x024f, 0x0002 }, | 328 | { USBTV_BASE + 0x024f, 0x0002 }, |
| 250 | }; | 329 | }; |
| @@ -253,6 +332,10 @@ static int usbtv_setup_capture(struct usbtv *usbtv) | |||
| 253 | if (ret) | 332 | if (ret) |
| 254 | return ret; | 333 | return ret; |
| 255 | 334 | ||
| 335 | ret = usbtv_select_norm(usbtv, usbtv->norm); | ||
| 336 | if (ret) | ||
| 337 | return ret; | ||
| 338 | |||
| 256 | ret = usbtv_select_input(usbtv, usbtv->input); | 339 | ret = usbtv_select_input(usbtv, usbtv->input); |
| 257 | if (ret) | 340 | if (ret) |
| 258 | return ret; | 341 | return ret; |
| @@ -296,7 +379,7 @@ static void usbtv_image_chunk(struct usbtv *usbtv, u32 *chunk) | |||
| 296 | frame_id = USBTV_FRAME_ID(chunk); | 379 | frame_id = USBTV_FRAME_ID(chunk); |
| 297 | odd = USBTV_ODD(chunk); | 380 | odd = USBTV_ODD(chunk); |
| 298 | chunk_no = USBTV_CHUNK_NO(chunk); | 381 | chunk_no = USBTV_CHUNK_NO(chunk); |
| 299 | if (chunk_no >= USBTV_CHUNKS) | 382 | if (chunk_no >= usbtv->n_chunks) |
| 300 | return; | 383 | return; |
| 301 | 384 | ||
| 302 | /* Beginning of a frame. */ | 385 | /* Beginning of a frame. */ |
| @@ -324,10 +407,10 @@ static void usbtv_image_chunk(struct usbtv *usbtv, u32 *chunk) | |||
| 324 | usbtv->chunks_done++; | 407 | usbtv->chunks_done++; |
| 325 | 408 | ||
| 326 | /* Last chunk in a frame, signalling an end */ | 409 | /* Last chunk in a frame, signalling an end */ |
| 327 | if (odd && chunk_no == USBTV_CHUNKS-1) { | 410 | if (odd && chunk_no == usbtv->n_chunks-1) { |
| 328 | int size = vb2_plane_size(&buf->vb, 0); | 411 | int size = vb2_plane_size(&buf->vb, 0); |
| 329 | enum vb2_buffer_state state = usbtv->chunks_done == | 412 | enum vb2_buffer_state state = usbtv->chunks_done == |
| 330 | USBTV_CHUNKS ? | 413 | usbtv->n_chunks ? |
| 331 | VB2_BUF_STATE_DONE : | 414 | VB2_BUF_STATE_DONE : |
| 332 | VB2_BUF_STATE_ERROR; | 415 | VB2_BUF_STATE_ERROR; |
| 333 | 416 | ||
| @@ -500,6 +583,8 @@ static int usbtv_querycap(struct file *file, void *priv, | |||
| 500 | static int usbtv_enum_input(struct file *file, void *priv, | 583 | static int usbtv_enum_input(struct file *file, void *priv, |
| 501 | struct v4l2_input *i) | 584 | struct v4l2_input *i) |
| 502 | { | 585 | { |
| 586 | struct usbtv *dev = video_drvdata(file); | ||
| 587 | |||
| 503 | switch (i->index) { | 588 | switch (i->index) { |
| 504 | case USBTV_COMPOSITE_INPUT: | 589 | case USBTV_COMPOSITE_INPUT: |
| 505 | strlcpy(i->name, "Composite", sizeof(i->name)); | 590 | strlcpy(i->name, "Composite", sizeof(i->name)); |
| @@ -512,7 +597,7 @@ static int usbtv_enum_input(struct file *file, void *priv, | |||
| 512 | } | 597 | } |
| 513 | 598 | ||
| 514 | i->type = V4L2_INPUT_TYPE_CAMERA; | 599 | i->type = V4L2_INPUT_TYPE_CAMERA; |
| 515 | i->std = V4L2_STD_525_60; | 600 | i->std = dev->vdev.tvnorms; |
| 516 | return 0; | 601 | return 0; |
| 517 | } | 602 | } |
| 518 | 603 | ||
| @@ -531,23 +616,37 @@ static int usbtv_enum_fmt_vid_cap(struct file *file, void *priv, | |||
| 531 | static int usbtv_fmt_vid_cap(struct file *file, void *priv, | 616 | static int usbtv_fmt_vid_cap(struct file *file, void *priv, |
| 532 | struct v4l2_format *f) | 617 | struct v4l2_format *f) |
| 533 | { | 618 | { |
| 534 | f->fmt.pix.width = USBTV_WIDTH; | 619 | struct usbtv *usbtv = video_drvdata(file); |
| 535 | f->fmt.pix.height = USBTV_HEIGHT; | 620 | |
| 621 | f->fmt.pix.width = usbtv->width; | ||
| 622 | f->fmt.pix.height = usbtv->height; | ||
| 536 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; | 623 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; |
| 537 | f->fmt.pix.field = V4L2_FIELD_INTERLACED; | 624 | f->fmt.pix.field = V4L2_FIELD_INTERLACED; |
| 538 | f->fmt.pix.bytesperline = USBTV_WIDTH * 2; | 625 | f->fmt.pix.bytesperline = usbtv->width * 2; |
| 539 | f->fmt.pix.sizeimage = (f->fmt.pix.bytesperline * f->fmt.pix.height); | 626 | f->fmt.pix.sizeimage = (f->fmt.pix.bytesperline * f->fmt.pix.height); |
| 540 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | 627 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; |
| 541 | f->fmt.pix.priv = 0; | 628 | |
| 542 | return 0; | 629 | return 0; |
| 543 | } | 630 | } |
| 544 | 631 | ||
| 545 | static int usbtv_g_std(struct file *file, void *priv, v4l2_std_id *norm) | 632 | static int usbtv_g_std(struct file *file, void *priv, v4l2_std_id *norm) |
| 546 | { | 633 | { |
| 547 | *norm = V4L2_STD_525_60; | 634 | struct usbtv *usbtv = video_drvdata(file); |
| 635 | *norm = usbtv->norm; | ||
| 548 | return 0; | 636 | return 0; |
| 549 | } | 637 | } |
| 550 | 638 | ||
| 639 | static int usbtv_s_std(struct file *file, void *priv, v4l2_std_id norm) | ||
| 640 | { | ||
| 641 | int ret = -EINVAL; | ||
| 642 | struct usbtv *usbtv = video_drvdata(file); | ||
| 643 | |||
| 644 | if ((norm & V4L2_STD_525_60) || (norm & V4L2_STD_PAL)) | ||
| 645 | ret = usbtv_select_norm(usbtv, norm); | ||
| 646 | |||
| 647 | return ret; | ||
| 648 | } | ||
| 649 | |||
| 551 | static int usbtv_g_input(struct file *file, void *priv, unsigned int *i) | 650 | static int usbtv_g_input(struct file *file, void *priv, unsigned int *i) |
| 552 | { | 651 | { |
| 553 | struct usbtv *usbtv = video_drvdata(file); | 652 | struct usbtv *usbtv = video_drvdata(file); |
| @@ -561,13 +660,6 @@ static int usbtv_s_input(struct file *file, void *priv, unsigned int i) | |||
| 561 | return usbtv_select_input(usbtv, i); | 660 | return usbtv_select_input(usbtv, i); |
| 562 | } | 661 | } |
| 563 | 662 | ||
| 564 | static int usbtv_s_std(struct file *file, void *priv, v4l2_std_id norm) | ||
| 565 | { | ||
| 566 | if (norm & V4L2_STD_525_60) | ||
| 567 | return 0; | ||
| 568 | return -EINVAL; | ||
| 569 | } | ||
| 570 | |||
| 571 | struct v4l2_ioctl_ops usbtv_ioctl_ops = { | 663 | struct v4l2_ioctl_ops usbtv_ioctl_ops = { |
| 572 | .vidioc_querycap = usbtv_querycap, | 664 | .vidioc_querycap = usbtv_querycap, |
| 573 | .vidioc_enum_input = usbtv_enum_input, | 665 | .vidioc_enum_input = usbtv_enum_input, |
| @@ -604,10 +696,12 @@ static int usbtv_queue_setup(struct vb2_queue *vq, | |||
| 604 | const struct v4l2_format *v4l_fmt, unsigned int *nbuffers, | 696 | const struct v4l2_format *v4l_fmt, unsigned int *nbuffers, |
| 605 | unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) | 697 | unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) |
| 606 | { | 698 | { |
| 699 | struct usbtv *usbtv = vb2_get_drv_priv(vq); | ||
| 700 | |||
| 607 | if (*nbuffers < 2) | 701 | if (*nbuffers < 2) |
| 608 | *nbuffers = 2; | 702 | *nbuffers = 2; |
| 609 | *nplanes = 1; | 703 | *nplanes = 1; |
| 610 | sizes[0] = USBTV_WIDTH * USBTV_HEIGHT / 2 * sizeof(u32); | 704 | sizes[0] = USBTV_CHUNK * usbtv->n_chunks * 2 * sizeof(u32); |
| 611 | 705 | ||
| 612 | return 0; | 706 | return 0; |
| 613 | } | 707 | } |
| @@ -690,7 +784,11 @@ static int usbtv_probe(struct usb_interface *intf, | |||
| 690 | return -ENOMEM; | 784 | return -ENOMEM; |
| 691 | usbtv->dev = dev; | 785 | usbtv->dev = dev; |
| 692 | usbtv->udev = usb_get_dev(interface_to_usbdev(intf)); | 786 | usbtv->udev = usb_get_dev(interface_to_usbdev(intf)); |
| 787 | |||
| 693 | usbtv->iso_size = size; | 788 | usbtv->iso_size = size; |
| 789 | |||
| 790 | (void)usbtv_configure_for_norm(usbtv, V4L2_STD_525_60); | ||
| 791 | |||
| 694 | spin_lock_init(&usbtv->buflock); | 792 | spin_lock_init(&usbtv->buflock); |
| 695 | mutex_init(&usbtv->v4l2_lock); | 793 | mutex_init(&usbtv->v4l2_lock); |
| 696 | mutex_init(&usbtv->vb2q_lock); | 794 | mutex_init(&usbtv->vb2q_lock); |
| @@ -727,7 +825,7 @@ static int usbtv_probe(struct usb_interface *intf, | |||
| 727 | usbtv->vdev.release = video_device_release_empty; | 825 | usbtv->vdev.release = video_device_release_empty; |
| 728 | usbtv->vdev.fops = &usbtv_fops; | 826 | usbtv->vdev.fops = &usbtv_fops; |
| 729 | usbtv->vdev.ioctl_ops = &usbtv_ioctl_ops; | 827 | usbtv->vdev.ioctl_ops = &usbtv_ioctl_ops; |
| 730 | usbtv->vdev.tvnorms = V4L2_STD_525_60; | 828 | usbtv->vdev.tvnorms = USBTV_TV_STD; |
| 731 | usbtv->vdev.queue = &usbtv->vb2q; | 829 | usbtv->vdev.queue = &usbtv->vb2q; |
| 732 | usbtv->vdev.lock = &usbtv->v4l2_lock; | 830 | usbtv->vdev.lock = &usbtv->v4l2_lock; |
| 733 | set_bit(V4L2_FL_USE_FH_PRIO, &usbtv->vdev.flags); | 831 | set_bit(V4L2_FL_USE_FH_PRIO, &usbtv->vdev.flags); |
