aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c308
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
901static int em28xx_get_fmt(struct em28xx *dev, struct v4l2_format *format) 900static 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
945static 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;