aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/usb
diff options
context:
space:
mode:
authorLubomir Rintel <lkundrak@v3.sk>2013-07-12 04:03:03 -0400
committerMauro Carvalho Chehab <m.chehab@samsung.com>2013-07-26 12:29:29 -0400
commit2206112b157d0ba736bead38eaf04b4ade24ece7 (patch)
tree302945649d581c9096c545af6340474fcbee0b03 /drivers/media/usb
parentac22521cb2dc07e0b2193868c647dee5d737f85a (diff)
[media] usbtv: Add S-Video input support
Alongside already existing Composite input. Signed-off-by: Lubomir Rintel <lkundrak@v3.sk> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers/media/usb')
-rw-r--r--drivers/media/usb/usbtv/usbtv.c99
1 files changed, 82 insertions, 17 deletions
diff --git a/drivers/media/usb/usbtv/usbtv.c b/drivers/media/usb/usbtv/usbtv.c
index bf43f874685e..b164e542aec8 100644
--- a/drivers/media/usb/usbtv/usbtv.c
+++ b/drivers/media/usb/usbtv/usbtv.c
@@ -90,17 +90,78 @@ struct usbtv {
90 * out when a new one begins. */ 90 * out when a new one begins. */
91 u32 frame_id; 91 u32 frame_id;
92 92
93 enum {
94 USBTV_COMPOSITE_INPUT,
95 USBTV_SVIDEO_INPUT,
96 } input;
93 int iso_size; 97 int iso_size;
94 unsigned int sequence; 98 unsigned int sequence;
95 struct urb *isoc_urbs[USBTV_ISOC_TRANSFERS]; 99 struct urb *isoc_urbs[USBTV_ISOC_TRANSFERS];
96}; 100};
97 101
98static int usbtv_setup_capture(struct usbtv *usbtv) 102static int usbtv_set_regs(struct usbtv *usbtv, const u16 regs[][2], int size)
99{ 103{
100 int ret; 104 int ret;
101 int pipe = usb_rcvctrlpipe(usbtv->udev, 0); 105 int pipe = usb_rcvctrlpipe(usbtv->udev, 0);
102 int i; 106 int i;
103 static const u16 protoregs[][2] = { 107
108 for (i = 0; i < size; i++) {
109 u16 index = regs[i][0];
110 u16 value = regs[i][1];
111
112 ret = usb_control_msg(usbtv->udev, pipe, USBTV_REQUEST_REG,
113 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
114 value, index, NULL, 0, 0);
115 if (ret < 0)
116 return ret;
117 }
118
119 return 0;
120}
121
122static int usbtv_select_input(struct usbtv *usbtv, int input)
123{
124 int ret;
125
126 static const u16 composite[][2] = {
127 { USBTV_BASE + 0x0105, 0x0060 },
128 { USBTV_BASE + 0x011f, 0x00f2 },
129 { USBTV_BASE + 0x0127, 0x0060 },
130 { USBTV_BASE + 0x00ae, 0x0010 },
131 { USBTV_BASE + 0x0284, 0x00aa },
132 { USBTV_BASE + 0x0239, 0x0060 },
133 };
134
135 static const u16 svideo[][2] = {
136 { USBTV_BASE + 0x0105, 0x0010 },
137 { USBTV_BASE + 0x011f, 0x00ff },
138 { USBTV_BASE + 0x0127, 0x0060 },
139 { USBTV_BASE + 0x00ae, 0x0030 },
140 { USBTV_BASE + 0x0284, 0x0088 },
141 { USBTV_BASE + 0x0239, 0x0060 },
142 };
143
144 switch (input) {
145 case USBTV_COMPOSITE_INPUT:
146 ret = usbtv_set_regs(usbtv, composite, ARRAY_SIZE(composite));
147 break;
148 case USBTV_SVIDEO_INPUT:
149 ret = usbtv_set_regs(usbtv, svideo, ARRAY_SIZE(svideo));
150 break;
151 default:
152 ret = -EINVAL;
153 }
154
155 if (!ret)
156 usbtv->input = input;
157
158 return ret;
159}
160
161static int usbtv_setup_capture(struct usbtv *usbtv)
162{
163 int ret;
164 static const u16 setup[][2] = {
104 /* These seem to enable the device. */ 165 /* These seem to enable the device. */
105 { USBTV_BASE + 0x0008, 0x0001 }, 166 { USBTV_BASE + 0x0008, 0x0001 },
106 { USBTV_BASE + 0x01d0, 0x00ff }, 167 { USBTV_BASE + 0x01d0, 0x00ff },
@@ -188,16 +249,13 @@ static int usbtv_setup_capture(struct usbtv *usbtv)
188 { USBTV_BASE + 0x024f, 0x0002 }, 249 { USBTV_BASE + 0x024f, 0x0002 },
189 }; 250 };
190 251
191 for (i = 0; i < ARRAY_SIZE(protoregs); i++) { 252 ret = usbtv_set_regs(usbtv, setup, ARRAY_SIZE(setup));
192 u16 index = protoregs[i][0]; 253 if (ret)
193 u16 value = protoregs[i][1]; 254 return ret;
194 255
195 ret = usb_control_msg(usbtv->udev, pipe, USBTV_REQUEST_REG, 256 ret = usbtv_select_input(usbtv, usbtv->input);
196 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 257 if (ret)
197 value, index, NULL, 0, 0); 258 return ret;
198 if (ret < 0)
199 return ret;
200 }
201 259
202 return 0; 260 return 0;
203} 261}
@@ -418,10 +476,17 @@ static int usbtv_querycap(struct file *file, void *priv,
418static int usbtv_enum_input(struct file *file, void *priv, 476static int usbtv_enum_input(struct file *file, void *priv,
419 struct v4l2_input *i) 477 struct v4l2_input *i)
420{ 478{
421 if (i->index > 0) 479 switch (i->index) {
480 case USBTV_COMPOSITE_INPUT:
481 strlcpy(i->name, "Composite", sizeof(i->name));
482 break;
483 case USBTV_SVIDEO_INPUT:
484 strlcpy(i->name, "S-Video", sizeof(i->name));
485 break;
486 default:
422 return -EINVAL; 487 return -EINVAL;
488 }
423 489
424 strlcpy(i->name, "Composite", sizeof(i->name));
425 i->type = V4L2_INPUT_TYPE_CAMERA; 490 i->type = V4L2_INPUT_TYPE_CAMERA;
426 i->std = V4L2_STD_525_60; 491 i->std = V4L2_STD_525_60;
427 return 0; 492 return 0;
@@ -461,15 +526,15 @@ static int usbtv_g_std(struct file *file, void *priv, v4l2_std_id *norm)
461 526
462static int usbtv_g_input(struct file *file, void *priv, unsigned int *i) 527static int usbtv_g_input(struct file *file, void *priv, unsigned int *i)
463{ 528{
464 *i = 0; 529 struct usbtv *usbtv = video_drvdata(file);
530 *i = usbtv->input;
465 return 0; 531 return 0;
466} 532}
467 533
468static int usbtv_s_input(struct file *file, void *priv, unsigned int i) 534static int usbtv_s_input(struct file *file, void *priv, unsigned int i)
469{ 535{
470 if (i > 0) 536 struct usbtv *usbtv = video_drvdata(file);
471 return -EINVAL; 537 return usbtv_select_input(usbtv, i);
472 return 0;
473} 538}
474 539
475static int usbtv_s_std(struct file *file, void *priv, v4l2_std_id norm) 540static int usbtv_s_std(struct file *file, void *priv, v4l2_std_id norm)