aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2013-03-20 14:29:52 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2013-04-14 19:00:55 -0400
commit3315c59a45d5314c935a7dd82ab3c324c0d01343 (patch)
tree9938a497a3a0068516d43b455306f34202774338 /drivers/media
parent8f69da955873f5e33b60ff117856a2bf1309a336 (diff)
[media] hdpvr: add dv_timings support
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/usb/hdpvr/hdpvr-video.c217
-rw-r--r--drivers/media/usb/hdpvr/hdpvr.h1
2 files changed, 194 insertions, 24 deletions
diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c
index 042f204972a4..43763097d9bf 100644
--- a/drivers/media/usb/hdpvr/hdpvr-video.c
+++ b/drivers/media/usb/hdpvr/hdpvr-video.c
@@ -21,6 +21,7 @@
21#include <linux/workqueue.h> 21#include <linux/workqueue.h>
22 22
23#include <linux/videodev2.h> 23#include <linux/videodev2.h>
24#include <linux/v4l2-dv-timings.h>
24#include <media/v4l2-dev.h> 25#include <media/v4l2-dev.h>
25#include <media/v4l2-common.h> 26#include <media/v4l2-common.h>
26#include <media/v4l2-ioctl.h> 27#include <media/v4l2-ioctl.h>
@@ -36,6 +37,25 @@
36 list_size(&dev->free_buff_list), \ 37 list_size(&dev->free_buff_list), \
37 list_size(&dev->rec_buff_list)); } 38 list_size(&dev->rec_buff_list)); }
38 39
40static const struct v4l2_dv_timings hdpvr_dv_timings[] = {
41 V4L2_DV_BT_CEA_720X480I59_94,
42 V4L2_DV_BT_CEA_720X576I50,
43 V4L2_DV_BT_CEA_720X480P59_94,
44 V4L2_DV_BT_CEA_720X576P50,
45 V4L2_DV_BT_CEA_1280X720P50,
46 V4L2_DV_BT_CEA_1280X720P60,
47 V4L2_DV_BT_CEA_1920X1080I50,
48 V4L2_DV_BT_CEA_1920X1080I60,
49};
50
51/* Use 480i59 as the default timings */
52#define HDPVR_DEF_DV_TIMINGS_IDX (0)
53
54struct hdpvr_fh {
55 struct v4l2_fh fh;
56 bool legacy_mode;
57};
58
39static uint list_size(struct list_head *list) 59static uint list_size(struct list_head *list)
40{ 60{
41 struct list_head *tmp; 61 struct list_head *tmp;
@@ -355,13 +375,23 @@ static int hdpvr_stop_streaming(struct hdpvr_device *dev)
355 * video 4 linux 2 file operations 375 * video 4 linux 2 file operations
356 */ 376 */
357 377
378static int hdpvr_open(struct file *file)
379{
380 struct hdpvr_fh *fh = kzalloc(sizeof(*fh), GFP_KERNEL);
381
382 if (fh == NULL)
383 return -ENOMEM;
384 fh->legacy_mode = true;
385 v4l2_fh_init(&fh->fh, video_devdata(file));
386 v4l2_fh_add(&fh->fh);
387 file->private_data = fh;
388 return 0;
389}
390
358static int hdpvr_release(struct file *file) 391static int hdpvr_release(struct file *file)
359{ 392{
360 struct hdpvr_device *dev = video_drvdata(file); 393 struct hdpvr_device *dev = video_drvdata(file);
361 394
362 if (!dev)
363 return -ENODEV;
364
365 mutex_lock(&dev->io_mutex); 395 mutex_lock(&dev->io_mutex);
366 if (file->private_data == dev->owner) { 396 if (file->private_data == dev->owner) {
367 hdpvr_stop_streaming(dev); 397 hdpvr_stop_streaming(dev);
@@ -388,9 +418,6 @@ static ssize_t hdpvr_read(struct file *file, char __user *buffer, size_t count,
388 if (*pos) 418 if (*pos)
389 return -ESPIPE; 419 return -ESPIPE;
390 420
391 if (!dev)
392 return -ENODEV;
393
394 mutex_lock(&dev->io_mutex); 421 mutex_lock(&dev->io_mutex);
395 if (dev->status == STATUS_IDLE) { 422 if (dev->status == STATUS_IDLE) {
396 if (hdpvr_start_streaming(dev)) { 423 if (hdpvr_start_streaming(dev)) {
@@ -518,7 +545,7 @@ static unsigned int hdpvr_poll(struct file *filp, poll_table *wait)
518 545
519static const struct v4l2_file_operations hdpvr_fops = { 546static const struct v4l2_file_operations hdpvr_fops = {
520 .owner = THIS_MODULE, 547 .owner = THIS_MODULE,
521 .open = v4l2_fh_open, 548 .open = hdpvr_open,
522 .release = hdpvr_release, 549 .release = hdpvr_release,
523 .read = hdpvr_read, 550 .read = hdpvr_read,
524 .poll = hdpvr_poll, 551 .poll = hdpvr_poll,
@@ -594,6 +621,121 @@ static int vidioc_querystd(struct file *file, void *fh, v4l2_std_id *a)
594 return 0; 621 return 0;
595} 622}
596 623
624static int vidioc_s_dv_timings(struct file *file, void *_fh,
625 struct v4l2_dv_timings *timings)
626{
627 struct hdpvr_device *dev = video_drvdata(file);
628 struct hdpvr_fh *fh = _fh;
629 int i;
630
631 fh->legacy_mode = false;
632 if (dev->options.video_input)
633 return -ENODATA;
634 if (dev->status != STATUS_IDLE)
635 return -EBUSY;
636 for (i = 0; i < ARRAY_SIZE(hdpvr_dv_timings); i++)
637 if (v4l_match_dv_timings(timings, hdpvr_dv_timings + i, 0))
638 break;
639 if (i == ARRAY_SIZE(hdpvr_dv_timings))
640 return -EINVAL;
641 dev->cur_dv_timings = hdpvr_dv_timings[i];
642 dev->width = hdpvr_dv_timings[i].bt.width;
643 dev->height = hdpvr_dv_timings[i].bt.height;
644 return 0;
645}
646
647static int vidioc_g_dv_timings(struct file *file, void *_fh,
648 struct v4l2_dv_timings *timings)
649{
650 struct hdpvr_device *dev = video_drvdata(file);
651 struct hdpvr_fh *fh = _fh;
652
653 fh->legacy_mode = false;
654 if (dev->options.video_input)
655 return -ENODATA;
656 *timings = dev->cur_dv_timings;
657 return 0;
658}
659
660static int vidioc_query_dv_timings(struct file *file, void *_fh,
661 struct v4l2_dv_timings *timings)
662{
663 struct hdpvr_device *dev = video_drvdata(file);
664 struct hdpvr_fh *fh = _fh;
665 struct hdpvr_video_info *vid_info;
666 bool interlaced;
667 int ret = 0;
668 int i;
669
670 fh->legacy_mode = false;
671 if (dev->options.video_input)
672 return -ENODATA;
673 vid_info = get_video_info(dev);
674 if (vid_info == NULL)
675 return -ENOLCK;
676 interlaced = vid_info->fps <= 30;
677 for (i = 0; i < ARRAY_SIZE(hdpvr_dv_timings); i++) {
678 const struct v4l2_bt_timings *bt = &hdpvr_dv_timings[i].bt;
679 unsigned hsize;
680 unsigned vsize;
681 unsigned fps;
682
683 hsize = bt->hfrontporch + bt->hsync + bt->hbackporch + bt->width;
684 vsize = bt->vfrontporch + bt->vsync + bt->vbackporch +
685 bt->il_vfrontporch + bt->il_vsync + bt->il_vbackporch +
686 bt->height;
687 fps = (unsigned)bt->pixelclock / (hsize * vsize);
688 if (bt->width != vid_info->width ||
689 bt->height != vid_info->height ||
690 bt->interlaced != interlaced ||
691 (fps != vid_info->fps && fps + 1 != vid_info->fps))
692 continue;
693 *timings = hdpvr_dv_timings[i];
694 break;
695 }
696 if (i == ARRAY_SIZE(hdpvr_dv_timings))
697 ret = -ERANGE;
698 kfree(vid_info);
699 return ret;
700}
701
702static int vidioc_enum_dv_timings(struct file *file, void *_fh,
703 struct v4l2_enum_dv_timings *timings)
704{
705 struct hdpvr_device *dev = video_drvdata(file);
706 struct hdpvr_fh *fh = _fh;
707
708 fh->legacy_mode = false;
709 memset(timings->reserved, 0, sizeof(timings->reserved));
710 if (dev->options.video_input)
711 return -ENODATA;
712 if (timings->index >= ARRAY_SIZE(hdpvr_dv_timings))
713 return -EINVAL;
714 timings->timings = hdpvr_dv_timings[timings->index];
715 return 0;
716}
717
718static int vidioc_dv_timings_cap(struct file *file, void *_fh,
719 struct v4l2_dv_timings_cap *cap)
720{
721 struct hdpvr_device *dev = video_drvdata(file);
722 struct hdpvr_fh *fh = _fh;
723
724 fh->legacy_mode = false;
725 if (dev->options.video_input)
726 return -ENODATA;
727 cap->type = V4L2_DV_BT_656_1120;
728 cap->bt.min_width = 720;
729 cap->bt.max_width = 1920;
730 cap->bt.min_height = 480;
731 cap->bt.max_height = 1080;
732 cap->bt.min_pixelclock = 27000000;
733 cap->bt.max_pixelclock = 74250000;
734 cap->bt.standards = V4L2_DV_BT_STD_CEA861;
735 cap->bt.capabilities = V4L2_DV_BT_CAP_INTERLACED | V4L2_DV_BT_CAP_PROGRESSIVE;
736 return 0;
737}
738
597static const char *iname[] = { 739static const char *iname[] = {
598 [HDPVR_COMPONENT] = "Component", 740 [HDPVR_COMPONENT] = "Component",
599 [HDPVR_SVIDEO] = "S-Video", 741 [HDPVR_SVIDEO] = "S-Video",
@@ -827,29 +969,48 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *private_data,
827 return 0; 969 return 0;
828} 970}
829 971
830static int vidioc_g_fmt_vid_cap(struct file *file, void *private_data, 972static int vidioc_g_fmt_vid_cap(struct file *file, void *_fh,
831 struct v4l2_format *f) 973 struct v4l2_format *f)
832{ 974{
833 struct hdpvr_device *dev = video_drvdata(file); 975 struct hdpvr_device *dev = video_drvdata(file);
834 struct hdpvr_video_info *vid_info; 976 struct hdpvr_fh *fh = _fh;
835 977
836 if (!dev) 978 /*
837 return -ENODEV; 979 * The original driver would always returns the current detected
838 980 * resolution as the format (and EFAULT if it couldn't be detected).
839 vid_info = get_video_info(dev); 981 * With the introduction of VIDIOC_QUERY_DV_TIMINGS there is now a
840 if (!vid_info) 982 * better way of doing this, but to stay compatible with existing
841 return -EFAULT; 983 * applications we assume legacy mode every time an application opens
842 984 * the device. Only if one of the new DV_TIMINGS ioctls is called
843 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 985 * will the filehandle go into 'normal' mode where g_fmt returns the
986 * last set format.
987 */
988 if (fh->legacy_mode) {
989 struct hdpvr_video_info *vid_info;
990
991 vid_info = get_video_info(dev);
992 if (!vid_info)
993 return -EFAULT;
994 f->fmt.pix.width = vid_info->width;
995 f->fmt.pix.height = vid_info->height;
996 kfree(vid_info);
997 } else {
998 f->fmt.pix.width = dev->width;
999 f->fmt.pix.height = dev->height;
1000 }
844 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; 1001 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
845 f->fmt.pix.width = vid_info->width;
846 f->fmt.pix.height = vid_info->height;
847 f->fmt.pix.sizeimage = dev->bulk_in_size; 1002 f->fmt.pix.sizeimage = dev->bulk_in_size;
848 f->fmt.pix.colorspace = 0;
849 f->fmt.pix.bytesperline = 0; 1003 f->fmt.pix.bytesperline = 0;
850 f->fmt.pix.field = V4L2_FIELD_ANY; 1004 f->fmt.pix.priv = 0;
851 1005 if (f->fmt.pix.width == 720) {
852 kfree(vid_info); 1006 /* SDTV formats */
1007 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
1008 f->fmt.pix.field = V4L2_FIELD_INTERLACED;
1009 } else {
1010 /* HDTV formats */
1011 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE240M;
1012 f->fmt.pix.field = V4L2_FIELD_NONE;
1013 }
853 return 0; 1014 return 0;
854} 1015}
855 1016
@@ -916,6 +1077,11 @@ static const struct v4l2_ioctl_ops hdpvr_ioctl_ops = {
916 .vidioc_s_std = vidioc_s_std, 1077 .vidioc_s_std = vidioc_s_std,
917 .vidioc_g_std = vidioc_g_std, 1078 .vidioc_g_std = vidioc_g_std,
918 .vidioc_querystd = vidioc_querystd, 1079 .vidioc_querystd = vidioc_querystd,
1080 .vidioc_s_dv_timings = vidioc_s_dv_timings,
1081 .vidioc_g_dv_timings = vidioc_g_dv_timings,
1082 .vidioc_query_dv_timings= vidioc_query_dv_timings,
1083 .vidioc_enum_dv_timings = vidioc_enum_dv_timings,
1084 .vidioc_dv_timings_cap = vidioc_dv_timings_cap,
919 .vidioc_enum_input = vidioc_enum_input, 1085 .vidioc_enum_input = vidioc_enum_input,
920 .vidioc_g_input = vidioc_g_input, 1086 .vidioc_g_input = vidioc_g_input,
921 .vidioc_s_input = vidioc_s_input, 1087 .vidioc_s_input = vidioc_s_input,
@@ -924,6 +1090,8 @@ static const struct v4l2_ioctl_ops hdpvr_ioctl_ops = {
924 .vidioc_s_audio = vidioc_s_audio, 1090 .vidioc_s_audio = vidioc_s_audio,
925 .vidioc_enum_fmt_vid_cap= vidioc_enum_fmt_vid_cap, 1091 .vidioc_enum_fmt_vid_cap= vidioc_enum_fmt_vid_cap,
926 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, 1092 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1093 .vidioc_s_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1094 .vidioc_try_fmt_vid_cap = vidioc_g_fmt_vid_cap,
927 .vidioc_encoder_cmd = vidioc_encoder_cmd, 1095 .vidioc_encoder_cmd = vidioc_encoder_cmd,
928 .vidioc_try_encoder_cmd = vidioc_try_encoder_cmd, 1096 .vidioc_try_encoder_cmd = vidioc_try_encoder_cmd,
929 .vidioc_log_status = v4l2_ctrl_log_status, 1097 .vidioc_log_status = v4l2_ctrl_log_status,
@@ -975,6 +1143,7 @@ int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent,
975 dev->cur_std = V4L2_STD_525_60; 1143 dev->cur_std = V4L2_STD_525_60;
976 dev->width = 720; 1144 dev->width = 720;
977 dev->height = 480; 1145 dev->height = 480;
1146 dev->cur_dv_timings = hdpvr_dv_timings[HDPVR_DEF_DV_TIMINGS_IDX];
978 v4l2_ctrl_handler_init(hdl, 11); 1147 v4l2_ctrl_handler_init(hdl, 11);
979 if (dev->fw_ver > 0x15) { 1148 if (dev->fw_ver > 0x15) {
980 v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops, 1149 v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops,
diff --git a/drivers/media/usb/hdpvr/hdpvr.h b/drivers/media/usb/hdpvr/hdpvr.h
index 050c6b9fec53..1478f3d57630 100644
--- a/drivers/media/usb/hdpvr/hdpvr.h
+++ b/drivers/media/usb/hdpvr/hdpvr.h
@@ -92,6 +92,7 @@ struct hdpvr_device {
92 /* holds the current set options */ 92 /* holds the current set options */
93 struct hdpvr_options options; 93 struct hdpvr_options options;
94 v4l2_std_id cur_std; 94 v4l2_std_id cur_std;
95 struct v4l2_dv_timings cur_dv_timings;
95 96
96 uint flags; 97 uint flags;
97 98