diff options
author | Lubomir Rintel <lkundrak@v3.sk> | 2013-07-12 04:03:03 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2013-07-26 12:29:29 -0400 |
commit | 2206112b157d0ba736bead38eaf04b4ade24ece7 (patch) | |
tree | 302945649d581c9096c545af6340474fcbee0b03 /drivers/media/usb | |
parent | ac22521cb2dc07e0b2193868c647dee5d737f85a (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.c | 99 |
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 | ||
98 | static int usbtv_setup_capture(struct usbtv *usbtv) | 102 | static 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 | |||
122 | static 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 | |||
161 | static 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, | |||
418 | static int usbtv_enum_input(struct file *file, void *priv, | 476 | static 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 | ||
462 | static int usbtv_g_input(struct file *file, void *priv, unsigned int *i) | 527 | static 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 | ||
468 | static int usbtv_s_input(struct file *file, void *priv, unsigned int i) | 534 | static 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 | ||
475 | static int usbtv_s_std(struct file *file, void *priv, v4l2_std_id norm) | 540 | static int usbtv_s_std(struct file *file, void *priv, v4l2_std_id norm) |