aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/cx88/cx88-core.c55
-rw-r--r--drivers/media/video/cx88/cx88-vbi.c7
-rw-r--r--drivers/media/video/cx88/cx88-video.c1072
-rw-r--r--drivers/media/video/cx88/cx88.h20
4 files changed, 521 insertions, 633 deletions
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c
index 18997361c75..278d2df77cd 100644
--- a/drivers/media/video/cx88/cx88-core.c
+++ b/drivers/media/video/cx88/cx88-core.c
@@ -5,6 +5,11 @@
5 * 5 *
6 * (c) 2003 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] 6 * (c) 2003 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
7 * 7 *
8 * (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org>
9 * - Multituner support
10 * - video_ioctl2 conversion
11 * - PAL/M fixes
12 *
8 * This program is free software; you can redistribute it and/or modify 13 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by 14 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or 15 * the Free Software Foundation; either version 2 of the License, or
@@ -631,22 +636,22 @@ int cx88_reset(struct cx88_core *core)
631 636
632/* ------------------------------------------------------------------ */ 637/* ------------------------------------------------------------------ */
633 638
634static unsigned int inline norm_swidth(struct cx88_tvnorm *norm) 639static unsigned int inline norm_swidth(struct v4l2_tvnorm *norm)
635{ 640{
636 return (norm->id & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 754 : 922; 641 return (norm->id & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 754 : 922;
637} 642}
638 643
639static unsigned int inline norm_hdelay(struct cx88_tvnorm *norm) 644static unsigned int inline norm_hdelay(struct v4l2_tvnorm *norm)
640{ 645{
641 return (norm->id & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 135 : 186; 646 return (norm->id & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 135 : 186;
642} 647}
643 648
644static unsigned int inline norm_vdelay(struct cx88_tvnorm *norm) 649static unsigned int inline norm_vdelay(struct v4l2_tvnorm *norm)
645{ 650{
646 return (norm->id & V4L2_STD_625_50) ? 0x24 : 0x18; 651 return (norm->id & V4L2_STD_625_50) ? 0x24 : 0x18;
647} 652}
648 653
649static unsigned int inline norm_fsc8(struct cx88_tvnorm *norm) 654static unsigned int inline norm_fsc8(struct v4l2_tvnorm *norm)
650{ 655{
651 if (norm->id & V4L2_STD_PAL_M) 656 if (norm->id & V4L2_STD_PAL_M)
652 return 28604892; // 3.575611 MHz 657 return 28604892; // 3.575611 MHz
@@ -666,7 +671,7 @@ static unsigned int inline norm_fsc8(struct cx88_tvnorm *norm)
666 return 35468950; // 4.43361875 MHz +/- 5 Hz 671 return 35468950; // 4.43361875 MHz +/- 5 Hz
667} 672}
668 673
669static unsigned int inline norm_htotal(struct cx88_tvnorm *norm) 674static unsigned int inline norm_htotal(struct v4l2_tvnorm *norm)
670{ 675{
671 676
672 unsigned int fsc4=norm_fsc8(norm)/2; 677 unsigned int fsc4=norm_fsc8(norm)/2;
@@ -677,7 +682,7 @@ static unsigned int inline norm_htotal(struct cx88_tvnorm *norm)
677 ((fsc4+262)/525*1001+15000)/30000; 682 ((fsc4+262)/525*1001+15000)/30000;
678} 683}
679 684
680static unsigned int inline norm_vbipack(struct cx88_tvnorm *norm) 685static unsigned int inline norm_vbipack(struct v4l2_tvnorm *norm)
681{ 686{
682 return (norm->id & V4L2_STD_625_50) ? 511 : 400; 687 return (norm->id & V4L2_STD_625_50) ? 511 : 400;
683} 688}
@@ -826,7 +831,7 @@ int cx88_stop_audio_dma(struct cx88_core *core)
826 831
827static int set_tvaudio(struct cx88_core *core) 832static int set_tvaudio(struct cx88_core *core)
828{ 833{
829 struct cx88_tvnorm *norm = core->tvnorm; 834 struct v4l2_tvnorm *norm = core->tvnorm;
830 835
831 if (CX88_VMUX_TELEVISION != INPUT(core->input)->type) 836 if (CX88_VMUX_TELEVISION != INPUT(core->input)->type)
832 return 0; 837 return 0;
@@ -874,7 +879,7 @@ static int set_tvaudio(struct cx88_core *core)
874 879
875 880
876 881
877int cx88_set_tvnorm(struct cx88_core *core, struct cx88_tvnorm *norm) 882int cx88_set_tvnorm(struct cx88_core *core, struct v4l2_tvnorm *norm)
878{ 883{
879 u32 fsc8; 884 u32 fsc8;
880 u32 adc_clock; 885 u32 adc_clock;
@@ -882,6 +887,7 @@ int cx88_set_tvnorm(struct cx88_core *core, struct cx88_tvnorm *norm)
882 u32 step_db,step_dr; 887 u32 step_db,step_dr;
883 u64 tmp64; 888 u64 tmp64;
884 u32 bdelay,agcdelay,htotal; 889 u32 bdelay,agcdelay,htotal;
890 u32 cxiformat, cxoformat;
885 891
886 core->tvnorm = norm; 892 core->tvnorm = norm;
887 fsc8 = norm_fsc8(norm); 893 fsc8 = norm_fsc8(norm);
@@ -890,9 +896,32 @@ int cx88_set_tvnorm(struct cx88_core *core, struct cx88_tvnorm *norm)
890 step_db = fsc8; 896 step_db = fsc8;
891 step_dr = fsc8; 897 step_dr = fsc8;
892 898
893 if (norm->id & V4L2_STD_SECAM) { 899 if (norm->id & V4L2_STD_NTSC_M_JP) {
900 cxiformat = VideoFormatNTSCJapan;
901 cxoformat = 0x181f0008;
902 } else if (norm->id & V4L2_STD_PAL_M) {
903 cxiformat = VideoFormatPALM;
904 cxoformat = 0x1c1f0008;
905 } else if (norm->id & V4L2_STD_PAL_N) {
906 cxiformat = VideoFormatPALN;
907 cxoformat = 0x1c1f0008;
908 } else if (norm->id & V4L2_STD_PAL_Nc) {
909 cxiformat = VideoFormatPALNC;
910 cxoformat = 0x1c1f0008;
911 } else if (norm->id & V4L2_STD_PAL_60) {
912 cxiformat = VideoFormatPAL60;
913 cxoformat = 0x181f0008;
914 } else if (norm->id & V4L2_STD_NTSC) {
915 cxiformat = VideoFormatNTSC;
916 cxoformat = 0x181f0008;
917 } else if (norm->id & V4L2_STD_SECAM) {
918 cxiformat = VideoFormatSECAM;
919 cxoformat = 0x181f0008;
894 step_db = 4250000 * 8; 920 step_db = 4250000 * 8;
895 step_dr = 4406250 * 8; 921 step_dr = 4406250 * 8;
922 } else { /* PAL */
923 cxiformat = VideoFormatPAL;
924 cxoformat = 0x181f0008;
896 } 925 }
897 926
898 dprintk(1,"set_tvnorm: \"%s\" fsc8=%d adc=%d vdec=%d db/dr=%d/%d\n", 927 dprintk(1,"set_tvnorm: \"%s\" fsc8=%d adc=%d vdec=%d db/dr=%d/%d\n",
@@ -900,13 +929,13 @@ int cx88_set_tvnorm(struct cx88_core *core, struct cx88_tvnorm *norm)
900 set_pll(core,2,vdec_clock); 929 set_pll(core,2,vdec_clock);
901 930
902 dprintk(1,"set_tvnorm: MO_INPUT_FORMAT 0x%08x [old=0x%08x]\n", 931 dprintk(1,"set_tvnorm: MO_INPUT_FORMAT 0x%08x [old=0x%08x]\n",
903 norm->cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f); 932 cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f);
904 cx_andor(MO_INPUT_FORMAT, 0xf, norm->cxiformat); 933 cx_andor(MO_INPUT_FORMAT, 0xf, cxiformat);
905 934
906 // FIXME: as-is from DScaler 935 // FIXME: as-is from DScaler
907 dprintk(1,"set_tvnorm: MO_OUTPUT_FORMAT 0x%08x [old=0x%08x]\n", 936 dprintk(1,"set_tvnorm: MO_OUTPUT_FORMAT 0x%08x [old=0x%08x]\n",
908 norm->cxoformat, cx_read(MO_OUTPUT_FORMAT)); 937 cxoformat, cx_read(MO_OUTPUT_FORMAT));
909 cx_write(MO_OUTPUT_FORMAT, norm->cxoformat); 938 cx_write(MO_OUTPUT_FORMAT, cxoformat);
910 939
911 // MO_SCONV_REG = adc clock / video dec clock * 2^17 940 // MO_SCONV_REG = adc clock / video dec clock * 2^17
912 tmp64 = adc_clock * (u64)(1 << 17); 941 tmp64 = adc_clock * (u64)(1 << 17);
diff --git a/drivers/media/video/cx88/cx88-vbi.c b/drivers/media/video/cx88/cx88-vbi.c
index aa2a6977009..b6b968851d7 100644
--- a/drivers/media/video/cx88/cx88-vbi.c
+++ b/drivers/media/video/cx88/cx88-vbi.c
@@ -21,9 +21,11 @@ MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]");
21 21
22/* ------------------------------------------------------------------ */ 22/* ------------------------------------------------------------------ */
23 23
24void cx8800_vbi_fmt(struct cx8800_dev *dev, struct v4l2_format *f) 24int cx8800_vbi_fmt (struct file *file, void *priv,
25 struct v4l2_format *f)
25{ 26{
26 memset(&f->fmt.vbi,0,sizeof(f->fmt.vbi)); 27 struct cx8800_fh *fh = priv;
28 struct cx8800_dev *dev = fh->dev;
27 29
28 f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH; 30 f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH;
29 f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; 31 f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
@@ -43,6 +45,7 @@ void cx8800_vbi_fmt(struct cx8800_dev *dev, struct v4l2_format *f)
43 f->fmt.vbi.start[0] = 7 -1; 45 f->fmt.vbi.start[0] = 7 -1;
44 f->fmt.vbi.start[1] = 319 -1; 46 f->fmt.vbi.start[1] = 319 -1;
45 } 47 }
48 return 0;
46} 49}
47 50
48static int cx8800_start_vbi_dma(struct cx8800_dev *dev, 51static int cx8800_start_vbi_dma(struct cx8800_dev *dev,
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index c86a7e06235..d9d1a07f3a4 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -1,3 +1,4 @@
1
1/* 2/*
2 * 3 *
3 * device driver for Conexant 2388x based TV cards 4 * device driver for Conexant 2388x based TV cards
@@ -5,6 +6,11 @@
5 * 6 *
6 * (c) 2003-04 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] 7 * (c) 2003-04 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
7 * 8 *
9 * (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org>
10 * - Multituner support
11 * - video_ioctl2 conversion
12 * - PAL/M fixes
13 *
8 * 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
9 * it under the terms of the GNU General Public License as published by 15 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or 16 * the Free Software Foundation; either version 2 of the License, or
@@ -80,62 +86,47 @@ static LIST_HEAD(cx8800_devlist);
80/* ------------------------------------------------------------------- */ 86/* ------------------------------------------------------------------- */
81/* static data */ 87/* static data */
82 88
83static struct cx88_tvnorm tvnorms[] = { 89static struct v4l2_tvnorm tvnorms[] = {
84 { 90 {
85 .name = "NTSC-M", 91 .name = "NTSC-M",
86 .id = V4L2_STD_NTSC_M, 92 .id = V4L2_STD_NTSC_M,
87 .cxiformat = VideoFormatNTSC,
88 .cxoformat = 0x181f0008,
89 },{ 93 },{
90 .name = "NTSC-JP", 94 .name = "NTSC-JP",
91 .id = V4L2_STD_NTSC_M_JP, 95 .id = V4L2_STD_NTSC_M_JP,
92 .cxiformat = VideoFormatNTSCJapan,
93 .cxoformat = 0x181f0008,
94 },{ 96 },{
95 .name = "PAL-BG", 97 .name = "PAL-BG",
96 .id = V4L2_STD_PAL_BG, 98 .id = V4L2_STD_PAL_BG,
97 .cxiformat = VideoFormatPAL,
98 .cxoformat = 0x181f0008,
99 },{ 99 },{
100 .name = "PAL-DK", 100 .name = "PAL-DK",
101 .id = V4L2_STD_PAL_DK, 101 .id = V4L2_STD_PAL_DK,
102 .cxiformat = VideoFormatPAL,
103 .cxoformat = 0x181f0008,
104 },{ 102 },{
105 .name = "PAL-I", 103 .name = "PAL-I",
106 .id = V4L2_STD_PAL_I, 104 .id = V4L2_STD_PAL_I,
107 .cxiformat = VideoFormatPAL,
108 .cxoformat = 0x181f0008,
109 },{ 105 },{
110 .name = "PAL-M", 106 .name = "PAL-M",
111 .id = V4L2_STD_PAL_M, 107 .id = V4L2_STD_PAL_M,
112 .cxiformat = VideoFormatPALM,
113 .cxoformat = 0x1c1f0008,
114 },{ 108 },{
115 .name = "PAL-N", 109 .name = "PAL-N",
116 .id = V4L2_STD_PAL_N, 110 .id = V4L2_STD_PAL_N,
117 .cxiformat = VideoFormatPALN,
118 .cxoformat = 0x1c1f0008,
119 },{ 111 },{
120 .name = "PAL-Nc", 112 .name = "PAL-Nc",
121 .id = V4L2_STD_PAL_Nc, 113 .id = V4L2_STD_PAL_Nc,
122 .cxiformat = VideoFormatPALNC,
123 .cxoformat = 0x1c1f0008,
124 },{ 114 },{
125 .name = "PAL-60", 115 .name = "PAL-60",
126 .id = V4L2_STD_PAL_60, 116 .id = V4L2_STD_PAL_60,
127 .cxiformat = VideoFormatPAL60,
128 .cxoformat = 0x181f0008,
129 },{ 117 },{
130 .name = "SECAM-L", 118 .name = "SECAM-L",
131 .id = V4L2_STD_SECAM_L, 119 .id = V4L2_STD_SECAM_L,
132 .cxiformat = VideoFormatSECAM,
133 .cxoformat = 0x181f0008,
134 },{ 120 },{
135 .name = "SECAM-DK", 121 .name = "SECAM-DK",
136 .id = V4L2_STD_SECAM_DK, 122 .id = V4L2_STD_SECAM_DK,
137 .cxiformat = VideoFormatSECAM, 123 }
138 .cxoformat = 0x181f0008, 124};
125
126static struct v4l2_tvnorm radionorms[] = {
127 {
128 .name = "RADIO",
129 .id = 0,
139 } 130 }
140}; 131};
141 132
@@ -364,14 +355,6 @@ int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl)
364} 355}
365EXPORT_SYMBOL(cx8800_ctrl_query); 356EXPORT_SYMBOL(cx8800_ctrl_query);
366 357
367static int cx88_queryctrl(struct v4l2_queryctrl *qctrl)
368{
369 qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
370 if (qctrl->id == 0)
371 return -EINVAL;
372 return cx8800_ctrl_query(qctrl);
373}
374
375/* ------------------------------------------------------------------- */ 358/* ------------------------------------------------------------------- */
376/* resource management */ 359/* resource management */
377 360
@@ -944,19 +927,20 @@ video_mmap(struct file *file, struct vm_area_struct * vma)
944} 927}
945 928
946/* ------------------------------------------------------------------ */ 929/* ------------------------------------------------------------------ */
930/* VIDEO CTRL IOCTLS */
947 931
948/* static int get_control(struct cx8800_dev *dev, struct v4l2_control *ctl) */ 932static int vidioc_g_ctrl (struct file *file, void *priv,
949static int get_control(struct cx88_core *core, struct v4l2_control *ctl) 933 struct v4l2_control *ctl)
950{ 934{
951 /* struct cx88_core *core = dev->core; */ 935 struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
952 struct cx88_ctrl *c = NULL; 936 struct cx88_ctrl *c = NULL;
953 u32 value; 937 u32 value;
954 int i; 938 int i;
955 939
956 for (i = 0; i < CX8800_CTLS; i++) 940 for (i = 0; i < CX8800_CTLS; i++)
957 if (cx8800_ctls[i].v.id == ctl->id) 941 if (cx8800_ctls[i].v.id == ctl->id)
958 c = &cx8800_ctls[i]; 942 c = &cx8800_ctls[i];
959 if (NULL == c) 943 if (unlikely(NULL == c))
960 return -EINVAL; 944 return -EINVAL;
961 945
962 value = c->sreg ? cx_sread(c->sreg) : cx_read(c->reg); 946 value = c->sreg ? cx_sread(c->sreg) : cx_read(c->reg);
@@ -978,19 +962,18 @@ static int get_control(struct cx88_core *core, struct v4l2_control *ctl)
978 return 0; 962 return 0;
979} 963}
980 964
981/* static int set_control(struct cx8800_dev *dev, struct v4l2_control *ctl) */
982static int set_control(struct cx88_core *core, struct v4l2_control *ctl) 965static int set_control(struct cx88_core *core, struct v4l2_control *ctl)
983{ 966{
984 /* struct cx88_core *core = dev->core; */
985 struct cx88_ctrl *c = NULL; 967 struct cx88_ctrl *c = NULL;
986 u32 value,mask; 968 u32 value,mask;
987 int i; 969 int i;
970
988 for (i = 0; i < CX8800_CTLS; i++) { 971 for (i = 0; i < CX8800_CTLS; i++) {
989 if (cx8800_ctls[i].v.id == ctl->id) { 972 if (cx8800_ctls[i].v.id == ctl->id) {
990 c = &cx8800_ctls[i]; 973 c = &cx8800_ctls[i];
991 } 974 }
992 } 975 }
993 if (NULL == c) 976 if (unlikely(NULL == c))
994 return -EINVAL; 977 return -EINVAL;
995 978
996 if (ctl->value < c->v.minimum) 979 if (ctl->value < c->v.minimum)
@@ -1042,648 +1025,483 @@ static void init_controls(struct cx88_core *core)
1042 for (i = 0; i < CX8800_CTLS; i++) { 1025 for (i = 0; i < CX8800_CTLS; i++) {
1043 ctrl.id=cx8800_ctls[i].v.id; 1026 ctrl.id=cx8800_ctls[i].v.id;
1044 ctrl.value=cx8800_ctls[i].v.default_value; 1027 ctrl.value=cx8800_ctls[i].v.default_value;
1028
1045 set_control(core, &ctrl); 1029 set_control(core, &ctrl);
1046 } 1030 }
1047} 1031}
1048 1032
1049/* ------------------------------------------------------------------ */ 1033/* ------------------------------------------------------------------ */
1034/* VIDEO IOCTLS */
1035
1036static int vidioc_g_fmt_cap (struct file *file, void *priv,
1037 struct v4l2_format *f)
1038{
1039 struct cx8800_fh *fh = priv;
1040
1041 f->fmt.pix.width = fh->width;
1042 f->fmt.pix.height = fh->height;
1043 f->fmt.pix.field = fh->vidq.field;
1044 f->fmt.pix.pixelformat = fh->fmt->fourcc;
1045 f->fmt.pix.bytesperline =
1046 (f->fmt.pix.width * fh->fmt->depth) >> 3;
1047 f->fmt.pix.sizeimage =
1048 f->fmt.pix.height * f->fmt.pix.bytesperline;
1049 return 0;
1050}
1050 1051
1051static int cx8800_g_fmt(struct cx8800_dev *dev, struct cx8800_fh *fh, 1052static int vidioc_try_fmt_cap (struct file *file, void *priv,
1052 struct v4l2_format *f) 1053 struct v4l2_format *f)
1053{ 1054{
1054 switch (f->type) { 1055 struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
1055 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 1056 struct cx8800_fmt *fmt;
1056 memset(&f->fmt.pix,0,sizeof(f->fmt.pix)); 1057 enum v4l2_field field;
1057 f->fmt.pix.width = fh->width; 1058 unsigned int maxw, maxh;
1058 f->fmt.pix.height = fh->height; 1059
1059 f->fmt.pix.field = fh->vidq.field; 1060 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
1060 f->fmt.pix.pixelformat = fh->fmt->fourcc; 1061 if (NULL == fmt)
1061 f->fmt.pix.bytesperline = 1062 return -EINVAL;
1062 (f->fmt.pix.width * fh->fmt->depth) >> 3; 1063
1063 f->fmt.pix.sizeimage = 1064 field = f->fmt.pix.field;
1064 f->fmt.pix.height * f->fmt.pix.bytesperline; 1065 maxw = norm_maxw(core->tvnorm);
1065 return 0; 1066 maxh = norm_maxh(core->tvnorm);
1066 case V4L2_BUF_TYPE_VBI_CAPTURE: 1067
1067 cx8800_vbi_fmt(dev, f); 1068 if (V4L2_FIELD_ANY == field) {
1068 return 0; 1069 field = (f->fmt.pix.height > maxh/2)
1070 ? V4L2_FIELD_INTERLACED
1071 : V4L2_FIELD_BOTTOM;
1072 }
1073
1074 switch (field) {
1075 case V4L2_FIELD_TOP:
1076 case V4L2_FIELD_BOTTOM:
1077 maxh = maxh / 2;
1078 break;
1079 case V4L2_FIELD_INTERLACED:
1080 break;
1069 default: 1081 default:
1070 return -EINVAL; 1082 return -EINVAL;
1071 } 1083 }
1084
1085 f->fmt.pix.field = field;
1086 if (f->fmt.pix.height < 32)
1087 f->fmt.pix.height = 32;
1088 if (f->fmt.pix.height > maxh)
1089 f->fmt.pix.height = maxh;
1090 if (f->fmt.pix.width < 48)
1091 f->fmt.pix.width = 48;
1092 if (f->fmt.pix.width > maxw)
1093 f->fmt.pix.width = maxw;
1094 f->fmt.pix.width &= ~0x03;
1095 f->fmt.pix.bytesperline =
1096 (f->fmt.pix.width * fmt->depth) >> 3;
1097 f->fmt.pix.sizeimage =
1098 f->fmt.pix.height * f->fmt.pix.bytesperline;
1099
1100 return 0;
1072} 1101}
1073 1102
1074static int cx8800_try_fmt(struct cx8800_dev *dev, struct cx8800_fh *fh, 1103static int vidioc_s_fmt_cap (struct file *file, void *priv,
1075 struct v4l2_format *f) 1104 struct v4l2_format *f)
1076{ 1105{
1077 struct cx88_core *core = dev->core; 1106 struct cx8800_fh *fh = priv;
1107 int err = vidioc_try_fmt_cap (file,priv,f);
1078 1108
1079 switch (f->type) { 1109 if (0 != err)
1080 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 1110 return err;
1081 { 1111 fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat);
1082 struct cx8800_fmt *fmt; 1112 fh->width = f->fmt.pix.width;
1083 enum v4l2_field field; 1113 fh->height = f->fmt.pix.height;
1084 unsigned int maxw, maxh; 1114 fh->vidq.field = f->fmt.pix.field;
1085 1115 return 0;
1086 fmt = format_by_fourcc(f->fmt.pix.pixelformat); 1116}
1087 if (NULL == fmt)
1088 return -EINVAL;
1089
1090 field = f->fmt.pix.field;
1091 maxw = norm_maxw(core->tvnorm);
1092 maxh = norm_maxh(core->tvnorm);
1093
1094 if (V4L2_FIELD_ANY == field) {
1095 field = (f->fmt.pix.height > maxh/2)
1096 ? V4L2_FIELD_INTERLACED
1097 : V4L2_FIELD_BOTTOM;
1098 }
1099 1117
1100 switch (field) { 1118static int vidioc_querycap (struct file *file, void *priv,
1101 case V4L2_FIELD_TOP: 1119 struct v4l2_capability *cap)
1102 case V4L2_FIELD_BOTTOM: 1120{
1103 maxh = maxh / 2; 1121 struct cx8800_dev *dev = ((struct cx8800_fh *)priv)->dev;
1104 break; 1122 struct cx88_core *core = dev->core;
1105 case V4L2_FIELD_INTERLACED:
1106 break;
1107 default:
1108 return -EINVAL;
1109 }
1110 1123
1111 f->fmt.pix.field = field; 1124 strcpy(cap->driver, "cx8800");
1112 if (f->fmt.pix.height < 32) 1125 strlcpy(cap->card, cx88_boards[core->board].name,
1113 f->fmt.pix.height = 32; 1126 sizeof(cap->card));
1114 if (f->fmt.pix.height > maxh) 1127 sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci));
1115 f->fmt.pix.height = maxh; 1128 cap->version = CX88_VERSION_CODE;
1116 if (f->fmt.pix.width < 48) 1129 cap->capabilities =
1117 f->fmt.pix.width = 48; 1130 V4L2_CAP_VIDEO_CAPTURE |
1118 if (f->fmt.pix.width > maxw) 1131 V4L2_CAP_READWRITE |
1119 f->fmt.pix.width = maxw; 1132 V4L2_CAP_STREAMING |
1120 f->fmt.pix.width &= ~0x03; 1133 V4L2_CAP_VBI_CAPTURE;
1121 f->fmt.pix.bytesperline = 1134 if (UNSET != core->tuner_type)
1122 (f->fmt.pix.width * fmt->depth) >> 3; 1135 cap->capabilities |= V4L2_CAP_TUNER;
1123 f->fmt.pix.sizeimage = 1136 return 0;
1124 f->fmt.pix.height * f->fmt.pix.bytesperline; 1137}
1125 1138
1126 return 0; 1139static int vidioc_enum_fmt_cap (struct file *file, void *priv,
1127 } 1140 struct v4l2_fmtdesc *f)
1128 case V4L2_BUF_TYPE_VBI_CAPTURE: 1141{
1129 cx8800_vbi_fmt(dev, f); 1142 if (unlikely(f->index >= ARRAY_SIZE(formats)))
1130 return 0;
1131 default:
1132 return -EINVAL; 1143 return -EINVAL;
1133 } 1144
1145 strlcpy(f->description,formats[f->index].name,sizeof(f->description));
1146 f->pixelformat = formats[f->index].fourcc;
1147
1148 return 0;
1134} 1149}
1135 1150
1136static int cx8800_s_fmt(struct cx8800_dev *dev, struct cx8800_fh *fh, 1151#ifdef CONFIG_VIDEO_V4L1_COMPAT
1137 struct v4l2_format *f) 1152static int vidiocgmbuf (struct file *file, void *priv, struct video_mbuf *mbuf)
1138{ 1153{
1154 struct cx8800_fh *fh = priv;
1155 struct videobuf_queue *q;
1156 struct v4l2_requestbuffers req;
1157 unsigned int i;
1139 int err; 1158 int err;
1140 1159
1141 switch (f->type) { 1160 q = get_queue(fh);
1142 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 1161 memset(&req,0,sizeof(req));
1143 err = cx8800_try_fmt(dev,fh,f); 1162 req.type = q->type;
1144 if (0 != err) 1163 req.count = 8;
1145 return err; 1164 req.memory = V4L2_MEMORY_MMAP;
1165 err = videobuf_reqbufs(q,&req);
1166 if (err < 0)
1167 return err;
1146 1168
1147 fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); 1169 mbuf->frames = req.count;
1148 fh->width = f->fmt.pix.width; 1170 mbuf->size = 0;
1149 fh->height = f->fmt.pix.height; 1171 for (i = 0; i < mbuf->frames; i++) {
1150 fh->vidq.field = f->fmt.pix.field; 1172 mbuf->offsets[i] = q->bufs[i]->boff;
1151 return 0; 1173 mbuf->size += q->bufs[i]->bsize;
1152 case V4L2_BUF_TYPE_VBI_CAPTURE:
1153 cx8800_vbi_fmt(dev, f);
1154 return 0;
1155 default:
1156 return -EINVAL;
1157 } 1174 }
1175 return 0;
1158} 1176}
1177#endif
1159 1178
1160/* 1179
1161 * This function is _not_ called directly, but from 1180static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p)
1162 * video_generic_ioctl (and maybe others). userspace
1163 * copying is done already, arg is a kernel pointer.
1164 */
1165static int video_do_ioctl(struct inode *inode, struct file *file,
1166 unsigned int cmd, void *arg)
1167{ 1181{
1168 struct cx8800_fh *fh = file->private_data; 1182 struct cx8800_fh *fh = priv;
1169 struct cx8800_dev *dev = fh->dev; 1183 return (videobuf_reqbufs(get_queue(fh), p));
1170 struct cx88_core *core = dev->core; 1184}
1171 int err;
1172 1185
1173 if (video_debug > 1) 1186static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p)
1174 v4l_print_ioctl(core->name,cmd); 1187{
1175 switch (cmd) { 1188 struct cx8800_fh *fh = priv;
1189 return (videobuf_querybuf(get_queue(fh), p));
1190}
1176 1191
1177 /* --- capabilities ------------------------------------------ */ 1192static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p)
1178 case VIDIOC_QUERYCAP: 1193{
1179 { 1194 struct cx8800_fh *fh = priv;
1180 struct v4l2_capability *cap = arg; 1195 return (videobuf_qbuf(get_queue(fh), p));
1181 1196}
1182 memset(cap,0,sizeof(*cap));
1183 strcpy(cap->driver, "cx8800");
1184 strlcpy(cap->card, cx88_boards[core->board].name,
1185 sizeof(cap->card));
1186 sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci));
1187 cap->version = CX88_VERSION_CODE;
1188 cap->capabilities =
1189 V4L2_CAP_VIDEO_CAPTURE |
1190 V4L2_CAP_READWRITE |
1191 V4L2_CAP_STREAMING |
1192 V4L2_CAP_VBI_CAPTURE |
1193 0;
1194 if (UNSET != core->tuner_type)
1195 cap->capabilities |= V4L2_CAP_TUNER;
1196 return 0;
1197 }
1198 1197
1199 /* --- capture ioctls ---------------------------------------- */ 1198static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p)
1200 case VIDIOC_ENUM_FMT: 1199{
1201 { 1200 struct cx8800_fh *fh = priv;
1202 struct v4l2_fmtdesc *f = arg; 1201 return (videobuf_dqbuf(get_queue(fh), p,
1203 enum v4l2_buf_type type; 1202 file->f_flags & O_NONBLOCK));
1204 unsigned int index; 1203}
1205
1206 index = f->index;
1207 type = f->type;
1208 switch (type) {
1209 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1210 if (index >= ARRAY_SIZE(formats))
1211 return -EINVAL;
1212 memset(f,0,sizeof(*f));
1213 f->index = index;
1214 f->type = type;
1215 strlcpy(f->description,formats[index].name,sizeof(f->description));
1216 f->pixelformat = formats[index].fourcc;
1217 break;
1218 default:
1219 return -EINVAL;
1220 }
1221 return 0;
1222 }
1223 case VIDIOC_G_FMT:
1224 {
1225 struct v4l2_format *f = arg;
1226 return cx8800_g_fmt(dev,fh,f);
1227 }
1228 case VIDIOC_S_FMT:
1229 {
1230 struct v4l2_format *f = arg;
1231 return cx8800_s_fmt(dev,fh,f);
1232 }
1233 case VIDIOC_TRY_FMT:
1234 {
1235 struct v4l2_format *f = arg;
1236 return cx8800_try_fmt(dev,fh,f);
1237 }
1238#ifdef CONFIG_VIDEO_V4L1_COMPAT
1239 /* --- streaming capture ------------------------------------- */
1240 case VIDIOCGMBUF:
1241 {
1242 struct video_mbuf *mbuf = arg;
1243 struct videobuf_queue *q;
1244 struct v4l2_requestbuffers req;
1245 unsigned int i;
1246
1247 q = get_queue(fh);
1248 memset(&req,0,sizeof(req));
1249 req.type = q->type;
1250 req.count = 8;
1251 req.memory = V4L2_MEMORY_MMAP;
1252 err = videobuf_reqbufs(q,&req);
1253 if (err < 0)
1254 return err;
1255 memset(mbuf,0,sizeof(*mbuf));
1256 mbuf->frames = req.count;
1257 mbuf->size = 0;
1258 for (i = 0; i < mbuf->frames; i++) {
1259 mbuf->offsets[i] = q->bufs[i]->boff;
1260 mbuf->size += q->bufs[i]->bsize;
1261 }
1262 return 0;
1263 }
1264#endif
1265 case VIDIOC_REQBUFS:
1266 return videobuf_reqbufs(get_queue(fh), arg);
1267 1204
1268 case VIDIOC_QUERYBUF: 1205static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
1269 return videobuf_querybuf(get_queue(fh), arg); 1206{
1207 struct cx8800_fh *fh = priv;
1208 struct cx8800_dev *dev = fh->dev;
1270 1209
1271 case VIDIOC_QBUF: 1210 if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE))
1272 return videobuf_qbuf(get_queue(fh), arg); 1211 return -EINVAL;
1212 if (unlikely(i != fh->type))
1213 return -EINVAL;
1273 1214
1274 case VIDIOC_DQBUF: 1215 if (unlikely(!res_get(dev,fh,get_ressource(fh))))
1275 return videobuf_dqbuf(get_queue(fh), arg, 1216 return -EBUSY;
1276 file->f_flags & O_NONBLOCK); 1217 return videobuf_streamon(get_queue(fh));
1218}
1277 1219
1278 case VIDIOC_STREAMON: 1220static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
1279 { 1221{
1280 int res = get_ressource(fh); 1222 struct cx8800_fh *fh = priv;
1223 struct cx8800_dev *dev = fh->dev;
1224 int err, res;
1281 1225
1282 if (!res_get(dev,fh,res)) 1226 if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1283 return -EBUSY; 1227 return -EINVAL;
1284 return videobuf_streamon(get_queue(fh)); 1228 if (i != fh->type)
1285 } 1229 return -EINVAL;
1286 case VIDIOC_STREAMOFF:
1287 {
1288 int res = get_ressource(fh);
1289 1230
1290 err = videobuf_streamoff(get_queue(fh)); 1231 res = get_ressource(fh);
1291 if (err < 0) 1232 err = videobuf_streamoff(get_queue(fh));
1292 return err; 1233 if (err < 0)
1293 res_free(dev,fh,res); 1234 return err;
1294 return 0; 1235 res_free(dev,fh,res);
1295 }
1296 default:
1297 return cx88_do_ioctl( inode, file, fh->radio, core, cmd, arg, video_do_ioctl );
1298 }
1299 return 0; 1236 return 0;
1300} 1237}
1301 1238
1302int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, 1239static int vidioc_s_std (struct file *file, void *priv, unsigned int i)
1303 struct cx88_core *core, unsigned int cmd, void *arg, v4l2_kioctl driver_ioctl)
1304{ 1240{
1305 int err; 1241 struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
1306 1242
1307 if (video_debug) { 1243 mutex_lock(&core->lock);
1308 if (video_debug > 1) { 1244 cx88_set_tvnorm(core,&tvnorms[i]);
1309 if (_IOC_DIR(cmd) & _IOC_WRITE) 1245 mutex_unlock(&core->lock);
1310 v4l_printk_ioctl_arg("cx88(w)",cmd, arg); 1246 return 0;
1311 else if (!_IOC_DIR(cmd) & _IOC_READ) { 1247}
1312 v4l_print_ioctl("cx88", cmd);
1313 }
1314 } else
1315 v4l_print_ioctl(core->name,cmd);
1316
1317 }
1318
1319 switch (cmd) {
1320 /* ---------- tv norms ---------- */
1321 case VIDIOC_ENUMSTD:
1322 {
1323 struct v4l2_standard *e = arg;
1324 unsigned int i;
1325
1326 i = e->index;
1327 if (i >= ARRAY_SIZE(tvnorms))
1328 return -EINVAL;
1329 err = v4l2_video_std_construct(e, tvnorms[e->index].id,
1330 tvnorms[e->index].name);
1331 e->index = i;
1332 if (err < 0)
1333 return err;
1334 return 0;
1335 }
1336 case VIDIOC_G_STD:
1337 {
1338 v4l2_std_id *id = arg;
1339 1248
1340 *id = core->tvnorm->id; 1249/* only one input in this sample driver */
1341 return 0; 1250static int vidioc_enum_input (struct file *file, void *priv,
1342 } 1251 struct v4l2_input *i)
1343 case VIDIOC_S_STD: 1252{
1344 { 1253 struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
1345 v4l2_std_id *id = arg; 1254
1346 unsigned int i; 1255 static const char *iname[] = {
1256 [ CX88_VMUX_COMPOSITE1 ] = "Composite1",
1257 [ CX88_VMUX_COMPOSITE2 ] = "Composite2",
1258 [ CX88_VMUX_COMPOSITE3 ] = "Composite3",
1259 [ CX88_VMUX_COMPOSITE4 ] = "Composite4",
1260 [ CX88_VMUX_SVIDEO ] = "S-Video",
1261 [ CX88_VMUX_TELEVISION ] = "Television",
1262 [ CX88_VMUX_CABLE ] = "Cable TV",
1263 [ CX88_VMUX_DVB ] = "DVB",
1264 [ CX88_VMUX_DEBUG ] = "for debug only",
1265 };
1266 unsigned int n;
1347 1267
1348 for(i = 0; i < ARRAY_SIZE(tvnorms); i++) 1268 n = i->index;
1349 if (*id & tvnorms[i].id) 1269 if (n >= 4)
1350 break; 1270 return -EINVAL;
1351 if (i == ARRAY_SIZE(tvnorms)) 1271 if (0 == INPUT(n)->type)
1352 return -EINVAL; 1272 return -EINVAL;
1273 memset(i,0,sizeof(*i));
1274 i->index = n;
1275 i->type = V4L2_INPUT_TYPE_CAMERA;
1276 strcpy(i->name,iname[INPUT(n)->type]);
1277 if ((CX88_VMUX_TELEVISION == INPUT(n)->type) ||
1278 (CX88_VMUX_CABLE == INPUT(n)->type))
1279 i->type = V4L2_INPUT_TYPE_TUNER;
1280 for (n = 0; n < ARRAY_SIZE(tvnorms); n++)
1281 i->std |= tvnorms[n].id;
1282 return 0;
1283}
1353 1284
1354 mutex_lock(&core->lock); 1285static int vidioc_g_input (struct file *file, void *priv, unsigned int *i)
1355 cx88_set_tvnorm(core,&tvnorms[i]); 1286{
1356 mutex_unlock(&core->lock); 1287 struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
1357 return 0;
1358 }
1359 1288
1360 /* ------ input switching ---------- */ 1289 *i = core->input;
1361 case VIDIOC_ENUMINPUT: 1290 return 0;
1362 { 1291}
1363 static const char *iname[] = {
1364 [ CX88_VMUX_COMPOSITE1 ] = "Composite1",
1365 [ CX88_VMUX_COMPOSITE2 ] = "Composite2",
1366 [ CX88_VMUX_COMPOSITE3 ] = "Composite3",
1367 [ CX88_VMUX_COMPOSITE4 ] = "Composite4",
1368 [ CX88_VMUX_SVIDEO ] = "S-Video",
1369 [ CX88_VMUX_TELEVISION ] = "Television",
1370 [ CX88_VMUX_CABLE ] = "Cable TV",
1371 [ CX88_VMUX_DVB ] = "DVB",
1372 [ CX88_VMUX_DEBUG ] = "for debug only",
1373 };
1374 struct v4l2_input *i = arg;
1375 unsigned int n;
1376
1377 n = i->index;
1378 if (n >= 4)
1379 return -EINVAL;
1380 if (0 == INPUT(n)->type)
1381 return -EINVAL;
1382 memset(i,0,sizeof(*i));
1383 i->index = n;
1384 i->type = V4L2_INPUT_TYPE_CAMERA;
1385 strcpy(i->name,iname[INPUT(n)->type]);
1386 if ((CX88_VMUX_TELEVISION == INPUT(n)->type) ||
1387 (CX88_VMUX_CABLE == INPUT(n)->type))
1388 i->type = V4L2_INPUT_TYPE_TUNER;
1389 for (n = 0; n < ARRAY_SIZE(tvnorms); n++)
1390 i->std |= tvnorms[n].id;
1391 return 0;
1392 }
1393 case VIDIOC_G_INPUT:
1394 {
1395 unsigned int *i = arg;
1396 1292
1397 *i = core->input; 1293static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
1398 return 0; 1294{
1399 } 1295 struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
1400 case VIDIOC_S_INPUT:
1401 {
1402 unsigned int *i = arg;
1403 1296
1404 if (*i >= 4) 1297 if (i >= 4)
1405 return -EINVAL; 1298 return -EINVAL;
1406 mutex_lock(&core->lock);
1407 cx88_newstation(core);
1408 video_mux(core,*i);
1409 mutex_unlock(&core->lock);
1410 return 0;
1411 }
1412 1299
1300 mutex_lock(&core->lock);
1301 cx88_newstation(core);
1302 video_mux(core,i);
1303 mutex_unlock(&core->lock);
1304 return 0;
1305}
1413 1306
1414 1307
1415 /* --- controls ---------------------------------------------- */
1416 case VIDIOC_QUERYCTRL:
1417 {
1418 struct v4l2_queryctrl *c = arg;
1419 1308
1420 return cx88_queryctrl(c); 1309static int vidioc_queryctrl (struct file *file, void *priv,
1421 } 1310 struct v4l2_queryctrl *qctrl)
1422 case VIDIOC_G_CTRL: 1311{
1423 return get_control(core,arg); 1312 qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
1424 case VIDIOC_S_CTRL: 1313 if (unlikely(qctrl->id == 0))
1425 return set_control(core,arg); 1314 return -EINVAL;
1315 return cx8800_ctrl_query(qctrl);
1316}
1426 1317
1427 /* --- tuner ioctls ------------------------------------------ */ 1318static int vidioc_s_ctrl (struct file *file, void *priv,
1428 case VIDIOC_G_TUNER: 1319 struct v4l2_control *ctl)
1429 { 1320{
1430 struct v4l2_tuner *t = arg; 1321 struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
1431 u32 reg;
1432
1433 if (UNSET == core->tuner_type)
1434 return -EINVAL;
1435 if (0 != t->index)
1436 return -EINVAL;
1437
1438 memset(t,0,sizeof(*t));
1439 strcpy(t->name, "Television");
1440 t->type = V4L2_TUNER_ANALOG_TV;
1441 t->capability = V4L2_TUNER_CAP_NORM;
1442 t->rangehigh = 0xffffffffUL;
1443
1444 cx88_get_stereo(core ,t);
1445 reg = cx_read(MO_DEVICE_STATUS);
1446 t->signal = (reg & (1<<5)) ? 0xffff : 0x0000;
1447 return 0;
1448 }
1449 case VIDIOC_S_TUNER:
1450 {
1451 struct v4l2_tuner *t = arg;
1452 1322
1453 if (UNSET == core->tuner_type) 1323 return
1454 return -EINVAL; 1324 set_control(core,ctl);
1455 if (0 != t->index) 1325}
1456 return -EINVAL;
1457 cx88_set_stereo(core, t->audmode, 1);
1458 return 0;
1459 }
1460 case VIDIOC_G_FREQUENCY:
1461 {
1462 struct v4l2_frequency *f = arg;
1463 1326
1464 memset(f,0,sizeof(*f)); 1327static int vidioc_g_tuner (struct file *file, void *priv,
1328 struct v4l2_tuner *t)
1329{
1330 struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
1331 u32 reg;
1465 1332
1466 if (UNSET == core->tuner_type) 1333 if (unlikely(UNSET == core->tuner_type))
1467 return -EINVAL; 1334 return -EINVAL;
1468 1335
1469 /* f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; */ 1336 strcpy(t->name, "Television");
1470 f->type = radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; 1337 t->type = V4L2_TUNER_ANALOG_TV;
1471 f->frequency = core->freq; 1338 t->capability = V4L2_TUNER_CAP_NORM;
1339 t->rangehigh = 0xffffffffUL;
1472 1340
1473 cx88_call_i2c_clients(core,VIDIOC_G_FREQUENCY,f); 1341 cx88_get_stereo(core ,t);
1342 reg = cx_read(MO_DEVICE_STATUS);
1343 t->signal = (reg & (1<<5)) ? 0xffff : 0x0000;
1344 return 0;
1345}
1474 1346
1475 return 0; 1347static int vidioc_s_tuner (struct file *file, void *priv,
1476 } 1348 struct v4l2_tuner *t)
1477 case VIDIOC_S_FREQUENCY: 1349{
1478 { 1350 struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
1479 struct v4l2_frequency *f = arg;
1480
1481 if (UNSET == core->tuner_type)
1482 return -EINVAL;
1483 if (f->tuner != 0)
1484 return -EINVAL;
1485 if (0 == radio && f->type != V4L2_TUNER_ANALOG_TV)
1486 return -EINVAL;
1487 if (1 == radio && f->type != V4L2_TUNER_RADIO)
1488 return -EINVAL;
1489 mutex_lock(&core->lock);
1490 core->freq = f->frequency;
1491 cx88_newstation(core);
1492 cx88_call_i2c_clients(core,VIDIOC_S_FREQUENCY,f);
1493
1494 /* When changing channels it is required to reset TVAUDIO */
1495 msleep (10);
1496 cx88_set_tvaudio(core);
1497 1351
1498 mutex_unlock(&core->lock); 1352 if (UNSET == core->tuner_type)
1499 return 0; 1353 return -EINVAL;
1500 } 1354 if (0 != t->index)
1501#ifdef CONFIG_VIDEO_ADV_DEBUG 1355 return -EINVAL;
1502 /* ioctls to allow direct acces to the cx2388x registers */
1503 case VIDIOC_INT_G_REGISTER:
1504 {
1505 struct v4l2_register *reg = arg;
1506 1356
1507 if (reg->i2c_id != 0) 1357 cx88_set_stereo(core, t->audmode, 1);
1508 return -EINVAL; 1358 return 0;
1509 /* cx2388x has a 24-bit register space */ 1359}
1510 reg->val = cx_read(reg->reg&0xffffff);
1511 return 0;
1512 }
1513 case VIDIOC_INT_S_REGISTER:
1514 {
1515 struct v4l2_register *reg = arg;
1516 1360
1517 if (reg->i2c_id != 0) 1361static int vidioc_g_frequency (struct file *file, void *priv,
1518 return -EINVAL; 1362 struct v4l2_frequency *f)
1519 if (!capable(CAP_SYS_ADMIN)) 1363{
1520 return -EPERM; 1364 struct cx8800_fh *fh = priv;
1521 cx_write(reg->reg&0xffffff, reg->val); 1365 struct cx88_core *core = fh->dev->core;
1522 return 0; 1366
1523 } 1367 if (unlikely(UNSET == core->tuner_type))
1524#endif 1368 return -EINVAL;
1369
1370 /* f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; */
1371 f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
1372 f->frequency = core->freq;
1373
1374 cx88_call_i2c_clients(core,VIDIOC_G_FREQUENCY,f);
1525 1375
1526 default:
1527 return v4l_compat_translate_ioctl(inode,file,cmd,arg,
1528 driver_ioctl);
1529 }
1530 return 0; 1376 return 0;
1531} 1377}
1532 1378
1533static int video_ioctl(struct inode *inode, struct file *file, 1379static int vidioc_s_frequency (struct file *file, void *priv,
1534 unsigned int cmd, unsigned long arg) 1380 struct v4l2_frequency *f)
1535{ 1381{
1536 int retval; 1382 struct cx8800_fh *fh = priv;
1383 struct cx88_core *core = fh->dev->core;
1537 1384
1538 retval=video_usercopy(inode, file, cmd, arg, video_do_ioctl); 1385 if (unlikely(UNSET == core->tuner_type))
1386 return -EINVAL;
1387 if (unlikely(f->tuner != 0))
1388 return -EINVAL;
1389 if (unlikely(0 == fh->radio && f->type != V4L2_TUNER_ANALOG_TV))
1390 return -EINVAL;
1391 if (unlikely(1 == fh->radio && f->type != V4L2_TUNER_RADIO))
1392 return -EINVAL;
1393 mutex_lock(&core->lock);
1394 core->freq = f->frequency;
1395 cx88_newstation(core);
1396 cx88_call_i2c_clients(core,VIDIOC_S_FREQUENCY,f);
1539 1397
1540 if (video_debug > 1) { 1398 /* When changing channels it is required to reset TVAUDIO */
1541 if (retval < 0) { 1399 msleep (10);
1542 v4l_print_ioctl("cx88(err)", cmd); 1400 cx88_set_tvaudio(core);
1543 printk(KERN_DEBUG "cx88(err): errcode=%d\n",retval);
1544 } else if (_IOC_DIR(cmd) & _IOC_READ)
1545 v4l_printk_ioctl_arg("cx88(r)",cmd, (void *)arg);
1546 }
1547 1401
1548 return retval; 1402 mutex_unlock(&core->lock);
1403 return 0;
1549} 1404}
1550 1405
1406
1407/* ----------------------------------------------------------- */
1408/* RADIO ESPECIFIC IOCTLS */
1551/* ----------------------------------------------------------- */ 1409/* ----------------------------------------------------------- */
1552 1410
1553static int radio_do_ioctl(struct inode *inode, struct file *file, 1411static int radio_querycap (struct file *file, void *priv,
1554 unsigned int cmd, void *arg) 1412 struct v4l2_capability *cap)
1555{ 1413{
1556 struct cx8800_fh *fh = file->private_data; 1414 struct cx8800_dev *dev = ((struct cx8800_fh *)priv)->dev;
1557 struct cx8800_dev *dev = fh->dev;
1558 struct cx88_core *core = dev->core; 1415 struct cx88_core *core = dev->core;
1559 1416
1560 if (video_debug > 1) 1417 strcpy(cap->driver, "cx8800");
1561 v4l_print_ioctl(core->name,cmd); 1418 strlcpy(cap->card, cx88_boards[core->board].name,
1562 1419 sizeof(cap->card));
1563 switch (cmd) { 1420 sprintf(cap->bus_info,"PCI:%s", pci_name(dev->pci));
1564 case VIDIOC_QUERYCAP: 1421 cap->version = CX88_VERSION_CODE;
1565 { 1422 cap->capabilities = V4L2_CAP_TUNER;
1566 struct v4l2_capability *cap = arg; 1423 return 0;
1567 1424}
1568 memset(cap,0,sizeof(*cap));
1569 strcpy(cap->driver, "cx8800");
1570 strlcpy(cap->card, cx88_boards[core->board].name,
1571 sizeof(cap->card));
1572 sprintf(cap->bus_info,"PCI:%s", pci_name(dev->pci));
1573 cap->version = CX88_VERSION_CODE;
1574 cap->capabilities = V4L2_CAP_TUNER;
1575 return 0;
1576 }
1577 case VIDIOC_G_TUNER:
1578 {
1579 struct v4l2_tuner *t = arg;
1580 1425
1581 if (t->index > 0) 1426static int radio_g_tuner (struct file *file, void *priv,
1582 return -EINVAL; 1427 struct v4l2_tuner *t)
1428{
1429 struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
1583 1430
1584 memset(t,0,sizeof(*t)); 1431 if (unlikely(t->index > 0))
1585 strcpy(t->name, "Radio"); 1432 return -EINVAL;
1586 t->type = V4L2_TUNER_RADIO;
1587 1433
1588 cx88_call_i2c_clients(core,VIDIOC_G_TUNER,t); 1434 strcpy(t->name, "Radio");
1589 return 0; 1435 t->type = V4L2_TUNER_RADIO;
1590 }
1591 case VIDIOC_ENUMINPUT:
1592 {
1593 struct v4l2_input *i = arg;
1594 1436
1595 if (i->index != 0) 1437 cx88_call_i2c_clients(core,VIDIOC_G_TUNER,t);
1596 return -EINVAL; 1438 return 0;
1597 strcpy(i->name,"Radio"); 1439}
1598 i->type = V4L2_INPUT_TYPE_TUNER;
1599 return 0;
1600 }
1601 case VIDIOC_G_INPUT:
1602 {
1603 int *i = arg;
1604 *i = 0;
1605 return 0;
1606 }
1607 case VIDIOC_G_AUDIO:
1608 {
1609 struct v4l2_audio *a = arg;
1610 1440
1611 memset(a,0,sizeof(*a)); 1441static int radio_enum_input (struct file *file, void *priv,
1612 strcpy(a->name,"Radio"); 1442 struct v4l2_input *i)
1613 return 0; 1443{
1614 } 1444 if (i->index != 0)
1615 case VIDIOC_G_STD: 1445 return -EINVAL;
1616 { 1446 strcpy(i->name,"Radio");
1617 v4l2_std_id *id = arg; 1447 i->type = V4L2_INPUT_TYPE_TUNER;
1618 *id = 0;
1619 return 0;
1620 }
1621#ifdef CONFIG_VIDEO_V4L1_COMPAT
1622 case VIDIOCSTUNER:
1623 {
1624 struct video_tuner *v = arg;
1625 1448
1626 if (v->tuner) /* Only tuner 0 */ 1449 return 0;
1627 return -EINVAL; 1450}
1628 1451
1629 cx88_call_i2c_clients(core,VIDIOCSTUNER,v); 1452static int radio_g_audio (struct file *file, void *priv, struct v4l2_audio *a)
1630 return 0; 1453{
1631 } 1454 if (unlikely(a->index))
1632#endif 1455 return -EINVAL;
1633 case VIDIOC_S_TUNER:
1634 {
1635 struct v4l2_tuner *t = arg;
1636 1456
1637 if (0 != t->index) 1457 memset(a,0,sizeof(*a));
1638 return -EINVAL; 1458 strcpy(a->name,"Radio");
1459 return 0;
1460}
1639 1461
1640 cx88_call_i2c_clients(core,VIDIOC_S_TUNER,t); 1462/* FIXME: Should add a standard for radio */
1641 1463
1642 return 0; 1464static int radio_s_tuner (struct file *file, void *priv,
1643 } 1465 struct v4l2_tuner *t)
1466{
1467 struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
1644 1468
1645 case VIDIOC_S_AUDIO: 1469 if (0 != t->index)
1646 case VIDIOC_S_INPUT: 1470 return -EINVAL;
1647 case VIDIOC_S_STD:
1648 return 0;
1649 1471
1650 case VIDIOC_QUERYCTRL: 1472 cx88_call_i2c_clients(core,VIDIOC_S_TUNER,t);
1651 {
1652 struct v4l2_queryctrl *c = arg;
1653 int i;
1654
1655 if (c->id < V4L2_CID_BASE ||
1656 c->id >= V4L2_CID_LASTP1)
1657 return -EINVAL;
1658 if (c->id == V4L2_CID_AUDIO_MUTE) {
1659 for (i = 0; i < CX8800_CTLS; i++)
1660 if (cx8800_ctls[i].v.id == c->id)
1661 break;
1662 *c = cx8800_ctls[i].v;
1663 } else
1664 *c = no_ctl;
1665 return 0;
1666 }
1667 1473
1474 return 0;
1475}
1668 1476
1669 case VIDIOC_G_CTRL: 1477static int radio_s_audio (struct file *file, void *fh,
1670 case VIDIOC_S_CTRL: 1478 struct v4l2_audio *a)
1671 case VIDIOC_G_FREQUENCY: 1479{
1672 case VIDIOC_S_FREQUENCY: 1480 return 0;
1673 return video_do_ioctl(inode,file,cmd,arg); 1481}
1674 1482
1675 default: 1483static int radio_s_input (struct file *file, void *fh, unsigned int i)
1676 return v4l_compat_translate_ioctl(inode,file,cmd,arg, 1484{
1677 radio_do_ioctl);
1678 }
1679 return 0; 1485 return 0;
1680}; 1486}
1681 1487
1682static int radio_ioctl(struct inode *inode, struct file *file, 1488static int radio_queryctrl (struct file *file, void *priv,
1683 unsigned int cmd, unsigned long arg) 1489 struct v4l2_queryctrl *c)
1684{ 1490{
1685 return video_usercopy(inode, file, cmd, arg, radio_do_ioctl); 1491 int i;
1686}; 1492
1493 if (c->id < V4L2_CID_BASE ||
1494 c->id >= V4L2_CID_LASTP1)
1495 return -EINVAL;
1496 if (c->id == V4L2_CID_AUDIO_MUTE) {
1497 for (i = 0; i < CX8800_CTLS; i++)
1498 if (cx8800_ctls[i].v.id == c->id)
1499 break;
1500 *c = cx8800_ctls[i].v;
1501 } else
1502 *c = no_ctl;
1503 return 0;
1504}
1687 1505
1688/* ----------------------------------------------------------- */ 1506/* ----------------------------------------------------------- */
1689 1507
@@ -1816,27 +1634,48 @@ static const struct file_operations video_fops =
1816 .read = video_read, 1634 .read = video_read,
1817 .poll = video_poll, 1635 .poll = video_poll,
1818 .mmap = video_mmap, 1636 .mmap = video_mmap,
1819 .ioctl = video_ioctl, 1637 .ioctl = video_ioctl2,
1820 .compat_ioctl = v4l_compat_ioctl32, 1638 .compat_ioctl = v4l_compat_ioctl32,
1821 .llseek = no_llseek, 1639 .llseek = no_llseek,
1822}; 1640};
1823 1641
1642static struct video_device cx8800_vbi_template;
1824static struct video_device cx8800_video_template = 1643static struct video_device cx8800_video_template =
1825{ 1644{
1826 .name = "cx8800-video", 1645 .name = "cx8800-video",
1827 .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_SCALES, 1646 .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_SCALES,
1828 .hardware = 0, 1647 .fops = &video_fops,
1829 .fops = &video_fops, 1648 .minor = -1,
1830 .minor = -1, 1649 .vidioc_querycap = vidioc_querycap,
1831}; 1650 .vidioc_enum_fmt_cap = vidioc_enum_fmt_cap,
1832 1651 .vidioc_g_fmt_cap = vidioc_g_fmt_cap,
1833static struct video_device cx8800_vbi_template = 1652 .vidioc_try_fmt_cap = vidioc_try_fmt_cap,
1834{ 1653 .vidioc_s_fmt_cap = vidioc_s_fmt_cap,
1835 .name = "cx8800-vbi", 1654 .vidioc_g_fmt_vbi = cx8800_vbi_fmt,
1836 .type = VID_TYPE_TELETEXT|VID_TYPE_TUNER, 1655 .vidioc_try_fmt_vbi = cx8800_vbi_fmt,
1837 .hardware = 0, 1656 .vidioc_s_fmt_vbi = cx8800_vbi_fmt,
1838 .fops = &video_fops, 1657 .vidioc_reqbufs = vidioc_reqbufs,
1839 .minor = -1, 1658 .vidioc_querybuf = vidioc_querybuf,
1659 .vidioc_qbuf = vidioc_qbuf,
1660 .vidioc_dqbuf = vidioc_dqbuf,
1661 .vidioc_s_std = vidioc_s_std,
1662 .vidioc_enum_input = vidioc_enum_input,
1663 .vidioc_g_input = vidioc_g_input,
1664 .vidioc_s_input = vidioc_s_input,
1665 .vidioc_queryctrl = vidioc_queryctrl,
1666 .vidioc_g_ctrl = vidioc_g_ctrl,
1667 .vidioc_s_ctrl = vidioc_s_ctrl,
1668 .vidioc_streamon = vidioc_streamon,
1669 .vidioc_streamoff = vidioc_streamoff,
1670#ifdef CONFIG_VIDEO_V4L1_COMPAT
1671 .vidiocgmbuf = vidiocgmbuf,
1672#endif
1673 .vidioc_g_tuner = vidioc_g_tuner,
1674 .vidioc_s_tuner = vidioc_s_tuner,
1675 .vidioc_g_frequency = vidioc_g_frequency,
1676 .vidioc_s_frequency = vidioc_s_frequency,
1677 .tvnorms = tvnorms,
1678 .tvnormsize = ARRAY_SIZE(tvnorms),
1840}; 1679};
1841 1680
1842static const struct file_operations radio_fops = 1681static const struct file_operations radio_fops =
@@ -1844,18 +1683,32 @@ static const struct file_operations radio_fops =
1844 .owner = THIS_MODULE, 1683 .owner = THIS_MODULE,
1845 .open = video_open, 1684 .open = video_open,
1846 .release = video_release, 1685 .release = video_release,
1847 .ioctl = radio_ioctl, 1686 .ioctl = video_ioctl2,
1848 .compat_ioctl = v4l_compat_ioctl32, 1687 .compat_ioctl = v4l_compat_ioctl32,
1849 .llseek = no_llseek, 1688 .llseek = no_llseek,
1850}; 1689};
1851 1690
1852static struct video_device cx8800_radio_template = 1691static struct video_device cx8800_radio_template =
1853{ 1692{
1854 .name = "cx8800-radio", 1693 .name = "cx8800-radio",
1855 .type = VID_TYPE_TUNER, 1694 .type = VID_TYPE_TUNER,
1856 .hardware = 0, 1695 .hardware = 0,
1857 .fops = &radio_fops, 1696 .fops = &radio_fops,
1858 .minor = -1, 1697 .minor = -1,
1698 .vidioc_querycap = radio_querycap,
1699 .vidioc_g_tuner = radio_g_tuner,
1700 .vidioc_enum_input = radio_enum_input,
1701 .vidioc_g_audio = radio_g_audio,
1702 .vidioc_s_tuner = radio_s_tuner,
1703 .vidioc_s_audio = radio_s_audio,
1704 .vidioc_s_input = radio_s_input,
1705 .vidioc_queryctrl = radio_queryctrl,
1706 .vidioc_g_ctrl = vidioc_g_ctrl,
1707 .vidioc_s_ctrl = vidioc_s_ctrl,
1708 .vidioc_g_frequency = vidioc_g_frequency,
1709 .vidioc_s_frequency = vidioc_s_frequency,
1710 .tvnorms = radionorms,
1711 .tvnormsize = ARRAY_SIZE(radionorms),
1859}; 1712};
1860 1713
1861/* ----------------------------------------------------------- */ 1714/* ----------------------------------------------------------- */
@@ -1890,6 +1743,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
1890{ 1743{
1891 struct cx8800_dev *dev; 1744 struct cx8800_dev *dev;
1892 struct cx88_core *core; 1745 struct cx88_core *core;
1746
1893 int err; 1747 int err;
1894 1748
1895 dev = kzalloc(sizeof(*dev),GFP_KERNEL); 1749 dev = kzalloc(sizeof(*dev),GFP_KERNEL);
@@ -1924,6 +1778,12 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
1924 goto fail_core; 1778 goto fail_core;
1925 } 1779 }
1926 1780
1781 /* Initialize VBI template */
1782 memcpy( &cx8800_vbi_template, &cx8800_video_template,
1783 sizeof(cx8800_vbi_template) );
1784 strcpy(cx8800_vbi_template.name,"cx8800-vbi");
1785 cx8800_vbi_template.type = VID_TYPE_TELETEXT|VID_TYPE_TUNER;
1786
1927 /* initialize driver struct */ 1787 /* initialize driver struct */
1928 spin_lock_init(&dev->slock); 1788 spin_lock_init(&dev->slock);
1929 core->tvnorm = tvnorms; 1789 core->tvnorm = tvnorms;
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
index a9575ad8ca2..97177c0d022 100644
--- a/drivers/media/video/cx88/cx88.h
+++ b/drivers/media/video/cx88/cx88.h
@@ -82,20 +82,13 @@ enum cx8802_board_access {
82/* ----------------------------------------------------------- */ 82/* ----------------------------------------------------------- */
83/* tv norms */ 83/* tv norms */
84 84
85struct cx88_tvnorm { 85static unsigned int inline norm_maxw(struct v4l2_tvnorm *norm)
86 char *name;
87 v4l2_std_id id;
88 u32 cxiformat;
89 u32 cxoformat;
90};
91
92static unsigned int inline norm_maxw(struct cx88_tvnorm *norm)
93{ 86{
94 return (norm->id & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 720 : 768; 87 return (norm->id & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 720 : 768;
95} 88}
96 89
97 90
98static unsigned int inline norm_maxh(struct cx88_tvnorm *norm) 91static unsigned int inline norm_maxh(struct v4l2_tvnorm *norm)
99{ 92{
100 return (norm->id & V4L2_STD_625_50) ? 576 : 480; 93 return (norm->id & V4L2_STD_625_50) ? 576 : 480;
101} 94}
@@ -319,7 +312,7 @@ struct cx88_core {
319 312
320 /* state info */ 313 /* state info */
321 struct task_struct *kthread; 314 struct task_struct *kthread;
322 struct cx88_tvnorm *tvnorm; 315 struct v4l2_tvnorm *tvnorm;
323 u32 tvaudio; 316 u32 tvaudio;
324 u32 audiomode_manual; 317 u32 audiomode_manual;
325 u32 audiomode_current; 318 u32 audiomode_current;
@@ -536,7 +529,7 @@ extern void cx88_sram_channel_dump(struct cx88_core *core,
536 529
537extern int cx88_set_scale(struct cx88_core *core, unsigned int width, 530extern int cx88_set_scale(struct cx88_core *core, unsigned int width,
538 unsigned int height, enum v4l2_field field); 531 unsigned int height, enum v4l2_field field);
539extern int cx88_set_tvnorm(struct cx88_core *core, struct cx88_tvnorm *norm); 532extern int cx88_set_tvnorm(struct cx88_core *core, struct v4l2_tvnorm *norm);
540 533
541extern struct video_device *cx88_vdev_init(struct cx88_core *core, 534extern struct video_device *cx88_vdev_init(struct cx88_core *core,
542 struct pci_dev *pci, 535 struct pci_dev *pci,
@@ -553,7 +546,10 @@ extern int cx88_stop_audio_dma(struct cx88_core *core);
553/* ----------------------------------------------------------- */ 546/* ----------------------------------------------------------- */
554/* cx88-vbi.c */ 547/* cx88-vbi.c */
555 548
556void cx8800_vbi_fmt(struct cx8800_dev *dev, struct v4l2_format *f); 549/* Can be used as g_vbi_fmt, try_vbi_fmt and s_vbi_fmt */
550int cx8800_vbi_fmt (struct file *file, void *priv,
551 struct v4l2_format *f);
552
557/* 553/*
558int cx8800_start_vbi_dma(struct cx8800_dev *dev, 554int cx8800_start_vbi_dma(struct cx8800_dev *dev,
559 struct cx88_dmaqueue *q, 555 struct cx88_dmaqueue *q,