diff options
author | Mauro Carvalho Chehab <mchehab@infradead.org> | 2006-01-23 14:11:08 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@brturbo.com.br> | 2006-01-23 14:11:08 -0500 |
commit | 2d50f847c62acbafa25dc690d0fe65b8b908a326 (patch) | |
tree | b07c01a3571c08b6e27c645bc1c5ff3475718a03 /drivers/media/video/em28xx/em28xx-video.c | |
parent | e5589befc472ca50882f37c4fb32333fc93a65b7 (diff) |
V4L/DVB (3422): Implemented VIDIOC_G_FMT/S_FMT for sliced VBI
- Implemented VIDIOC_G_FMT/S_FMT for sliced VBI
- VIDIOC_S_FMT now calls a function
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/em28xx/em28xx-video.c')
-rw-r--r-- | drivers/media/video/em28xx/em28xx-video.c | 308 |
1 files changed, 155 insertions, 153 deletions
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index e4e82ae716bf..d8d02c44c9d2 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c | |||
@@ -897,7 +897,6 @@ static int em28xx_set_norm(struct em28xx *dev, int width, int height) | |||
897 | return 0; | 897 | return 0; |
898 | } | 898 | } |
899 | 899 | ||
900 | |||
901 | static int em28xx_get_fmt(struct em28xx *dev, struct v4l2_format *format) | 900 | static int em28xx_get_fmt(struct em28xx *dev, struct v4l2_format *format) |
902 | { | 901 | { |
903 | em28xx_videodbg("VIDIOC_G_FMT: type=%s\n", | 902 | em28xx_videodbg("VIDIOC_G_FMT: type=%s\n", |
@@ -909,7 +908,9 @@ static int em28xx_get_fmt(struct em28xx *dev, struct v4l2_format *format) | |||
909 | "V4L2_BUF_TYPE_SLICED_VBI_CAPTURE " : | 908 | "V4L2_BUF_TYPE_SLICED_VBI_CAPTURE " : |
910 | "not supported"); | 909 | "not supported"); |
911 | 910 | ||
912 | if (format->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 911 | switch (format->type) { |
912 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
913 | { | ||
913 | format->fmt.pix.width = dev->width; | 914 | format->fmt.pix.width = dev->width; |
914 | format->fmt.pix.height = dev->height; | 915 | format->fmt.pix.height = dev->height; |
915 | format->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; | 916 | format->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; |
@@ -920,12 +921,161 @@ static int em28xx_get_fmt(struct em28xx *dev, struct v4l2_format *format) | |||
920 | 921 | ||
921 | em28xx_videodbg("VIDIOC_G_FMT: %dx%d\n", dev->width, | 922 | em28xx_videodbg("VIDIOC_G_FMT: %dx%d\n", dev->width, |
922 | dev->height); | 923 | dev->height); |
923 | return 0; | 924 | break; |
925 | } | ||
926 | |||
927 | case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: | ||
928 | { | ||
929 | format->fmt.sliced.service_set=0; | ||
930 | |||
931 | em28xx_i2c_call_clients(dev,VIDIOC_G_FMT,format); | ||
932 | |||
933 | if (format->fmt.sliced.service_set==0) | ||
934 | return -EINVAL; | ||
935 | |||
936 | break; | ||
924 | } | 937 | } |
925 | 938 | ||
926 | return -EINVAL; | 939 | default: |
940 | return -EINVAL; | ||
941 | } | ||
942 | return (0); | ||
927 | } | 943 | } |
928 | 944 | ||
945 | static int em28xx_set_fmt(struct em28xx *dev, unsigned int cmd, struct v4l2_format *format) | ||
946 | { | ||
947 | u32 i; | ||
948 | int ret = 0; | ||
949 | int width = format->fmt.pix.width; | ||
950 | int height = format->fmt.pix.height; | ||
951 | unsigned int hscale, vscale; | ||
952 | unsigned int maxh, maxw; | ||
953 | |||
954 | maxw = norm_maxw(dev); | ||
955 | maxh = norm_maxh(dev); | ||
956 | |||
957 | em28xx_videodbg("%s: type=%s\n", | ||
958 | cmd == VIDIOC_TRY_FMT ? | ||
959 | "VIDIOC_TRY_FMT" : "VIDIOC_S_FMT", | ||
960 | format->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ? | ||
961 | "V4L2_BUF_TYPE_VIDEO_CAPTURE" : | ||
962 | format->type == V4L2_BUF_TYPE_VBI_CAPTURE ? | ||
963 | "V4L2_BUF_TYPE_VBI_CAPTURE " : | ||
964 | "not supported"); | ||
965 | |||
966 | if (format->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { | ||
967 | em28xx_i2c_call_clients(dev,VIDIOC_G_FMT,format); | ||
968 | |||
969 | if (format->fmt.sliced.service_set==0) | ||
970 | return -EINVAL; | ||
971 | |||
972 | return 0; | ||
973 | } | ||
974 | |||
975 | |||
976 | if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
977 | return -EINVAL; | ||
978 | |||
979 | em28xx_videodbg("%s: requested %dx%d\n", | ||
980 | cmd == VIDIOC_TRY_FMT ? | ||
981 | "VIDIOC_TRY_FMT" : "VIDIOC_S_FMT", | ||
982 | format->fmt.pix.width, format->fmt.pix.height); | ||
983 | |||
984 | /* FIXME: Move some code away from here */ | ||
985 | /* width must even because of the YUYV format */ | ||
986 | /* height must be even because of interlacing */ | ||
987 | height &= 0xfffe; | ||
988 | width &= 0xfffe; | ||
989 | |||
990 | if (height < 32) | ||
991 | height = 32; | ||
992 | if (height > maxh) | ||
993 | height = maxh; | ||
994 | if (width < 48) | ||
995 | width = 48; | ||
996 | if (width > maxw) | ||
997 | width = maxw; | ||
998 | |||
999 | if(dev->is_em2800){ | ||
1000 | /* the em2800 can only scale down to 50% */ | ||
1001 | if(height % (maxh / 2)) | ||
1002 | height=maxh; | ||
1003 | if(width % (maxw / 2)) | ||
1004 | width=maxw; | ||
1005 | /* according to empiatech support */ | ||
1006 | /* the MaxPacketSize is to small to support */ | ||
1007 | /* framesizes larger than 640x480 @ 30 fps */ | ||
1008 | /* or 640x576 @ 25 fps. As this would cut */ | ||
1009 | /* of a part of the image we prefer */ | ||
1010 | /* 360x576 or 360x480 for now */ | ||
1011 | if(width == maxw && height == maxh) | ||
1012 | width /= 2; | ||
1013 | } | ||
1014 | |||
1015 | if ((hscale = | ||
1016 | (((unsigned long)maxw) << 12) / width - 4096L) >= | ||
1017 | 0x4000) | ||
1018 | hscale = 0x3fff; | ||
1019 | width = | ||
1020 | (((unsigned long)maxw) << 12) / (hscale + 4096L); | ||
1021 | |||
1022 | if ((vscale = | ||
1023 | (((unsigned long)maxh) << 12) / height - 4096L) >= | ||
1024 | 0x4000) | ||
1025 | vscale = 0x3fff; | ||
1026 | height = | ||
1027 | (((unsigned long)maxh) << 12) / (vscale + 4096L); | ||
1028 | |||
1029 | format->fmt.pix.width = width; | ||
1030 | format->fmt.pix.height = height; | ||
1031 | format->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; | ||
1032 | format->fmt.pix.bytesperline = width * 2; | ||
1033 | format->fmt.pix.sizeimage = width * 2 * height; | ||
1034 | format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
1035 | format->fmt.pix.field = V4L2_FIELD_INTERLACED; | ||
1036 | |||
1037 | em28xx_videodbg("%s: returned %dx%d (%d, %d)\n", | ||
1038 | cmd == | ||
1039 | VIDIOC_TRY_FMT ? "VIDIOC_TRY_FMT" : | ||
1040 | "VIDIOC_S_FMT", format->fmt.pix.width, | ||
1041 | format->fmt.pix.height, hscale, vscale); | ||
1042 | |||
1043 | if (cmd == VIDIOC_TRY_FMT) | ||
1044 | return 0; | ||
1045 | |||
1046 | for (i = 0; i < dev->num_frames; i++) | ||
1047 | if (dev->frame[i].vma_use_count) { | ||
1048 | em28xx_videodbg("VIDIOC_S_FMT failed. " | ||
1049 | "Unmap the buffers first.\n"); | ||
1050 | return -EINVAL; | ||
1051 | } | ||
1052 | |||
1053 | /* stop io in case it is already in progress */ | ||
1054 | if (dev->stream == STREAM_ON) { | ||
1055 | em28xx_videodbg("VIDIOC_SET_FMT: interupting stream\n"); | ||
1056 | if ((ret = em28xx_stream_interrupt(dev))) | ||
1057 | return ret; | ||
1058 | } | ||
1059 | |||
1060 | em28xx_release_buffers(dev); | ||
1061 | dev->io = IO_NONE; | ||
1062 | |||
1063 | /* set new image size */ | ||
1064 | dev->width = width; | ||
1065 | dev->height = height; | ||
1066 | dev->frame_size = dev->width * dev->height * 2; | ||
1067 | dev->field_size = dev->frame_size >> 1; /*both_fileds ? dev->frame_size>>1 : dev->frame_size; */ | ||
1068 | dev->bytesperline = dev->width * 2; | ||
1069 | dev->hscale = hscale; | ||
1070 | dev->vscale = vscale; | ||
1071 | em28xx_uninit_isoc(dev); | ||
1072 | em28xx_set_alternate(dev); | ||
1073 | em28xx_capture_start(dev, 1); | ||
1074 | em28xx_resolution_set(dev); | ||
1075 | em28xx_init_isoc(dev); | ||
1076 | |||
1077 | return 0; | ||
1078 | } | ||
929 | 1079 | ||
930 | /* | 1080 | /* |
931 | * em28xx_v4l2_do_ioctl() | 1081 | * em28xx_v4l2_do_ioctl() |
@@ -983,24 +1133,6 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, | |||
983 | 1133 | ||
984 | em28xx_set_norm(dev, dev->width, dev->height); | 1134 | em28xx_set_norm(dev, dev->width, dev->height); |
985 | 1135 | ||
986 | /* | ||
987 | dev->width=norm_maxw(dev); | ||
988 | dev->height=norm_maxh(dev); | ||
989 | dev->frame_size=dev->width*dev->height*2; | ||
990 | dev->field_size=dev->frame_size>>1; | ||
991 | dev->bytesperline=dev->width*2; | ||
992 | dev->hscale=0; | ||
993 | dev->vscale=0; | ||
994 | |||
995 | em28xx_resolution_set(dev); | ||
996 | */ | ||
997 | /* | ||
998 | em28xx_uninit_isoc(dev); | ||
999 | em28xx_set_alternate(dev); | ||
1000 | em28xx_capture_start(dev, 1); | ||
1001 | em28xx_resolution_set(dev); | ||
1002 | em28xx_init_isoc(dev); | ||
1003 | */ | ||
1004 | em28xx_i2c_call_clients(dev, DECODER_SET_NORM, | 1136 | em28xx_i2c_call_clients(dev, DECODER_SET_NORM, |
1005 | &tvnorms[i].mode); | 1137 | &tvnorms[i].mode); |
1006 | em28xx_i2c_call_clients(dev, VIDIOC_S_STD, | 1138 | em28xx_i2c_call_clients(dev, VIDIOC_S_STD, |
@@ -1396,138 +1528,8 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp, | |||
1396 | 1528 | ||
1397 | case VIDIOC_TRY_FMT: | 1529 | case VIDIOC_TRY_FMT: |
1398 | case VIDIOC_S_FMT: | 1530 | case VIDIOC_S_FMT: |
1399 | { | 1531 | return em28xx_set_fmt(dev, cmd, (struct v4l2_format *)arg); |
1400 | struct v4l2_format *format = arg; | ||
1401 | u32 i; | ||
1402 | int ret = 0; | ||
1403 | int width = format->fmt.pix.width; | ||
1404 | int height = format->fmt.pix.height; | ||
1405 | unsigned int hscale, vscale; | ||
1406 | unsigned int maxh, maxw; | ||
1407 | |||
1408 | maxw = norm_maxw(dev); | ||
1409 | maxh = norm_maxh(dev); | ||
1410 | |||
1411 | /* int both_fields; */ | ||
1412 | |||
1413 | em28xx_videodbg("%s: type=%s\n", | ||
1414 | cmd == | ||
1415 | VIDIOC_TRY_FMT ? "VIDIOC_TRY_FMT" : | ||
1416 | "VIDIOC_S_FMT", | ||
1417 | format->type == | ||
1418 | V4L2_BUF_TYPE_VIDEO_CAPTURE ? | ||
1419 | "V4L2_BUF_TYPE_VIDEO_CAPTURE" : format->type == | ||
1420 | V4L2_BUF_TYPE_VBI_CAPTURE ? | ||
1421 | "V4L2_BUF_TYPE_VBI_CAPTURE " : | ||
1422 | "not supported"); | ||
1423 | |||
1424 | if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1425 | return -EINVAL; | ||
1426 | |||
1427 | em28xx_videodbg("%s: requested %dx%d\n", | ||
1428 | cmd == | ||
1429 | VIDIOC_TRY_FMT ? "VIDIOC_TRY_FMT" : | ||
1430 | "VIDIOC_S_FMT", format->fmt.pix.width, | ||
1431 | format->fmt.pix.height); | ||
1432 | |||
1433 | /* FIXME: Move some code away from here */ | ||
1434 | /* width must even because of the YUYV format */ | ||
1435 | /* height must be even because of interlacing */ | ||
1436 | height &= 0xfffe; | ||
1437 | width &= 0xfffe; | ||
1438 | |||
1439 | if (height < 32) | ||
1440 | height = 32; | ||
1441 | if (height > maxh) | ||
1442 | height = maxh; | ||
1443 | if (width < 48) | ||
1444 | width = 48; | ||
1445 | if (width > maxw) | ||
1446 | width = maxw; | ||
1447 | |||
1448 | if(dev->is_em2800){ | ||
1449 | /* the em2800 can only scale down to 50% */ | ||
1450 | if(height % (maxh / 2)) | ||
1451 | height=maxh; | ||
1452 | if(width % (maxw / 2)) | ||
1453 | width=maxw; | ||
1454 | /* according to empiatech support */ | ||
1455 | /* the MaxPacketSize is to small to support */ | ||
1456 | /* framesizes larger than 640x480 @ 30 fps */ | ||
1457 | /* or 640x576 @ 25 fps. As this would cut */ | ||
1458 | /* of a part of the image we prefer */ | ||
1459 | /* 360x576 or 360x480 for now */ | ||
1460 | if(width == maxw && height == maxh) | ||
1461 | width /= 2; | ||
1462 | } | ||
1463 | |||
1464 | if ((hscale = | ||
1465 | (((unsigned long)maxw) << 12) / width - 4096L) >= | ||
1466 | 0x4000) | ||
1467 | hscale = 0x3fff; | ||
1468 | width = | ||
1469 | (((unsigned long)maxw) << 12) / (hscale + 4096L); | ||
1470 | |||
1471 | if ((vscale = | ||
1472 | (((unsigned long)maxh) << 12) / height - 4096L) >= | ||
1473 | 0x4000) | ||
1474 | vscale = 0x3fff; | ||
1475 | height = | ||
1476 | (((unsigned long)maxh) << 12) / (vscale + 4096L); | ||
1477 | |||
1478 | format->fmt.pix.width = width; | ||
1479 | format->fmt.pix.height = height; | ||
1480 | format->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; | ||
1481 | format->fmt.pix.bytesperline = width * 2; | ||
1482 | format->fmt.pix.sizeimage = width * 2 * height; | ||
1483 | format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
1484 | format->fmt.pix.field = V4L2_FIELD_INTERLACED; | ||
1485 | |||
1486 | em28xx_videodbg("%s: returned %dx%d (%d, %d)\n", | ||
1487 | cmd == | ||
1488 | VIDIOC_TRY_FMT ? "VIDIOC_TRY_FMT" : | ||
1489 | "VIDIOC_S_FMT", format->fmt.pix.width, | ||
1490 | format->fmt.pix.height, hscale, vscale); | ||
1491 | |||
1492 | if (cmd == VIDIOC_TRY_FMT) | ||
1493 | return 0; | ||
1494 | |||
1495 | for (i = 0; i < dev->num_frames; i++) | ||
1496 | if (dev->frame[i].vma_use_count) { | ||
1497 | em28xx_videodbg("VIDIOC_S_FMT failed. " | ||
1498 | "Unmap the buffers first.\n"); | ||
1499 | return -EINVAL; | ||
1500 | } | ||
1501 | |||
1502 | /* stop io in case it is already in progress */ | ||
1503 | if (dev->stream == STREAM_ON) { | ||
1504 | em28xx_videodbg("VIDIOC_SET_FMT: interupting stream\n"); | ||
1505 | if ((ret = em28xx_stream_interrupt(dev))) | ||
1506 | return ret; | ||
1507 | } | ||
1508 | |||
1509 | em28xx_release_buffers(dev); | ||
1510 | dev->io = IO_NONE; | ||
1511 | |||
1512 | /* set new image size */ | ||
1513 | dev->width = width; | ||
1514 | dev->height = height; | ||
1515 | dev->frame_size = dev->width * dev->height * 2; | ||
1516 | dev->field_size = dev->frame_size >> 1; /*both_fileds ? dev->frame_size>>1 : dev->frame_size; */ | ||
1517 | dev->bytesperline = dev->width * 2; | ||
1518 | dev->hscale = hscale; | ||
1519 | dev->vscale = vscale; | ||
1520 | /* dev->both_fileds = both_fileds; */ | ||
1521 | em28xx_uninit_isoc(dev); | ||
1522 | em28xx_set_alternate(dev); | ||
1523 | em28xx_capture_start(dev, 1); | ||
1524 | em28xx_resolution_set(dev); | ||
1525 | em28xx_init_isoc(dev); | ||
1526 | |||
1527 | return 0; | ||
1528 | } | ||
1529 | 1532 | ||
1530 | /* --- streaming capture ------------------------------------- */ | ||
1531 | case VIDIOC_REQBUFS: | 1533 | case VIDIOC_REQBUFS: |
1532 | { | 1534 | { |
1533 | struct v4l2_requestbuffers *rb = arg; | 1535 | struct v4l2_requestbuffers *rb = arg; |