aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx88/cx88-blackbird.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/cx88/cx88-blackbird.c')
-rw-r--r--drivers/media/video/cx88/cx88-blackbird.c778
1 files changed, 344 insertions, 434 deletions
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
index 187e917f6659..8fcef790fc12 100644
--- a/drivers/media/video/cx88/cx88-blackbird.c
+++ b/drivers/media/video/cx88/cx88-blackbird.c
@@ -6,6 +6,9 @@
6 * (c) 2004 Jelle Foks <jelle@foks.8m.com> 6 * (c) 2004 Jelle Foks <jelle@foks.8m.com>
7 * (c) 2004 Gerd Knorr <kraxel@bytesex.org> 7 * (c) 2004 Gerd Knorr <kraxel@bytesex.org>
8 * 8 *
9 * (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org>
10 * - video_ioctl2 conversion
11 *
9 * Includes parts from the ivtv driver( http://ivtv.sourceforge.net/), 12 * Includes parts from the ivtv driver( http://ivtv.sourceforge.net/),
10 * 13 *
11 * This program is free software; you can redistribute it and/or modify 14 * This program is free software; you can redistribute it and/or modify
@@ -53,73 +56,6 @@ MODULE_PARM_DESC(debug,"enable debug messages [blackbird]");
53 56
54/* ------------------------------------------------------------------ */ 57/* ------------------------------------------------------------------ */
55 58
56
57struct cx88_tvnorm {
58 char *name;
59 v4l2_std_id id;
60 u32 cxiformat;
61 u32 cxoformat;
62};
63
64static struct cx88_tvnorm tvnorms[] = {
65 {
66 .name = "NTSC-M",
67 .id = V4L2_STD_NTSC_M,
68 .cxiformat = VideoFormatNTSC,
69 .cxoformat = 0x181f0008,
70 },{
71 .name = "NTSC-JP",
72 .id = V4L2_STD_NTSC_M_JP,
73 .cxiformat = VideoFormatNTSCJapan,
74 .cxoformat = 0x181f0008,
75 },{
76 .name = "PAL-BG",
77 .id = V4L2_STD_PAL_BG,
78 .cxiformat = VideoFormatPAL,
79 .cxoformat = 0x181f0008,
80 },{
81 .name = "PAL-DK",
82 .id = V4L2_STD_PAL_DK,
83 .cxiformat = VideoFormatPAL,
84 .cxoformat = 0x181f0008,
85 },{
86 .name = "PAL-I",
87 .id = V4L2_STD_PAL_I,
88 .cxiformat = VideoFormatPAL,
89 .cxoformat = 0x181f0008,
90 },{
91 .name = "PAL-M",
92 .id = V4L2_STD_PAL_M,
93 .cxiformat = VideoFormatPALM,
94 .cxoformat = 0x1c1f0008,
95 },{
96 .name = "PAL-N",
97 .id = V4L2_STD_PAL_N,
98 .cxiformat = VideoFormatPALN,
99 .cxoformat = 0x1c1f0008,
100 },{
101 .name = "PAL-Nc",
102 .id = V4L2_STD_PAL_Nc,
103 .cxiformat = VideoFormatPALNC,
104 .cxoformat = 0x1c1f0008,
105 },{
106 .name = "PAL-60",
107 .id = V4L2_STD_PAL_60,
108 .cxiformat = VideoFormatPAL60,
109 .cxoformat = 0x181f0008,
110 },{
111 .name = "SECAM-L",
112 .id = V4L2_STD_SECAM_L,
113 .cxiformat = VideoFormatSECAM,
114 .cxoformat = 0x181f0008,
115 },{
116 .name = "SECAM-DK",
117 .id = V4L2_STD_SECAM_DK,
118 .cxiformat = VideoFormatSECAM,
119 .cxoformat = 0x181f0008,
120 }
121};
122
123#define BLACKBIRD_FIRM_IMAGE_SIZE 256*1024 59#define BLACKBIRD_FIRM_IMAGE_SIZE 256*1024
124 60
125/* defines below are from ivtv-driver.h */ 61/* defines below are from ivtv-driver.h */
@@ -777,8 +713,13 @@ static int blackbird_queryctrl(struct cx8802_dev *dev, struct v4l2_queryctrl *qc
777 return 0; 713 return 0;
778} 714}
779 715
780static int blackbird_querymenu(struct cx8802_dev *dev, struct v4l2_querymenu *qmenu) 716/* ------------------------------------------------------------------ */
717/* IOCTL Handlers */
718
719static int vidioc_querymenu (struct file *file, void *priv,
720 struct v4l2_querymenu *qmenu)
781{ 721{
722 struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
782 struct v4l2_queryctrl qctrl; 723 struct v4l2_queryctrl qctrl;
783 724
784 qctrl.id = qmenu->id; 725 qctrl.id = qmenu->id;
@@ -786,413 +727,347 @@ static int blackbird_querymenu(struct cx8802_dev *dev, struct v4l2_querymenu *qm
786 return v4l2_ctrl_query_menu(qmenu, &qctrl, cx2341x_ctrl_get_menu(qmenu->id)); 727 return v4l2_ctrl_query_menu(qmenu, &qctrl, cx2341x_ctrl_get_menu(qmenu->id));
787} 728}
788 729
789/* ------------------------------------------------------------------ */ 730static int vidioc_querycap (struct file *file, void *priv,
790 731 struct v4l2_capability *cap)
791static int mpeg_do_ioctl(struct inode *inode, struct file *file,
792 unsigned int cmd, void *arg)
793{ 732{
794 struct cx8802_fh *fh = file->private_data; 733 struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
795 struct cx8802_dev *dev = fh->dev;
796 struct cx88_core *core = dev->core; 734 struct cx88_core *core = dev->core;
797 735
798 if (debug > 1) 736 strcpy(cap->driver, "cx88_blackbird");
799 v4l_print_ioctl(core->name,cmd); 737 strlcpy(cap->card, cx88_boards[core->board].name,sizeof(cap->card));
738 sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci));
739 cap->version = CX88_VERSION_CODE;
740 cap->capabilities =
741 V4L2_CAP_VIDEO_CAPTURE |
742 V4L2_CAP_READWRITE |
743 V4L2_CAP_STREAMING;
744 if (UNSET != core->tuner_type)
745 cap->capabilities |= V4L2_CAP_TUNER;
746 return 0;
747}
748
749static int vidioc_enum_fmt_cap (struct file *file, void *priv,
750 struct v4l2_fmtdesc *f)
751{
752 if (f->index != 0)
753 return -EINVAL;
800 754
801 switch (cmd) { 755 strlcpy(f->description, "MPEG", sizeof(f->description));
756 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
757 f->pixelformat = V4L2_PIX_FMT_MPEG;
758 return 0;
759}
802 760
803 /* --- capabilities ------------------------------------------ */ 761static int vidioc_g_fmt_cap (struct file *file, void *priv,
804 case VIDIOC_QUERYCAP: 762 struct v4l2_format *f)
805 { 763{
806 struct v4l2_capability *cap = arg; 764 struct cx8802_fh *fh = priv;
765 struct cx8802_dev *dev = fh->dev;
766
767 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
768 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
769 f->fmt.pix.bytesperline = 0;
770 f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */
771 f->fmt.pix.colorspace = 0;
772 f->fmt.pix.width = dev->width;
773 f->fmt.pix.height = dev->height;
774 f->fmt.pix.field = fh->mpegq.field;
775 dprintk(0,"VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",
776 dev->width, dev->height, fh->mpegq.field );
777 return 0;
778}
807 779
808 memset(cap,0,sizeof(*cap)); 780static int vidioc_try_fmt_cap (struct file *file, void *priv,
809 strcpy(cap->driver, "cx88_blackbird"); 781 struct v4l2_format *f)
810 strlcpy(cap->card, cx88_boards[core->board].name,sizeof(cap->card)); 782{
811 sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci)); 783 struct cx8802_fh *fh = priv;
812 cap->version = CX88_VERSION_CODE; 784 struct cx8802_dev *dev = fh->dev;
813 cap->capabilities = 785
814 V4L2_CAP_VIDEO_CAPTURE | 786 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
815 V4L2_CAP_READWRITE | 787 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
816 V4L2_CAP_STREAMING; 788 f->fmt.pix.bytesperline = 0;
817 if (UNSET != core->tuner_type) 789 f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */;
818 cap->capabilities |= V4L2_CAP_TUNER; 790 f->fmt.pix.colorspace = 0;
791 dprintk(0,"VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
792 dev->width, dev->height, fh->mpegq.field );
793 return 0;
794}
819 795
820 return 0; 796static int vidioc_s_fmt_cap (struct file *file, void *priv,
821 } 797 struct v4l2_format *f)
798{
799 struct cx8802_fh *fh = priv;
800 struct cx8802_dev *dev = fh->dev;
801 struct cx88_core *core = dev->core;
822 802
823 /* --- capture ioctls ---------------------------------------- */ 803 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
824 case VIDIOC_ENUM_FMT: 804 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
825 { 805 f->fmt.pix.bytesperline = 0;
826 struct v4l2_fmtdesc *f = arg; 806 f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */;
827 int index; 807 f->fmt.pix.colorspace = 0;
828 808 dev->width = f->fmt.pix.width;
829 index = f->index; 809 dev->height = f->fmt.pix.height;
830 if (index != 0) 810 fh->mpegq.field = f->fmt.pix.field;
831 return -EINVAL; 811 cx88_set_scale(core, f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
832 812 blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
833 memset(f,0,sizeof(*f)); 813 f->fmt.pix.height, f->fmt.pix.width);
834 f->index = index; 814 dprintk(0,"VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
835 strlcpy(f->description, "MPEG", sizeof(f->description)); 815 f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field );
836 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 816 return 0;
837 f->pixelformat = V4L2_PIX_FMT_MPEG; 817}
838 return 0;
839 }
840 case VIDIOC_G_FMT:
841 {
842 struct v4l2_format *f = arg;
843
844 memset(f,0,sizeof(*f));
845 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
846 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
847 f->fmt.pix.bytesperline = 0;
848 f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */
849 f->fmt.pix.colorspace = 0;
850 f->fmt.pix.width = dev->width;
851 f->fmt.pix.height = dev->height;
852 f->fmt.pix.field = fh->mpegq.field;
853 dprintk(0,"VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",
854 dev->width, dev->height, fh->mpegq.field );
855 return 0;
856 }
857 case VIDIOC_TRY_FMT:
858 {
859 struct v4l2_format *f = arg;
860
861 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
862 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
863 f->fmt.pix.bytesperline = 0;
864 f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */;
865 f->fmt.pix.colorspace = 0;
866 dprintk(0,"VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
867 dev->width, dev->height, fh->mpegq.field );
868 return 0;
869 }
870 case VIDIOC_S_FMT:
871 {
872 struct v4l2_format *f = arg;
873
874 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
875 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
876 f->fmt.pix.bytesperline = 0;
877 f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */;
878 f->fmt.pix.colorspace = 0;
879 dprintk(0,"VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
880 f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field );
881 return 0;
882 }
883 818
884 /* --- streaming capture ------------------------------------- */ 819static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p)
885 case VIDIOC_REQBUFS: 820{
886 return videobuf_reqbufs(&fh->mpegq, arg); 821 struct cx8802_fh *fh = priv;
822 return (videobuf_reqbufs(&fh->mpegq, p));
823}
887 824
888 case VIDIOC_QUERYBUF: 825static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p)
889 return videobuf_querybuf(&fh->mpegq, arg); 826{
827 struct cx8802_fh *fh = priv;
828 return (videobuf_querybuf(&fh->mpegq, p));
829}
890 830
891 case VIDIOC_QBUF: 831static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p)
892 return videobuf_qbuf(&fh->mpegq, arg); 832{
833 struct cx8802_fh *fh = priv;
834 return (videobuf_qbuf(&fh->mpegq, p));
835}
893 836
894 case VIDIOC_DQBUF: 837static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p)
895 return videobuf_dqbuf(&fh->mpegq, arg, 838{
896 file->f_flags & O_NONBLOCK); 839 struct cx8802_fh *fh = priv;
840 return (videobuf_dqbuf(&fh->mpegq, p,
841 file->f_flags & O_NONBLOCK));
842}
897 843
898 case VIDIOC_STREAMON: 844static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
899 return videobuf_streamon(&fh->mpegq); 845{
846 struct cx8802_fh *fh = priv;
847 return videobuf_streamon(&fh->mpegq);
848}
900 849
901 case VIDIOC_STREAMOFF: 850static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
902 return videobuf_streamoff(&fh->mpegq); 851{
852 struct cx8802_fh *fh = priv;
853 return videobuf_streamoff(&fh->mpegq);
854}
903 855
904 /* --- mpeg compression -------------------------------------- */ 856static int vidioc_g_mpegcomp (struct file *file, void *fh,
905 case VIDIOC_G_MPEGCOMP: 857 struct v4l2_mpeg_compression *f)
906 { 858{
907 struct v4l2_mpeg_compression *f = arg; 859 printk(KERN_WARNING "VIDIOC_G_MPEGCOMP is obsolete. "
860 "Replace with VIDIOC_G_EXT_CTRLS!");
861 memcpy(f,&default_mpeg_params,sizeof(*f));
862 return 0;
863}
908 864
909 printk(KERN_WARNING "VIDIOC_G_MPEGCOMP is obsolete. " 865static int vidioc_s_mpegcomp (struct file *file, void *fh,
910 "Replace with VIDIOC_G_EXT_CTRLS!"); 866 struct v4l2_mpeg_compression *f)
911 memcpy(f,&default_mpeg_params,sizeof(*f)); 867{
912 return 0; 868 printk(KERN_WARNING "VIDIOC_S_MPEGCOMP is obsolete. "
913 } 869 "Replace with VIDIOC_S_EXT_CTRLS!");
914 case VIDIOC_S_MPEGCOMP: 870 return 0;
915 printk(KERN_WARNING "VIDIOC_S_MPEGCOMP is obsolete. " 871}
916 "Replace with VIDIOC_S_EXT_CTRLS!");
917 return 0;
918 case VIDIOC_G_EXT_CTRLS:
919 {
920 struct v4l2_ext_controls *f = arg;
921 872
922 if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) 873static int vidioc_g_ext_ctrls (struct file *file, void *priv,
923 return -EINVAL; 874 struct v4l2_ext_controls *f)
924 return cx2341x_ext_ctrls(&dev->params, f, cmd); 875{
925 } 876 struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
926 case VIDIOC_S_EXT_CTRLS:
927 {
928 struct v4l2_ext_controls *f = arg;
929 struct cx2341x_mpeg_params p;
930 int err;
931
932 if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
933 return -EINVAL;
934 p = dev->params;
935 err = cx2341x_ext_ctrls(&p, VIDIOC_S_EXT_CTRLS, cmd);
936 if (err == 0 && cmd == VIDIOC_S_EXT_CTRLS) {
937 err = cx2341x_update(dev, blackbird_mbox_func, &dev->params, &p);
938 dev->params = p;
939 }
940 return err;
941 }
942 case VIDIOC_TRY_EXT_CTRLS:
943 {
944 struct v4l2_ext_controls *f = arg;
945 struct cx2341x_mpeg_params p;
946 int err;
947
948 if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
949 return -EINVAL;
950 p = dev->params;
951 err = cx2341x_ext_ctrls(&p, VIDIOC_TRY_EXT_CTRLS, cmd);
952 return err;
953 }
954 case VIDIOC_S_FREQUENCY:
955 {
956 struct v4l2_frequency *f = arg;
957 877
958 blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, 878 if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
959 BLACKBIRD_END_NOW, 879 return -EINVAL;
960 BLACKBIRD_MPEG_CAPTURE, 880 return cx2341x_ext_ctrls(&dev->params, f, VIDIOC_G_EXT_CTRLS);
961 BLACKBIRD_RAW_BITS_NONE); 881}
962 882
963 cx88_set_freq (core,f); 883static int vidioc_s_ext_ctrls (struct file *file, void *priv,
884 struct v4l2_ext_controls *f)
885{
886 struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
887 struct cx2341x_mpeg_params p;
888 int err;
964 889
965 blackbird_initialize_codec(dev); 890 if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
966 cx88_set_scale(dev->core, dev->width, dev->height, 891 return -EINVAL;
967 fh->mpegq.field); 892 p = dev->params;
968 return 0; 893 err = cx2341x_ext_ctrls(&p, f, VIDIOC_S_EXT_CTRLS);
969 } 894 if (!err) {
970 case VIDIOC_LOG_STATUS: 895 err = cx2341x_update(dev, blackbird_mbox_func, &dev->params, &p);
971 { 896 dev->params = p;
972 char name[32 + 2];
973
974 snprintf(name, sizeof(name), "%s/2", core->name);
975 printk("%s/2: ============ START LOG STATUS ============\n",
976 core->name);
977 cx88_call_i2c_clients(core, VIDIOC_LOG_STATUS, NULL);
978 cx2341x_log_status(&dev->params, name);
979 printk("%s/2: ============= END LOG STATUS =============\n",
980 core->name);
981 return 0;
982 } 897 }
983 case VIDIOC_QUERYMENU: 898 return err;
984 return blackbird_querymenu(dev, arg); 899}
985 case VIDIOC_QUERYCTRL:
986 {
987 struct v4l2_queryctrl *qctrl = arg;
988 900
989 if (blackbird_queryctrl(dev, qctrl) == 0) 901static int vidioc_try_ext_ctrls (struct file *file, void *priv,
990 return 0; 902 struct v4l2_ext_controls *f)
903{
904 struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
905 struct cx2341x_mpeg_params p;
906 int err;
991 907
992 struct v4l2_queryctrl *qctrl = arg; 908 if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
909 return -EINVAL;
910 p = dev->params;
911 err = cx2341x_ext_ctrls(&p, f, VIDIOC_TRY_EXT_CTRLS);
993 912
994 qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id); 913 return err;
995 if (unlikely(qctrl->id == 0)) 914}
996 return -EINVAL;
997 return cx8800_ctrl_query(qctrl);
998 }
999 915
1000 /* ------ input switching ---------- */ 916static int vidioc_s_frequency (struct file *file, void *priv,
1001 case VIDIOC_ENUMINPUT: 917 struct v4l2_frequency *f)
1002 { 918{
1003 static const char *iname[] = { 919 struct cx8802_fh *fh = priv;
1004 [ CX88_VMUX_COMPOSITE1 ] = "Composite1", 920 struct cx8802_dev *dev = fh->dev;
1005 [ CX88_VMUX_COMPOSITE2 ] = "Composite2", 921 struct cx88_core *core = dev->core;
1006 [ CX88_VMUX_COMPOSITE3 ] = "Composite3",
1007 [ CX88_VMUX_COMPOSITE4 ] = "Composite4",
1008 [ CX88_VMUX_SVIDEO ] = "S-Video",
1009 [ CX88_VMUX_TELEVISION ] = "Television",
1010 [ CX88_VMUX_CABLE ] = "Cable TV",
1011 [ CX88_VMUX_DVB ] = "DVB",
1012 [ CX88_VMUX_DEBUG ] = "for debug only",
1013 };
1014 struct v4l2_input *i = arg;
1015 unsigned int n;
1016
1017 n = i->index;
1018 if (n >= 4)
1019 return -EINVAL;
1020 if (0 == INPUT(n)->type)
1021 return -EINVAL;
1022 memset(i,0,sizeof(*i));
1023 i->index = n;
1024 i->type = V4L2_INPUT_TYPE_CAMERA;
1025 strcpy(i->name,iname[INPUT(n)->type]);
1026 if ((CX88_VMUX_TELEVISION == INPUT(n)->type) ||
1027 (CX88_VMUX_CABLE == INPUT(n)->type))
1028 i->type = V4L2_INPUT_TYPE_TUNER;
1029 for (n = 0; n < ARRAY_SIZE(tvnorms); n++)
1030 i->std |= tvnorms[n].id;
1031 return 0;
1032 }
1033 case VIDIOC_G_CTRL:
1034 return cx88_get_control(core,arg);
1035 case VIDIOC_S_CTRL:
1036 return cx88_set_control(core,arg);
1037 922
1038 case VIDIOC_G_FREQUENCY: 923 blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
1039 { 924 BLACKBIRD_END_NOW,
1040 struct v4l2_frequency *f = arg; 925 BLACKBIRD_MPEG_CAPTURE,
926 BLACKBIRD_RAW_BITS_NONE);
927 cx88_set_freq (core,f);
928 blackbird_initialize_codec(dev);
929 cx88_set_scale(dev->core, dev->width, dev->height,
930 fh->mpegq.field);
931 return 0;
932}
1041 933
1042 memset(f,0,sizeof(*f)); 934static int vidioc_log_status (struct file *file, void *priv)
935{
936 struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
937 struct cx88_core *core = dev->core;
938 char name[32 + 2];
939
940 snprintf(name, sizeof(name), "%s/2", core->name);
941 printk("%s/2: ============ START LOG STATUS ============\n",
942 core->name);
943 cx88_call_i2c_clients(core, VIDIOC_LOG_STATUS, NULL);
944 cx2341x_log_status(&dev->params, name);
945 printk("%s/2: ============= END LOG STATUS =============\n",
946 core->name);
947 return 0;
948}
1043 949
1044 if (UNSET == core->tuner_type) 950static int vidioc_queryctrl (struct file *file, void *priv,
1045 return -EINVAL; 951 struct v4l2_queryctrl *qctrl)
952{
953 struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
1046 954
1047 /* f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; */ 955 if (blackbird_queryctrl(dev, qctrl) == 0)
1048 f->type = radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; 956 return 0;
1049 f->frequency = core->freq;
1050 957
1051 cx88_call_i2c_clients(core,VIDIOC_G_FREQUENCY,f); 958 qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
959 if (unlikely(qctrl->id == 0))
960 return -EINVAL;
961 return cx8800_ctrl_query(qctrl);
962}
1052 963
1053 return 0; 964static int vidioc_enum_input (struct file *file, void *priv,
1054 } 965 struct v4l2_input *i)
1055 case VIDIOC_G_INPUT: 966{
1056 { 967 struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
1057 unsigned int *i = arg; 968 return cx88_enum_input (core,i);
969}
1058 970
1059 *i = core->input; 971static int vidioc_g_ctrl (struct file *file, void *priv,
1060 return 0; 972 struct v4l2_control *ctl)
1061 } 973{
1062 case VIDIOC_S_INPUT: 974 struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
1063 { 975 return
1064 unsigned int *i = arg; 976 cx88_get_control(core,ctl);
1065 977}
1066 if (*i >= 4)
1067 return -EINVAL;
1068 mutex_lock(&core->lock);
1069 cx88_newstation(core);
1070 cx88_video_mux(core,*i);
1071 mutex_unlock(&core->lock);
1072 return 0;
1073 }
1074 978
979static int vidioc_s_ctrl (struct file *file, void *priv,
980 struct v4l2_control *ctl)
981{
982 struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
983 return
984 cx88_set_control(core,ctl);
985}
1075 986
1076 case VIDIOC_G_TUNER: 987static int vidioc_g_frequency (struct file *file, void *priv,
1077 { 988 struct v4l2_frequency *f)
1078 struct v4l2_tuner *t = arg; 989{
1079 u32 reg; 990 struct cx8802_fh *fh = priv;
991 struct cx88_core *core = fh->dev->core;
1080 992
1081 if (UNSET == core->tuner_type) 993 if (unlikely(UNSET == core->tuner_type))
1082 return -EINVAL; 994 return -EINVAL;
1083 if (0 != t->index)
1084 return -EINVAL;
1085 995
1086 memset(t,0,sizeof(*t)); 996 f->type = V4L2_TUNER_ANALOG_TV;
1087 strcpy(t->name, "Television"); 997 f->frequency = core->freq;
1088 t->type = V4L2_TUNER_ANALOG_TV; 998 cx88_call_i2c_clients(core,VIDIOC_G_FREQUENCY,f);
1089 t->capability = V4L2_TUNER_CAP_NORM;
1090 t->rangehigh = 0xffffffffUL;
1091 999
1092 cx88_get_stereo(core ,t); 1000 return 0;
1093 reg = cx_read(MO_DEVICE_STATUS); 1001}
1094 t->signal = (reg & (1<<5)) ? 0xffff : 0x0000;
1095 return 0;
1096 }
1097 case VIDIOC_S_TUNER:
1098 {
1099 struct v4l2_tuner *t = arg;
1100
1101 if (UNSET == core->tuner_type)
1102 return -EINVAL;
1103 if (0 != t->index)
1104 return -EINVAL;
1105 cx88_set_stereo(core, t->audmode, 1);
1106 return 0;
1107 }
1108 /* ---------- tv norms ---------- */
1109 case VIDIOC_S_STD:
1110 {
1111 v4l2_std_id *id = arg;
1112 unsigned int i;
1113
1114 for(i = 0; i < ARRAY_SIZE(tvnorms); i++)
1115 if (*id & tvnorms[i].id)
1116 break;
1117 if (i == ARRAY_SIZE(tvnorms))
1118 return -EINVAL;
1119
1120 mutex_lock(&core->lock);
1121 cx88_set_tvnorm(core,tvnorms[i].id);
1122 mutex_unlock(&core->lock);
1123 return 0;
1124 }
1125 case VIDIOC_ENUMSTD:
1126 {
1127 struct v4l2_standard *e = arg;
1128 unsigned int i;
1129
1130 i = e->index;
1131 if (i >= ARRAY_SIZE(tvnorms))
1132 return -EINVAL;
1133 err = v4l2_video_std_construct(e, tvnorms[e->index].id,
1134 tvnorms[e->index].name);
1135 e->index = i;
1136 if (err < 0)
1137 return err;
1138 return 0;
1139 }
1140 case VIDIOC_G_STD:
1141 {
1142 v4l2_std_id *id = arg;
1143 1002
1144 *id = core->tvnorm; 1003static int vidioc_g_input (struct file *file, void *priv, unsigned int *i)
1145 return 0; 1004{
1146 } 1005 struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
1147 1006
1148#ifdef CONFIG_VIDEO_ADV_DEBUG 1007 *i = core->input;
1149 /* ioctls to allow direct acces to the cx2388x registers */ 1008 return 0;
1150 case VIDIOC_INT_G_REGISTER: 1009}
1151 {
1152 struct v4l2_register *reg = arg;
1153 1010
1154 if (reg->i2c_id != 0) 1011static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
1155 return -EINVAL; 1012{
1156 /* cx2388x has a 24-bit register space */ 1013 struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
1157 reg->val = cx_read(reg->reg&0xffffff);
1158 return 0;
1159 }
1160 case VIDIOC_INT_S_REGISTER:
1161 {
1162 struct v4l2_register *reg = arg;
1163
1164 if (reg->i2c_id != 0)
1165 return -EINVAL;
1166 if (!capable(CAP_SYS_ADMIN))
1167 return -EPERM;
1168 cx_write(reg->reg&0xffffff, reg->val);
1169 return 0;
1170 }
1171#endif
1172 1014
1173 default: 1015 if (i >= 4)
1174 return v4l_compat_translate_ioctl(inode,file,cmd,arg, 1016 return -EINVAL;
1175 driver_ioctl); 1017
1176 } 1018 mutex_lock(&core->lock);
1019 cx88_newstation(core);
1020 cx88_video_mux(core,i);
1021 mutex_unlock(&core->lock);
1177 return 0; 1022 return 0;
1178} 1023}
1179 1024
1180int (*cx88_ioctl_hook)(struct inode *inode, struct file *file, 1025static int vidioc_g_tuner (struct file *file, void *priv,
1181 unsigned int cmd, void *arg); 1026 struct v4l2_tuner *t)
1182unsigned int (*cx88_ioctl_translator)(unsigned int cmd); 1027{
1028 struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
1029 u32 reg;
1030
1031 if (unlikely(UNSET == core->tuner_type))
1032 return -EINVAL;
1033
1034 strcpy(t->name, "Television");
1035 t->type = V4L2_TUNER_ANALOG_TV;
1036 t->capability = V4L2_TUNER_CAP_NORM;
1037 t->rangehigh = 0xffffffffUL;
1038
1039 cx88_get_stereo(core ,t);
1040 reg = cx_read(MO_DEVICE_STATUS);
1041 t->signal = (reg & (1<<5)) ? 0xffff : 0x0000;
1042 return 0;
1043}
1183 1044
1184static unsigned int mpeg_translate_ioctl(unsigned int cmd) 1045static int vidioc_s_tuner (struct file *file, void *priv,
1046 struct v4l2_tuner *t)
1185{ 1047{
1186 return cmd; 1048 struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
1049
1050 if (UNSET == core->tuner_type)
1051 return -EINVAL;
1052 if (0 != t->index)
1053 return -EINVAL;
1054
1055 cx88_set_stereo(core, t->audmode, 1);
1056 return 0;
1187} 1057}
1188 1058
1189static int mpeg_ioctl(struct inode *inode, struct file *file, 1059static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id)
1190 unsigned int cmd, unsigned long arg)
1191{ 1060{
1192 cmd = cx88_ioctl_translator( cmd ); 1061 struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
1193 return video_usercopy(inode, file, cmd, arg, cx88_ioctl_hook); 1062
1063 mutex_lock(&core->lock);
1064 cx88_set_tvnorm(core,*id);
1065 mutex_unlock(&core->lock);
1066 return 0;
1194} 1067}
1195 1068
1069/* FIXME: cx88_ioctl_hook not implemented */
1070
1196static int mpeg_open(struct inode *inode, struct file *file) 1071static int mpeg_open(struct inode *inode, struct file *file)
1197{ 1072{
1198 int minor = iminor(inode); 1073 int minor = iminor(inode);
@@ -1318,17 +1193,47 @@ static const struct file_operations mpeg_fops =
1318 .read = mpeg_read, 1193 .read = mpeg_read,
1319 .poll = mpeg_poll, 1194 .poll = mpeg_poll,
1320 .mmap = mpeg_mmap, 1195 .mmap = mpeg_mmap,
1321 .ioctl = mpeg_ioctl, 1196 .ioctl = video_ioctl2,
1322 .llseek = no_llseek, 1197 .llseek = no_llseek,
1323}; 1198};
1324 1199
1325static struct video_device cx8802_mpeg_template = 1200static struct video_device cx8802_mpeg_template =
1326{ 1201{
1327 .name = "cx8802", 1202 .name = "cx8802",
1328 .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_SCALES|VID_TYPE_MPEG_ENCODER, 1203 .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_SCALES|VID_TYPE_MPEG_ENCODER,
1329 .hardware = 0, 1204 .fops = &mpeg_fops,
1330 .fops = &mpeg_fops, 1205 .minor = -1,
1331 .minor = -1, 1206 .vidioc_querymenu = vidioc_querymenu,
1207 .vidioc_querycap = vidioc_querycap,
1208 .vidioc_enum_fmt_cap = vidioc_enum_fmt_cap,
1209 .vidioc_g_fmt_cap = vidioc_g_fmt_cap,
1210 .vidioc_try_fmt_cap = vidioc_try_fmt_cap,
1211 .vidioc_s_fmt_cap = vidioc_s_fmt_cap,
1212 .vidioc_reqbufs = vidioc_reqbufs,
1213 .vidioc_querybuf = vidioc_querybuf,
1214 .vidioc_qbuf = vidioc_qbuf,
1215 .vidioc_dqbuf = vidioc_dqbuf,
1216 .vidioc_streamon = vidioc_streamon,
1217 .vidioc_streamoff = vidioc_streamoff,
1218 .vidioc_g_mpegcomp = vidioc_g_mpegcomp,
1219 .vidioc_s_mpegcomp = vidioc_s_mpegcomp,
1220 .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls,
1221 .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls,
1222 .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls,
1223 .vidioc_s_frequency = vidioc_s_frequency,
1224 .vidioc_log_status = vidioc_log_status,
1225 .vidioc_queryctrl = vidioc_queryctrl,
1226 .vidioc_enum_input = vidioc_enum_input,
1227 .vidioc_g_ctrl = vidioc_g_ctrl,
1228 .vidioc_s_ctrl = vidioc_s_ctrl,
1229 .vidioc_g_frequency = vidioc_g_frequency,
1230 .vidioc_g_input = vidioc_g_input,
1231 .vidioc_s_input = vidioc_s_input,
1232 .vidioc_g_tuner = vidioc_g_tuner,
1233 .vidioc_s_tuner = vidioc_s_tuner,
1234 .vidioc_s_std = vidioc_s_std,
1235 .tvnorms = CX88_NORMS,
1236 .current_norm = V4L2_STD_PAL_BG,
1332}; 1237};
1333 1238
1334/* ------------------------------------------------------------------ */ 1239/* ------------------------------------------------------------------ */
@@ -1423,6 +1328,8 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv)
1423 cx2341x_fill_defaults(&dev->params); 1328 cx2341x_fill_defaults(&dev->params);
1424 dev->params.port = CX2341X_PORT_STREAMING; 1329 dev->params.port = CX2341X_PORT_STREAMING;
1425 1330
1331 cx8802_mpeg_template.current_norm = core->tvnorm;
1332
1426 if (core->tvnorm & V4L2_STD_525_60) { 1333 if (core->tvnorm & V4L2_STD_525_60) {
1427 dev->height = 480; 1334 dev->height = 480;
1428 } else { 1335 } else {
@@ -1437,6 +1344,11 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv)
1437 blackbird_register_video(dev); 1344 blackbird_register_video(dev);
1438 1345
1439 /* initial device configuration: needed ? */ 1346 /* initial device configuration: needed ? */
1347 mutex_lock(&dev->core->lock);
1348// init_controls(core);
1349 cx88_set_tvnorm(core,core->tvnorm);
1350 cx88_video_mux(core,0);
1351 mutex_unlock(&dev->core->lock);
1440 1352
1441 return 0; 1353 return 0;
1442 1354
@@ -1471,8 +1383,6 @@ static int blackbird_init(void)
1471 printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", 1383 printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
1472 SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); 1384 SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
1473#endif 1385#endif
1474 cx88_ioctl_hook = mpeg_do_ioctl;
1475 cx88_ioctl_translator = mpeg_translate_ioctl;
1476 return cx8802_register_driver(&cx8802_blackbird_driver); 1386 return cx8802_register_driver(&cx8802_blackbird_driver);
1477} 1387}
1478 1388
@@ -1484,8 +1394,8 @@ static void blackbird_fini(void)
1484module_init(blackbird_init); 1394module_init(blackbird_init);
1485module_exit(blackbird_fini); 1395module_exit(blackbird_fini);
1486 1396
1487EXPORT_SYMBOL(cx88_ioctl_hook); 1397module_param_named(video_debug,cx8802_mpeg_template.debug, int, 0644);
1488EXPORT_SYMBOL(cx88_ioctl_translator); 1398MODULE_PARM_DESC(debug,"enable debug messages [video]");
1489 1399
1490/* ----------------------------------------------------------- */ 1400/* ----------------------------------------------------------- */
1491/* 1401/*