Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux...
[deliverable/linux.git] / drivers / staging / easycap / easycap_low.c
CommitLineData
702422bd
T
1/*****************************************************************************
2* *
3* *
4* easycap_low.c *
5* *
6* *
7*****************************************************************************/
8/*
9 *
10 * Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org>
11 *
12 *
13 * This is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * The software is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this software; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 *
27*/
28/*****************************************************************************/
29/*
30 * ACKNOWLEGEMENTS AND REFERENCES
31 * ------------------------------
32 * This driver makes use of register information contained in the Syntek
33 * Semicon DC-1125 driver hosted at
34 * http://sourceforge.net/projects/syntekdriver/.
35 * Particularly useful has been a patch to the latter driver provided by
36 * Ivor Hewitt in January 2009. The NTSC implementation is taken from the
37 * work of Ben Trask.
38*/
39/****************************************************************************/
40
41#include "easycap_debug.h"
42#include "easycap.h"
43
44/*--------------------------------------------------------------------------*/
45const struct stk1160config { int reg; int set; } stk1160config[256] = {
46 {0x000, 0x0098},
47 {0x002, 0x0093},
48
49 {0x001, 0x0003},
50 {0x003, 0x0080},
51 {0x00D, 0x0000},
52 {0x00F, 0x0002},
53 {0x018, 0x0010},
54 {0x019, 0x0000},
55 {0x01A, 0x0014},
56 {0x01B, 0x000E},
57 {0x01C, 0x0046},
58
59 {0x100, 0x0033},
60 {0x103, 0x0000},
61 {0x104, 0x0000},
62 {0x105, 0x0000},
63 {0x106, 0x0000},
64
65#if defined(PREFER_NTSC)
66
67#undef OLDMARGIN
68#if defined(OLDMARGIN)
69 {0x110, 0x0008},
70#else
71 {0x110, 0x0014},
72#endif /*OLDMARGIN*/
73
74 {0x111, 0x0000},
75 {0x112, 0x0003},
76 {0x113, 0x0000},
77
78#if defined(OLDMARGIN)
79 {0x114, 0x0508},
80#else
81 {0x114, 0x0514},
82#endif /*OLDMARGIN*/
83
84 {0x115, 0x0005},
85 {0x116, 0x00F3},
86 {0x117, 0x0000},
87
88#else /* ! PREFER_NTSC*/
89
90#if defined(OLDMARGIN)
91 {0x110, 0x0008},
92#else
93 {0x110, 0x0014},
94#endif /*OLDMARGIN*/
95
96 {0x111, 0x0000},
97 {0x112, 0x0020},
98 {0x113, 0x0000},
99
100#if defined(OLDMARGIN)
101 {0x114, 0x0508},
102#else
103 {0x114, 0x0514},
104#endif /*OLDMARGIN*/
105
106 {0x115, 0x0005},
107 {0x116, 0x0110},
108 {0x117, 0x0001},
109
110#endif /* ! PREFER_NTSC*/
111
112 {0x202, 0x000F},
113 {0x203, 0x004A},
114 {0x2FF, 0x0000},
115/*---------------------------------------------------------------------------*/
116 {0xFFF, 0xFFFF}
117 };
118/*--------------------------------------------------------------------------*/
119const struct saa7113config { int reg; int set; } saa7113config[256] = {
120 {0x01, 0x08},
121 {0x02, 0x80},
122 {0x03, 0x33},
123 {0x04, 0x00},
124 {0x05, 0x00},
125 {0x06, 0xE9},
126 {0x07, 0x0D},
127#if defined(PREFER_NTSC)
128 {0x08, 0x78},
129#else
130 {0x08, 0x38},
131#endif /* ! PREFER_NTSC*/
132 {0x09, 0x00},
133 {0x0A, SAA_0A_DEFAULT},
134 {0x0B, SAA_0B_DEFAULT},
135 {0x0C, SAA_0C_DEFAULT},
136 {0x0D, SAA_0D_DEFAULT},
137 {0x0E, 0x01},
138 {0x0F, 0x36},
139 {0x10, 0x00},
140 {0x11, 0x0C},
141 {0x12, 0xE7},
142 {0x13, 0x00},
143 {0x15, 0x00},
144 {0x16, 0x00},
145#if defined(PREFER_NTSC)
146 {0x40, 0x82},
147#else
148 {0x40, 0x02},
149#endif /* ! PREFER_NTSC*/
150 {0x41, 0xFF},
151 {0x42, 0xFF},
152 {0x43, 0xFF},
153 {0x44, 0xFF},
154 {0x45, 0xFF},
155 {0x46, 0xFF},
156 {0x47, 0xFF},
157 {0x48, 0xFF},
158 {0x49, 0xFF},
159 {0x4A, 0xFF},
160 {0x4B, 0xFF},
161 {0x4C, 0xFF},
162 {0x4D, 0xFF},
163 {0x4E, 0xFF},
164 {0x4F, 0xFF},
165 {0x50, 0xFF},
166 {0x51, 0xFF},
167 {0x52, 0xFF},
168 {0x53, 0xFF},
169 {0x54, 0xFF},
170 {0x55, 0xFF},
171 {0x56, 0xFF},
172 {0x57, 0xFF},
173 {0x58, 0x40},
174 {0x59, 0x54},
175#if defined(PREFER_NTSC)
176 {0x5A, 0x0A},
177#else
178 {0x5A, 0x07},
179#endif /* ! PREFER_NTSC*/
180 {0x5B, 0x83},
181 {0xFF, 0xFF}
182 };
183/*--------------------------------------------------------------------------*/
184
185/****************************************************************************/
186int
187confirm_resolution(struct usb_device *p)
188{
189__u8 get0, get1, get2, get3, get4, get5, get6, get7;
190GET(p, 0x0110, &get0);
191GET(p, 0x0111, &get1);
192GET(p, 0x0112, &get2);
193GET(p, 0x0113, &get3);
194GET(p, 0x0114, &get4);
195GET(p, 0x0115, &get5);
196GET(p, 0x0116, &get6);
197GET(p, 0x0117, &get7);
198JOT(8, "0x%03X, 0x%03X, " \
199 "0x%03X, 0x%03X, " \
200 "0x%03X, 0x%03X, " \
201 "0x%03X, 0x%03X\n", \
202 get0, get1, get2, get3, get4, get5, get6, get7);
203JOT(8, "....cf PAL_720x526: " \
204 "0x%03X, 0x%03X, " \
205 "0x%03X, 0x%03X, " \
206 "0x%03X, 0x%03X, " \
207 "0x%03X, 0x%03X\n", \
208 0x000, 0x000, 0x001, 0x000, 0x5A0, 0x005, 0x121, 0x001);
209JOT(8, "....cf PAL_704x526: " \
210 "0x%03X, 0x%03X, " \
211 "0x%03X, 0x%03X, " \
212 "0x%03X, 0x%03X, " \
213 "0x%03X, 0x%03X\n", \
214 0x004, 0x000, 0x001, 0x000, 0x584, 0x005, 0x121, 0x001);
215JOT(8, "....cf VGA_640x480: " \
216 "0x%03X, 0x%03X, " \
217 "0x%03X, 0x%03X, " \
218 "0x%03X, 0x%03X, " \
219 "0x%03X, 0x%03X\n", \
220 0x008, 0x000, 0x020, 0x000, 0x508, 0x005, 0x110, 0x001);
221return 0;
222}
223/****************************************************************************/
224int
225confirm_stream(struct usb_device *p)
226{
227__u16 get2;
228__u8 igot;
229
230GET(p, 0x0100, &igot); get2 = 0x80 & igot;
231if (0x80 == get2)
232 JOT(8, "confirm_stream: OK\n");
233else
234 JOT(8, "confirm_stream: STUCK\n");
235return 0;
236}
237/****************************************************************************/
238int
239setup_stk(struct usb_device *p)
240{
241int i0;
242
243i0 = 0;
244while (0xFFF != stk1160config[i0].reg) {
245 SET(p, stk1160config[i0].reg, stk1160config[i0].set);
246 i0++;
247 }
248
249write_300(p);
250
251return 0;
252}
253/****************************************************************************/
254int
255setup_saa(struct usb_device *p)
256{
257int i0, ir;
258
259
260set2to78(p);
261
262
263i0 = 0;
264while (0xFF != saa7113config[i0].reg) {
265 ir = write_saa(p, saa7113config[i0].reg, saa7113config[i0].set);
266 i0++;
267 }
268return 0;
269}
270/****************************************************************************/
271int
272write_000(struct usb_device *p, __u16 set2, __u16 set0)
273{
274__u8 igot0, igot2;
275
276GET(p, 0x0002, &igot2);
277GET(p, 0x0000, &igot0);
278SET(p, 0x0002, set2);
279SET(p, 0x0000, set0);
280return 0;
281}
282/****************************************************************************/
283int
284write_saa(struct usb_device *p, __u16 reg0, __u16 set0)
285{
286SET(p, 0x200, 0x00);
287SET(p, 0x204, reg0);
288SET(p, 0x205, set0);
289SET(p, 0x200, 0x01);
290return wait_i2c(p);
291}
292/****************************************************************************/
293/*--------------------------------------------------------------------------*/
294/*
295 * REGISTER 500: SETTING VALUE TO 0x008B READS FROM VT1612A (?)
296 * REGISTER 500: SETTING VALUE TO 0x008C WRITES TO VT1612A
297 * REGISTER 502: LEAST SIGNIFICANT BYTE OF VALUE TO SET
298 * REGISTER 503: MOST SIGNIFICANT BYTE OF VALUE TO SET
299 * REGISTER 504: TARGET ADDRESS ON VT1612A
300 */
301/*--------------------------------------------------------------------------*/
302int
303write_vt(struct usb_device *p, __u16 reg0, __u16 set0)
304{
305__u8 igot;
306__u16 got502, got503;
307__u16 set502, set503;
308
309SET(p, 0x0504, reg0);
310SET(p, 0x0500, 0x008B);
311
312GET(p, 0x0502, &igot); got502 = (0xFF & igot);
313GET(p, 0x0503, &igot); got503 = (0xFF & igot);
314
315JOT(16, "write_vt(., 0x%04X, 0x%04X): was 0x%04X\n", \
316 reg0, set0, ((got503 << 8) | got502));
317
318set502 = (0x00FF & set0);
319set503 = ((0xFF00 & set0) >> 8);
320
321SET(p, 0x0504, reg0);
322SET(p, 0x0502, set502);
323SET(p, 0x0503, set503);
324SET(p, 0x0500, 0x008C);
325
326return 0;
327}
328/****************************************************************************/
329/*--------------------------------------------------------------------------*/
330/*
331 * REGISTER 500: SETTING VALUE TO 0x008B READS FROM VT1612A (?)
332 * REGISTER 500: SETTING VALUE TO 0x008C WRITES TO VT1612A
333 * REGISTER 502: LEAST SIGNIFICANT BYTE OF VALUE TO GET
334 * REGISTER 503: MOST SIGNIFICANT BYTE OF VALUE TO GET
335 * REGISTER 504: TARGET ADDRESS ON VT1612A
336 */
337/*--------------------------------------------------------------------------*/
338int
339read_vt(struct usb_device *p, __u16 reg0)
340{
341__u8 igot;
342__u16 got502, got503;
343
344SET(p, 0x0504, reg0);
345SET(p, 0x0500, 0x008B);
346
347GET(p, 0x0502, &igot); got502 = (0xFF & igot);
348GET(p, 0x0503, &igot); got503 = (0xFF & igot);
349
350JOT(16, "read_vt(., 0x%04X): has 0x%04X\n", reg0, ((got503 << 8) | got502));
351
352return (got503 << 8) | got502;
353}
354/****************************************************************************/
355/*--------------------------------------------------------------------------*/
356/*
357 * THESE APPEAR TO HAVE NO EFFECT ON EITHER VIDEO OR AUDIO.
358 */
359/*--------------------------------------------------------------------------*/
360int
361write_300(struct usb_device *p)
362{
363SET(p, 0x300, 0x0012);
364SET(p, 0x350, 0x002D);
365SET(p, 0x351, 0x0001);
366SET(p, 0x352, 0x0000);
367SET(p, 0x353, 0x0000);
368SET(p, 0x300, 0x0080);
369return 0;
370}
371/****************************************************************************/
372/*--------------------------------------------------------------------------*/
373/*
374 * NOTE: THE FOLLOWING IS NOT CHECKED:
375 * REGISTER 0x0F, WHICH IS INVOLVED IN CHROMINANCE AUTOMATIC GAIN CONTROL.
376 */
377/*--------------------------------------------------------------------------*/
378int
379check_saa(struct usb_device *p)
380{
381int i0, ir, rc;
382i0 = 0;
383
384rc = 0;
385while (0xFF != saa7113config[i0].reg) {
386 if (0x0F == saa7113config[i0].reg) {
387 i0++; continue;
388 }
389
390 ir = read_saa(p, saa7113config[i0].reg);
391 if (ir != saa7113config[i0].set) {
392 SAY("SAA register 0x%02X has 0x%02X, expected 0x%02X\n", \
393 saa7113config[i0].reg, ir, saa7113config[i0].set);
394 rc--;
395 }
396 i0++;
397}
398if (-8 > rc)
399 return rc;
400else
401 return 0;
402}
403/****************************************************************************/
404int
405merit_saa(struct usb_device *p)
406{
407int rc;
408
409rc = read_saa(p, 0x1F);
410if ((0 > rc) || (0x02 & rc))
411 return 1 ;
412else
413 return 0;
414}
415/****************************************************************************/
416int
417ready_saa(struct usb_device *p)
418{
419int j, rc;
420static int max = 10;
421
422j = 0;
423while (max > j) {
424 rc = read_saa(p, 0x1F);
425 if (0 <= rc) {
426 if ((1 == (0x01 & rc))&&(0 == (0x40 & rc)))
427 break;
428 }
429 msleep(100); j++;
430}
431if (max == j)
432 return -1;
433else {
434 if (0x20 & rc)
435 JOT(8, "hardware detects 60 Hz\n");
436 else
437 JOT(8, "hardware detects 50 Hz\n");
438 if (0x80 & rc)
439 JOT(8, "hardware detects interlacing\n");
440 else
441 JOT(8, "hardware detects no interlacing\n");
442}
443return 0;
444}
445/****************************************************************************/
446/*--------------------------------------------------------------------------*/
447/*
448 * NOTE: THE FOLLOWING ARE NOT CHECKED:
449 * REGISTERS 0x000, 0x002: FUNCTIONALITY IS NOT KNOWN
450 * REGISTER 0x100: ACCEPT ALSO (0x80 | stk1160config[.].set)
451 */
452/*--------------------------------------------------------------------------*/
453int
454check_stk(struct usb_device *p)
455{
456int i0, ir;
457i0 = 0;
458while (0xFFF != stk1160config[i0].reg) {
459 if (0x000 == stk1160config[i0].reg) {
460 i0++; continue;
461 }
462 if (0x002 == stk1160config[i0].reg) {
463 i0++; continue;
464 }
465
466 ir = read_stk(p, stk1160config[i0].reg);
467
468 if (0x100 == stk1160config[i0].reg) {
469 if ((ir != (0xFF & stk1160config[i0].set)) && \
470 (ir != (0x80 | (0xFF & stk1160config[i0].set))) && \
471 (0xFFFF != stk1160config[i0].set)) {
472 SAY("STK register 0x%03X has 0x%02X, " \
473 "expected 0x%02X\n", \
474 stk1160config[i0].reg, ir, \
475 stk1160config[i0].set);
476 }
477 i0++; continue;
478 }
479
480 if ((ir != (0xFF & stk1160config[i0].set)) && \
481 (0xFFFF != stk1160config[i0].set)) {
482 SAY("STK register 0x%03X has 0x%02X, " \
483 "expected 0x%02X\n", \
484 stk1160config[i0].reg, ir, \
485 stk1160config[i0].set);
486 }
487 i0++;
488 }
489return 0;
490}
491/****************************************************************************/
492int
493read_saa(struct usb_device *p, __u16 reg0)
494{
495__u8 igot;
496
497SET(p, 0x208, reg0);
498SET(p, 0x200, 0x20);
499if (0 != wait_i2c(p))
500 return -1;
501igot = 0;
502GET(p, 0x0209, &igot);
503return igot;
504}
505/****************************************************************************/
506int
507read_stk(struct usb_device *p, __u32 reg0)
508{
509__u8 igot;
510
511igot = 0;
512GET(p, reg0, &igot);
513return igot;
514}
515/*****************************************************************************/
516/*---------------------------------------------------------------------------*/
517/*
518 * HARDWARE USERSPACE INPUT NUMBER PHYSICAL INPUT DRIVER input VALUE
519 *
520 * CVBS+S-VIDEO 0 or 1 CVBS 1
521 * FOUR-CVBS 0 or 1 CVBS1 1
522 * FOUR-CVBS 2 CVBS2 2
523 * FOUR-CVBS 3 CVBS3 3
524 * FOUR-CVBS 4 CVBS4 4
525 * CVBS+S-VIDEO 5 S-VIDEO 5
526 *
527 * WHEN 5==input THE ARGUMENT mode MUST ALSO BE SUPPLIED:
528 *
529 * mode 7 => GAIN TO BE SET EXPLICITLY USING REGISTER 0x05 (UNTESTED)
530 * mode 9 => USE AUTOMATIC GAIN CONTROL (DEFAULT)
531 *
532*/
533/*---------------------------------------------------------------------------*/
534int
535select_input(struct usb_device *p, int input, int mode)
536{
537
538stop_100(p);
539
540msleep(20);
541switch (input) {
542case 0:
543case 1: {
544 SET(p, 0x0000, 0x0098); break;
545}
546case 2: {
547 SET(p, 0x0000, 0x0090); break;
548}
549case 3: {
550 SET(p, 0x0000, 0x0088); break;
551}
552case 4: {
553 SET(p, 0x0000, 0x0080); break;
554}
555case 5: {
556 if (9 != mode)
557 mode = 7;
558 switch (mode) {
559 case 7:
560 {
561 if (0 != write_saa(p, 0x02, 0x87)) {
562 SAY("ERROR: failed to set SAA " \
563 "register 0x02 for input " \
564 "%i\n", input);
565 }
566 if (0 != write_saa(p, 0x05, 0xFF)) {
567 SAY("ERROR: failed to set SAA " \
568 "register 0x05 for input " \
569 "%i\n", input);
570 }
571 break;
572 }
573 case 9:
574 {
575 if (0 != write_saa(p, 0x02, 0x89)) {
576 SAY("ERROR: failed to set SAA " \
577 "register 0x02 for input " \
578 "%i\n", input);
579 }
580 if (0 != write_saa(p, 0x05, 0x00)) {
581 SAY("ERROR: failed to set SAA " \
582 "register 0x05 for input " \
583 "%i\n", input);
584 }
585 break;
586 }
587 default:
588 {
589 SAY("MISTAKE: bad mode: %i\n", mode);
590 return -1;
591 }
592 }
593 if (0 != write_saa(p, 0x04, 0x00)) {
594 SAY("ERROR: failed to set SAA register 0x04 " \
595 "for input %i\n", input);
596 }
597 if (0 != write_saa(p, 0x09, 0x80)) {
598 SAY("ERROR: failed to set SAA register 0x09 " \
599 "for input %i\n", input);
600 }
601 break;
602}
603default:
604 {
605 SAY("ERROR: bad input: %i\n", input);
606 return -1;
607}
608}
609msleep(20);
610SET(p, 0x0002, 0x0093);
611msleep(20);
612
613start_100(p);
614
615return 0;
616}
617/****************************************************************************/
618int
619set_resolution(struct usb_device *p, \
620 __u16 set0, __u16 set1, __u16 set2, __u16 set3)
621{
622__u16 u0x0111, u0x0113, u0x0115, u0x0117;
623
624u0x0111 = ((0xFF00 & set0) >> 8);
625u0x0113 = ((0xFF00 & set1) >> 8);
626u0x0115 = ((0xFF00 & set2) >> 8);
627u0x0117 = ((0xFF00 & set3) >> 8);
628
629SET(p, 0x0110, (0x00FF & set0));
630SET(p, 0x0111, u0x0111);
631SET(p, 0x0112, (0x00FF & set1));
632SET(p, 0x0113, u0x0113);
633SET(p, 0x0114, (0x00FF & set2));
634SET(p, 0x0115, u0x0115);
635SET(p, 0x0116, (0x00FF & set3));
636SET(p, 0x0117, u0x0117);
637
638return 0;
639}
640/****************************************************************************/
641int
642start_100(struct usb_device *p)
643{
644__u16 get0;
645__u8 igot;
646
647GET(p, 0x0100, &igot); get0 = igot;
648msleep(0x1f4);
649SET(p, 0x0100, (0x80 | get0));
650msleep(0x1f4);
651return 0;
652}
653/****************************************************************************/
654int
655stop_100(struct usb_device *p)
656{
657__u16 get0;
658__u8 igot;
659
660GET(p, 0x0100, &igot); get0 = igot;
661msleep(0x1f4);
662SET(p, 0x0100, (0x7F & get0));
663msleep(0x1f4);
664return 0;
665}
666/****************************************************************************/
667/*--------------------------------------------------------------------------*/
668/*
669 * FUNCTION wait_i2c() RETURNS 0 ON SUCCESS
670*/
671/*--------------------------------------------------------------------------*/
672int
673wait_i2c(struct usb_device *p)
674{
675__u16 get0;
676__u8 igot;
677const int max = 4;
678int k;
679
680for (k = 0; k < max; k++) {
681 GET(p, 0x0201, &igot); get0 = igot;
682 switch (get0) {
683 case 0x04:
684 case 0x01: {
685 return 0;
686 }
687 case 0x00: {
688 msleep(10);
689 continue;
690 }
691 default: {
692 return get0 - 1;
693 }
694 }
695}
696return -1;
697}
698/****************************************************************************/
699int
700regset(struct usb_device *pusb_device, __u16 index, __u16 value)
701{
702__u16 igot;
703int rc0, rc1;
704
705if (!pusb_device)
706 return -EFAULT;
707
708rc1 = 0; igot = 0;
709rc0 = usb_control_msg(pusb_device, usb_sndctrlpipe(pusb_device, 0), \
710 (__u8)0x01, \
711 (__u8)(USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE), \
712 (__u16)value, \
713 (__u16)index, \
714 (void *)NULL, \
715 (__u16)0, \
716 (int)500);
717
718#if defined(NOREADBACK)
719#
720#else
721rc1 = usb_control_msg(pusb_device, usb_rcvctrlpipe(pusb_device, 0), \
722 (__u8)0x00, \
723 (__u8)(USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE), \
724 (__u16)0x00, \
725 (__u16)index, \
726 (void *)&igot, \
727 (__u16)sizeof(__u16), \
728 (int)50000);
729igot = 0xFF & igot;
730switch (index) {
731case 0x000:
732case 0x500:
733case 0x502:
734case 0x503:
735case 0x504:
736case 0x506:
737case 0x507: {
738 break;
739}
740case 0x204:
741case 0x205:
742case 0x350:
743case 0x351: {
744 if (0 != igot) {
745 JOT(8, "unexpected 0x%02X for STK register 0x%03X\n", \
746 igot, index);
747 }
748break;
749}
750case 0x114:
751case 0x116: {
752 if ((0xFF & value) != igot) {
753 JOT(8, "unexpected 0x%02X != 0x%02X " \
754 "for STK register 0x%03X\n", \
755 igot, value, index);
756 }
757break;
758}
759case 0x200: {
760 if (0 == igot)
761 break;
762}
763default: {
764 if (value != igot) {
765 JOT(8, "unexpected 0x%02X != 0x%02X " \
766 "for STK register 0x%03X\n", \
767 igot, value, index);
768 }
769break;
770}
771}
772#endif /* ! NOREADBACK*/
773
774return (0 > rc0) ? rc0 : rc1;
775}
776/*****************************************************************************/
777int
778regget(struct usb_device *pusb_device, __u16 index, void *pvoid)
779{
780int ir;
781
782if (!pusb_device)
783 return -EFAULT;
784
785ir = usb_control_msg(pusb_device, usb_rcvctrlpipe(pusb_device, 0), \
786 (__u8)0x00, \
787 (__u8)(USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE), \
788 (__u16)0x00, \
789 (__u16)index, \
790 (void *)pvoid, \
791 sizeof(__u8), \
792 (int)50000);
793return 0xFF & ir;
794}
795/*****************************************************************************/
796int
797wakeup_device(struct usb_device *pusb_device)
798{
799return usb_control_msg(pusb_device, usb_sndctrlpipe(pusb_device, 0), \
800 (__u8)USB_REQ_SET_FEATURE, \
801 (__u8)(USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE), \
802 USB_DEVICE_REMOTE_WAKEUP, \
803 (__u16)0, \
804 (void *) NULL, \
805 (__u16)0, \
806 (int)50000);
807}
808/*****************************************************************************/
809/*---------------------------------------------------------------------------*/
810/*
811 * IMPORTANT:
812 * THE MESSAGE OF TYPE (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE)
813 * CAUSES MUTING IF THE VALUE 0x0100 IS SENT.
814 * TO ENABLE AUDIO THE VALUE 0x0200 MUST BE SENT.
815 */
816/*---------------------------------------------------------------------------*/
817int
818audio_setup(struct easycap *peasycap)
819{
820struct usb_device *pusb_device;
821static __u8 request = 0x01;
822static __u8 requesttype = \
823 (__u8)(USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE);
824
825static __u16 value_unmute = 0x0200;
826static __u16 index = 0x0301;
827
828static unsigned char buffer[1];
829static __u16 length = 1;
7ebc8760 830int rc, id1, id2;
702422bd
T
831
832if (NULL == peasycap)
833 return -EFAULT;
834
835pusb_device = peasycap->pusb_device;
836if (NULL == pusb_device)
837 return -EFAULT;
838
839JOT(8, "%02X %02X %02X %02X %02X %02X %02X %02X\n", \
840 requesttype, request, \
841 (0x00FF & value_unmute), \
842 (0xFF00 & value_unmute) >> 8, \
843 (0x00FF & index), \
844 (0xFF00 & index) >> 8, \
845 (0x00FF & length), \
846 (0xFF00 & length) >> 8);
847
848buffer[0] = 0x01;
849
850rc = usb_control_msg(pusb_device, usb_sndctrlpipe(pusb_device, 0), \
851 (__u8)request, \
852 (__u8)requesttype, \
853 (__u16)value_unmute, \
854 (__u16)index, \
855 (void *)&buffer[0], \
856 (__u16)length, \
857 (int)50000);
858
859JOT(8, "0x%02X=buffer\n", *((__u8 *) &buffer[0]));
860if (rc != (int)length)
861 SAY("ERROR: usb_control_msg returned %i\n", rc);
862
863/*--------------------------------------------------------------------------*/
864/*
865 * REGISTER 500: SETTING VALUE TO 0x0094 RESETS AUDIO CONFIGURATION ???
866 * REGISTER 506: ANALOGUE AUDIO ATTENTUATOR ???
867 * FOR THE CVBS+S-VIDEO HARDWARE:
868 * SETTING VALUE TO 0x0000 GIVES QUIET SOUND.
869 * THE UPPER BYTE SEEMS TO HAVE NO EFFECT.
870 * FOR THE FOUR-CVBS HARDWARE:
871 * SETTING VALUE TO 0x0000 SEEMS TO HAVE NO EFFECT.
872 * REGISTER 507: ANALOGUE AUDIO PREAMPLIFIER ON/OFF ???
873 * FOR THE CVBS-S-VIDEO HARDWARE:
874 * SETTING VALUE TO 0x0001 GIVES VERY LOUD, DISTORTED SOUND.
875 * THE UPPER BYTE SEEMS TO HAVE NO EFFECT.
876 */
877/*--------------------------------------------------------------------------*/
878
879SET(pusb_device, 0x0500, 0x0094);
880
881SET(pusb_device, 0x0500, 0x008C);
882
883SET(pusb_device, 0x0506, 0x0001);
884SET(pusb_device, 0x0507, 0x0000);
885
7ebc8760
MT
886id1 = read_vt(pusb_device, 0x007C);
887id2 = read_vt(pusb_device, 0x007E);
888SAY("0x%04X:0x%04X is audio vendor id\n", id1, id2);
889
890/*---------------------------------------------------------------------------*/
891/*
892* SELECT AUDIO SOURCE "LINE IN" AND SET DEFAULT GAIN TO 0 dB.
893*
894* THESE COMMANDS SEEM TO BE ACCEPTED (THOUGH POSSIBLY IGNORED) EVEN WHEN
895* THERE IS NO SEPARATE AUDIO CHIP PRESENT.
896*/
897/*---------------------------------------------------------------------------*/
898
899write_vt(pusb_device, 0x0002, 0x8000);
900write_vt(pusb_device, 0x001C, 0x8000);
901
902write_vt(pusb_device, 0x000E, 0x0000);
903write_vt(pusb_device, 0x0010, 0x0000);
904write_vt(pusb_device, 0x0012, 0x8000);
905write_vt(pusb_device, 0x0016, 0x0000);
906
907write_vt(pusb_device, 0x001A, 0x0404);
908write_vt(pusb_device, 0x0002, 0x0000);
909write_vt(pusb_device, 0x001C, 0x0000);
702422bd
T
910
911check_vt(pusb_device);
912
913return 0;
914}
915/*****************************************************************************/
916int
917check_vt(struct usb_device *pusb_device)
918{
919int igot;
920
921igot = read_vt(pusb_device, 0x0002);
922if (0 > igot)
923 SAY("ERROR: failed to read VT1612A register 0x02\n");
924if (0x8000 & igot)
925 SAY("register 0x%02X muted\n", 0x02);
926
927igot = read_vt(pusb_device, 0x000E);
928if (0 > igot)
929 SAY("ERROR: failed to read VT1612A register 0x0E\n");
930if (0x8000 & igot)
931 SAY("register 0x%02X muted\n", 0x0E);
932
933igot = read_vt(pusb_device, 0x0010);
934if (0 > igot)
935 SAY("ERROR: failed to read VT1612A register 0x10\n");
936if (0x8000 & igot)
937 SAY("register 0x%02X muted\n", 0x10);
938
939igot = read_vt(pusb_device, 0x0012);
940if (0 > igot)
941 SAY("ERROR: failed to read VT1612A register 0x12\n");
942if (0x8000 & igot)
943 SAY("register 0x%02X muted\n", 0x12);
944
945igot = read_vt(pusb_device, 0x0016);
946if (0 > igot)
947 SAY("ERROR: failed to read VT1612A register 0x16\n");
948if (0x8000 & igot)
949 SAY("register 0x%02X muted\n", 0x16);
950
951igot = read_vt(pusb_device, 0x001A);
952if (0 > igot)
953 SAY("ERROR: failed to read VT1612A register 0x1A\n");
954if (0x8000 & igot)
955 SAY("register 0x%02X muted\n", 0x1A);
956
957igot = read_vt(pusb_device, 0x001C);
958if (0 > igot)
959 SAY("ERROR: failed to read VT1612A register 0x1C\n");
960if (0x8000 & igot)
961 SAY("register 0x%02X muted\n", 0x1C);
962
963return 0;
964}
965/*****************************************************************************/
966/*---------------------------------------------------------------------------*/
967/*
968 * NOTE: THIS DOES INCREASE THE VOLUME DRAMATICALLY:
969 * audio_gainset(pusb_device, 0x000F);
970 *
971 * IF 16<loud<31 VT1621A REGISTER 0x1C IS SET FOR POSITIVE GAIN.
972 * IF loud<=16 VT1621A REGISTER 0x1C IS SET FOR ZERO GAIN.
973 * THERE IS NEVER ANY (ADDITIONAL) ATTENUATION.
974 */
975/*---------------------------------------------------------------------------*/
976int
977audio_gainset(struct usb_device *pusb_device, __s8 loud)
978{
979int igot;
980__u8 u8;
981__u16 mute;
982
983if (16 > loud)
984 loud = 16;
985u8 = 0x000F & (__u8)(loud - 16);
986
987write_vt(pusb_device, 0x0002, 0x8000);
988
989igot = read_vt(pusb_device, 0x001C);
990if (0 > igot) {
991 SAY("ERROR: failed to read VT1612A register 0x1C\n");
992 mute = 0x0000;
993} else
994 mute = 0x8000 & ((unsigned int)igot);
995
996JOT(8, "0x%04X=(mute|u8|(u8<<8))\n", mute | u8 | (u8 << 8));
997
998write_vt(pusb_device, 0x001C, 0x8000);
999write_vt(pusb_device, 0x001C, (mute | u8 | (u8 << 8)));
1000write_vt(pusb_device, 0x0002, 0x0000);
1001
1002return 0;
1003}
1004/*****************************************************************************/
1005int
1006audio_gainget(struct usb_device *pusb_device)
1007{
1008int igot;
1009
1010igot = read_vt(pusb_device, 0x001C);
1011if (0 > igot)
1012 SAY("ERROR: failed to read VT1612A register 0x1C\n");
1013return igot;
1014}
1015/*****************************************************************************/
1016int
1017set2to78(struct usb_device *p)
1018{
1019int ir;
1020
1021msleep(20);
1022ir = regset(p, 0x0002, 0x0078);
1023if (0 > ir)
1024 SAY("ERROR: failed to set register 0x0002 to 0x0078\n");
1025msleep(20);
1026return ir;
1027}
1028/*****************************************************************************/
1029int
1030set2to93(struct usb_device *p)
1031{
1032int ir;
1033
1034msleep(20);
1035ir = regset(p, 0x0002, 0x0093);
1036if (0 > ir)
1037 SAY("ERROR: failed to set register 0x0002 to 0x0078\n");
1038msleep(20);
1039return ir;
1040}
1041/*****************************************************************************/
This page took 0.121761 seconds and 5 git commands to generate.