diff options
124 files changed, 15643 insertions, 4337 deletions
diff --git a/Documentation/dvb/cards.txt b/Documentation/dvb/cards.txt index ca58e339d85f..cc09187a5db7 100644 --- a/Documentation/dvb/cards.txt +++ b/Documentation/dvb/cards.txt | |||
@@ -22,10 +22,10 @@ o Frontends drivers: | |||
22 | - ves1x93 : Alps BSRV2 (ves1893 demodulator) and dbox2 (ves1993) | 22 | - ves1x93 : Alps BSRV2 (ves1893 demodulator) and dbox2 (ves1993) |
23 | - cx24110 : Conexant HM1221/HM1811 (cx24110 or cx24106 demod, cx24108 PLL) | 23 | - cx24110 : Conexant HM1221/HM1811 (cx24110 or cx24106 demod, cx24108 PLL) |
24 | - grundig_29504-491 : Grundig 29504-491 (Philips TDA8083 demodulator), tsa5522 PLL | 24 | - grundig_29504-491 : Grundig 29504-491 (Philips TDA8083 demodulator), tsa5522 PLL |
25 | - mt312 : Zarlink mt312 or Mitel vp310 demodulator, sl1935 or tsa5059 PLL | 25 | - mt312 : Zarlink mt312 or Mitel vp310 demodulator, sl1935 or tsa5059 PLLi, Technisat Sky2Pc with bios Rev. 2.3 |
26 | - stv0299 : Alps BSRU6 (tsa5059 PLL), LG TDQB-S00x (tsa5059 PLL), | 26 | - stv0299 : Alps BSRU6 (tsa5059 PLL), LG TDQB-S00x (tsa5059 PLL), |
27 | LG TDQF-S001F (sl1935 PLL), Philips SU1278 (tua6100 PLL), | 27 | LG TDQF-S001F (sl1935 PLL), Philips SU1278 (tua6100 PLL), |
28 | Philips SU1278SH (tsa5059 PLL), Samsung TBMU24112IMB | 28 | Philips SU1278SH (tsa5059 PLL), Samsung TBMU24112IMB, Technisat Sky2Pc with bios Rev. 2.6 |
29 | DVB-C: | 29 | DVB-C: |
30 | - ves1820 : various (ves1820 demodulator, sp5659c or spXXXX PLL) | 30 | - ves1820 : various (ves1820 demodulator, sp5659c or spXXXX PLL) |
31 | - at76c651 : Atmel AT76c651(B) with DAT7021 PLL | 31 | - at76c651 : Atmel AT76c651(B) with DAT7021 PLL |
diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index 8755b3e7b09e..62e32b49cec9 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 | |||
@@ -43,7 +43,7 @@ | |||
43 | 42 -> digitalnow DNTV Live! DVB-T Pro [1822:0025,1822:0019] | 43 | 42 -> digitalnow DNTV Live! DVB-T Pro [1822:0025,1822:0019] |
44 | 43 -> KWorld/VStream XPert DVB-T with cx22702 [17de:08a1,12ab:2300] | 44 | 43 -> KWorld/VStream XPert DVB-T with cx22702 [17de:08a1,12ab:2300] |
45 | 44 -> DViCO FusionHDTV DVB-T Dual Digital [18ac:db50,18ac:db54] | 45 | 44 -> DViCO FusionHDTV DVB-T Dual Digital [18ac:db50,18ac:db54] |
46 | 45 -> KWorld HardwareMpegTV XPert [17de:0840] | 46 | 45 -> KWorld HardwareMpegTV XPert [17de:0840,1421:0305] |
47 | 46 -> DViCO FusionHDTV DVB-T Hybrid [18ac:db40,18ac:db44] | 47 | 46 -> DViCO FusionHDTV DVB-T Hybrid [18ac:db40,18ac:db44] |
48 | 47 -> pcHDTV HD5500 HDTV [7063:5500] | 48 | 47 -> pcHDTV HD5500 HDTV [7063:5500] |
49 | 48 -> Kworld MCE 200 Deluxe [17de:0841] | 49 | 48 -> Kworld MCE 200 Deluxe [17de:0841] |
diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 53ce6a39083c..f6201cc37ec5 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 | |||
@@ -76,7 +76,7 @@ | |||
76 | 75 -> AVerMedia AVerTVHD MCE A180 [1461:1044] | 76 | 75 -> AVerMedia AVerTVHD MCE A180 [1461:1044] |
77 | 76 -> SKNet MonsterTV Mobile [1131:4ee9] | 77 | 76 -> SKNet MonsterTV Mobile [1131:4ee9] |
78 | 77 -> Pinnacle PCTV 40i/50i/110i (saa7133) [11bd:002e] | 78 | 77 -> Pinnacle PCTV 40i/50i/110i (saa7133) [11bd:002e] |
79 | 78 -> ASUSTeK P7131 Dual [1043:4862] | 79 | 78 -> ASUSTeK P7131 Dual [1043:4862,1043:4876] |
80 | 79 -> Sedna/MuchTV PC TV Cardbus TV/Radio (ITO25 Rev:2B) | 80 | 79 -> Sedna/MuchTV PC TV Cardbus TV/Radio (ITO25 Rev:2B) |
81 | 80 -> ASUS Digimatrix TV [1043:0210] | 81 | 80 -> ASUS Digimatrix TV [1043:0210] |
82 | 81 -> Philips Tiger reference design [1131:2018] | 82 | 81 -> Philips Tiger reference design [1131:2018] |
@@ -99,3 +99,8 @@ | |||
99 | 98 -> Proteus Pro 2309 [0919:2003] | 99 | 98 -> Proteus Pro 2309 [0919:2003] |
100 | 99 -> AVerMedia TV Hybrid A16AR [1461:2c00] | 100 | 99 -> AVerMedia TV Hybrid A16AR [1461:2c00] |
101 | 100 -> Asus Europa2 OEM [1043:4860] | 101 | 100 -> Asus Europa2 OEM [1043:4860] |
102 | 101 -> Pinnacle PCTV 310i [11bd:002f] | ||
103 | 102 -> Avermedia AVerTV Studio 507 [1461:9715] | ||
104 | 103 -> Compro Videomate DVB-T200A | ||
105 | 104 -> Hauppauge WinTV-HVR1110 DVB-T/Hybrid [0070:6701] | ||
106 | 105 -> Terratec Cinergy HT PCMCIA [153b:1172] | ||
diff --git a/Documentation/video4linux/cafe_ccic b/Documentation/video4linux/cafe_ccic new file mode 100644 index 000000000000..88821022a5de --- /dev/null +++ b/Documentation/video4linux/cafe_ccic | |||
@@ -0,0 +1,54 @@ | |||
1 | "cafe_ccic" is a driver for the Marvell 88ALP01 "cafe" CMOS camera | ||
2 | controller. This is the controller found in first-generation OLPC systems, | ||
3 | and this driver was written with support from the OLPC project. | ||
4 | |||
5 | Current status: the core driver works. It can generate data in YUV422, | ||
6 | RGB565, and RGB444 formats. (Anybody looking at the code will see RGB32 as | ||
7 | well, but that is a debugging aid which will be removed shortly). VGA and | ||
8 | QVGA modes work; CIF is there but the colors remain funky. Only the OV7670 | ||
9 | sensor is known to work with this controller at this time. | ||
10 | |||
11 | To try it out: either of these commands will work: | ||
12 | |||
13 | mplayer tv:// -tv driver=v4l2:width=640:height=480 -nosound | ||
14 | mplayer tv:// -tv driver=v4l2:width=640:height=480:outfmt=bgr16 -nosound | ||
15 | |||
16 | The "xawtv" utility also works; gqcam does not, for unknown reasons. | ||
17 | |||
18 | There are a few load-time options, most of which can be changed after | ||
19 | loading via sysfs as well: | ||
20 | |||
21 | - alloc_bufs_at_load: Normally, the driver will not allocate any DMA | ||
22 | buffers until the time comes to transfer data. If this option is set, | ||
23 | then worst-case-sized buffers will be allocated at module load time. | ||
24 | This option nails down the memory for the life of the module, but | ||
25 | perhaps decreases the chances of an allocation failure later on. | ||
26 | |||
27 | - dma_buf_size: The size of DMA buffers to allocate. Note that this | ||
28 | option is only consulted for load-time allocation; when buffers are | ||
29 | allocated at run time, they will be sized appropriately for the current | ||
30 | camera settings. | ||
31 | |||
32 | - n_dma_bufs: The controller can cycle through either two or three DMA | ||
33 | buffers. Normally, the driver tries to use three buffers; on faster | ||
34 | systems, however, it will work well with only two. | ||
35 | |||
36 | - min_buffers: The minimum number of streaming I/O buffers that the driver | ||
37 | will consent to work with. Default is one, but, on slower systems, | ||
38 | better behavior with mplayer can be achieved by setting to a higher | ||
39 | value (like six). | ||
40 | |||
41 | - max_buffers: The maximum number of streaming I/O buffers; default is | ||
42 | ten. That number was carefully picked out of a hat and should not be | ||
43 | assumed to actually mean much of anything. | ||
44 | |||
45 | - flip: If this boolean parameter is set, the sensor will be instructed to | ||
46 | invert the video image. Whether it makes sense is determined by how | ||
47 | your particular camera is mounted. | ||
48 | |||
49 | Work is ongoing with this driver, stay tuned. | ||
50 | |||
51 | jon | ||
52 | |||
53 | Jonathan Corbet | ||
54 | corbet@lwn.net | ||
diff --git a/Documentation/video4linux/zr36120.txt b/Documentation/video4linux/zr36120.txt deleted file mode 100644 index 1a1c2d03a5c8..000000000000 --- a/Documentation/video4linux/zr36120.txt +++ /dev/null | |||
@@ -1,162 +0,0 @@ | |||
1 | Driver for Trust Computer Products Framegrabber, version 0.6.1 | ||
2 | ------ --- ----- -------- -------- ------------ ------- - - - | ||
3 | |||
4 | - ZORAN ------------------------------------------------------ | ||
5 | Author: Pauline Middelink <middelin@polyware.nl> | ||
6 | Date: 18 September 1999 | ||
7 | Version: 0.6.1 | ||
8 | |||
9 | - Description ------------------------------------------------ | ||
10 | |||
11 | Video4Linux compatible driver for an unknown brand framegrabber | ||
12 | (Sold in the Netherlands by TRUST Computer Products) and various | ||
13 | other zoran zr36120 based framegrabbers. | ||
14 | |||
15 | The card contains a ZR36120 Multimedia PCI Interface and a Philips | ||
16 | SAA7110 Onechip Frontend videodecoder. There is also an DSP of | ||
17 | which I have forgotten the number, since i will never get that thing | ||
18 | to work without specs from the vendor itself. | ||
19 | |||
20 | The SAA711x are capable of processing 6 different video inputs, | ||
21 | CVBS1..6 and Y1+C1, Y2+C2, Y3+C3. All in 50/60Hz, NTSC, PAL or | ||
22 | SECAM and delivering a YUV datastream. On my card the input | ||
23 | 'CVBS-0' corresponds to channel CVBS2 and 'S-Video' to Y2+C2. | ||
24 | |||
25 | I have some reports of other cards working with the mentioned | ||
26 | chip sets. For a list of other working cards please have a look | ||
27 | at the cards named in the tvcards struct in the beginning of | ||
28 | zr36120.c | ||
29 | |||
30 | After some testing, I discovered that the carddesigner messed up | ||
31 | on the I2C interface. The Zoran chip includes 2 lines SDA and SCL | ||
32 | which (s)he connected reversely. So we have to clock on the SDA | ||
33 | and r/w data on the SCL pin. Life is fun... Each cardtype now has | ||
34 | a bit which signifies if you have a card with the same deficiency. | ||
35 | |||
36 | Oh, for the completeness of this story I must mention that my | ||
37 | card delivers the VSYNC pulse of the SAA chip to GIRQ1, not | ||
38 | GIRQ0 as some other cards have. This is also incorporated in | ||
39 | the driver be clearing/setting the 'useirq1' bit in the tvcard | ||
40 | description. | ||
41 | |||
42 | Another problems of continuous capturing data with a Zoran chip | ||
43 | is something nasty inside the chip. It effectively halves the | ||
44 | fps we ought to get... Here is the scenario: capturing frames | ||
45 | to memory is done in the so-called snapshot mode. In this mode | ||
46 | the Zoran stops after capturing a frame worth of data and wait | ||
47 | till the application set GRAB bit to indicate readiness for the | ||
48 | next frame. After detecting a set bit, the chip neatly waits | ||
49 | till the start of a frame, captures it and it goes back to off. | ||
50 | Smart ppl will notice the problem here. Its the waiting on the | ||
51 | _next_ frame each time we set the GRAB bit... Oh well, 12,5 fps | ||
52 | is still plenty fast for me. | ||
53 | -- update 28/7/1999 -- | ||
54 | Don't believe a word I just said... Proof is the output | ||
55 | of `streamer -t 300 -r 25 -f avi15 -o /dev/null` | ||
56 | ++--+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25 | ||
57 | +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25 | ||
58 | +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25 | ||
59 | +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25 | ||
60 | +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25 | ||
61 | +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25 | ||
62 | +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25 | ||
63 | +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25 | ||
64 | +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25 | ||
65 | +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25 | ||
66 | +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25 | ||
67 | +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- | ||
68 | syncer: done | ||
69 | writer: done | ||
70 | (note the /dev/null is prudent here, my system is not able to | ||
71 | grab /and/ write 25 fps to a file... gifts welcome :) ) | ||
72 | The technical reasoning follows: The zoran completed the last | ||
73 | frame, the VSYNC goes low, and GRAB is cleared. The interrupt | ||
74 | routine starts to work since its VSYNC driven, and again | ||
75 | activates the GRAB bit. A few ms later the VSYNC (re-)rises and | ||
76 | the zoran starts to work on a new and freshly broadcasted frame.... | ||
77 | |||
78 | For pointers I used the specs of both chips. Below are the URLs: | ||
79 | http://www.zoran.com/ftp/download/devices/pci/ZR36120/36120data.pdf | ||
80 | http://www-us.semiconductor.philips.com/acrobat/datasheets/SAA_7110_A_1.pdf | ||
81 | Some alternatives for the Philips SAA 7110 datasheet are: | ||
82 | http://www.datasheetcatalog.com/datasheets_pdf/S/A/A/7/SAA7110.shtml | ||
83 | http://www.datasheetarchive.com/search.php?search=SAA7110&sType=part | ||
84 | |||
85 | The documentation has very little on absolute numbers or timings | ||
86 | needed for the various modes/resolutions, but there are other | ||
87 | programs you can borrow those from. | ||
88 | |||
89 | ------ Install -------------------------------------------- | ||
90 | Read the file called TODO. Note its long list of limitations. | ||
91 | |||
92 | Build a kernel with VIDEO4LINUX enabled. Activate the | ||
93 | BT848 driver; we need this because we have need for the | ||
94 | other modules (i2c and videodev) it enables. | ||
95 | |||
96 | To install this software, extract it into a suitable directory. | ||
97 | Examine the makefile and change anything you don't like. Type "make". | ||
98 | |||
99 | After making the modules check if you have the much needed | ||
100 | /dev/video devices. If not, execute the following 4 lines: | ||
101 | mknod /dev/video c 81 0 | ||
102 | mknod /dev/video1 c 81 1 | ||
103 | mknod /dev/video2 c 81 2 | ||
104 | mknod /dev/video3 c 81 3 | ||
105 | mknod /dev/video4 c 81 4 | ||
106 | |||
107 | After making/checking the devices do: | ||
108 | modprobe i2c | ||
109 | modprobe videodev | ||
110 | modprobe saa7110 (optional) | ||
111 | modprobe saa7111 (optional) | ||
112 | modprobe tuner (optional) | ||
113 | insmod zoran cardtype=<n> | ||
114 | |||
115 | <n> is the cardtype of the card you have. The cardnumber can | ||
116 | be found in the source of zr36120. Look for tvcards. If your | ||
117 | card is not there, please try if any other card gives some | ||
118 | response, and mail me if you got a working tvcard addition. | ||
119 | |||
120 | PS. <TVCard editors behold!) | ||
121 | Don't forget to set video_input to the number of inputs | ||
122 | you defined in the video_mux part of the tvcard definition. | ||
123 | It's a common error to add a channel but not incrementing | ||
124 | video_input and getting angry with me/v4l/linux/linus :( | ||
125 | |||
126 | You are now ready to test the framegrabber with your favorite | ||
127 | video4linux compatible tool | ||
128 | |||
129 | ------ Application ---------------------------------------- | ||
130 | |||
131 | This device works with all Video4Linux compatible applications, | ||
132 | given the limitations in the TODO file. | ||
133 | |||
134 | ------ API ------------------------------------------------ | ||
135 | |||
136 | This uses the V4L interface as of kernel release 2.1.116, and in | ||
137 | fact has not been tested on any lower version. There are a couple | ||
138 | of minor differences due to the fact that the amount of data returned | ||
139 | with each frame varies, and no doubt there are discrepancies due to my | ||
140 | misunderstanding of the API. I intend to convert this driver to the | ||
141 | new V4L2 API when it has stabilized more. | ||
142 | |||
143 | ------ Current state -------------------------------------- | ||
144 | |||
145 | The driver is capable of overlaying a video image in screen, and | ||
146 | even capable of grabbing frames. It uses the BIGPHYSAREA patch | ||
147 | to allocate lots of large memory blocks when tis patch is | ||
148 | found in the kernel, but it doesn't need it. | ||
149 | The consequence is that, when loading the driver as a module, | ||
150 | the module may tell you it's out of memory, but 'free' says | ||
151 | otherwise. The reason is simple; the modules wants its memory | ||
152 | contiguous, not fragmented, and after a long uptime there | ||
153 | probably isn't a fragment of memory large enough... | ||
154 | |||
155 | The driver uses a double buffering scheme, which should really | ||
156 | be an n-way buffer, depending on the size of allocated framebuffer | ||
157 | and the requested grab-size/format. | ||
158 | This current version also fixes a dead-lock situation during irq | ||
159 | time, which really, really froze my system... :) | ||
160 | |||
161 | Good luck. | ||
162 | Pauline | ||
diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index 9f7e1fe8c97e..87410dbd3df4 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig | |||
@@ -67,6 +67,7 @@ source "drivers/media/common/Kconfig" | |||
67 | 67 | ||
68 | config VIDEO_TUNER | 68 | config VIDEO_TUNER |
69 | tristate | 69 | tristate |
70 | depends on I2C | ||
70 | 71 | ||
71 | config VIDEO_BUF | 72 | config VIDEO_BUF |
72 | tristate | 73 | tristate |
@@ -82,6 +83,7 @@ config VIDEO_IR | |||
82 | 83 | ||
83 | config VIDEO_TVEEPROM | 84 | config VIDEO_TVEEPROM |
84 | tristate | 85 | tristate |
86 | depends on I2C | ||
85 | 87 | ||
86 | config USB_DABUSB | 88 | config USB_DABUSB |
87 | tristate "DABUSB driver" | 89 | tristate "DABUSB driver" |
diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c index db753443587a..f51e02fe3655 100644 --- a/drivers/media/common/ir-keymaps.c +++ b/drivers/media/common/ir-keymaps.c | |||
@@ -1552,3 +1552,58 @@ IR_KEYTAB_TYPE ir_codes_norwood[IR_KEYTAB_SIZE] = { | |||
1552 | }; | 1552 | }; |
1553 | 1553 | ||
1554 | EXPORT_SYMBOL_GPL(ir_codes_norwood); | 1554 | EXPORT_SYMBOL_GPL(ir_codes_norwood); |
1555 | |||
1556 | /* From reading the following remotes: | ||
1557 | * Zenith Universal 7 / TV Mode 807 / VCR Mode 837 | ||
1558 | * Hauppauge (from NOVA-CI-s box product) | ||
1559 | * This is a "middle of the road" approach, differences are noted | ||
1560 | */ | ||
1561 | IR_KEYTAB_TYPE ir_codes_budget_ci_old[IR_KEYTAB_SIZE] = { | ||
1562 | [ 0x00 ] = KEY_0, | ||
1563 | [ 0x01 ] = KEY_1, | ||
1564 | [ 0x02 ] = KEY_2, | ||
1565 | [ 0x03 ] = KEY_3, | ||
1566 | [ 0x04 ] = KEY_4, | ||
1567 | [ 0x05 ] = KEY_5, | ||
1568 | [ 0x06 ] = KEY_6, | ||
1569 | [ 0x07 ] = KEY_7, | ||
1570 | [ 0x08 ] = KEY_8, | ||
1571 | [ 0x09 ] = KEY_9, | ||
1572 | [ 0x0a ] = KEY_ENTER, | ||
1573 | [ 0x0b ] = KEY_RED, | ||
1574 | [ 0x0c ] = KEY_POWER, /* RADIO on Hauppauge */ | ||
1575 | [ 0x0d ] = KEY_MUTE, | ||
1576 | [ 0x0f ] = KEY_A, /* TV on Hauppauge */ | ||
1577 | [ 0x10 ] = KEY_VOLUMEUP, | ||
1578 | [ 0x11 ] = KEY_VOLUMEDOWN, | ||
1579 | [ 0x14 ] = KEY_B, | ||
1580 | [ 0x1c ] = KEY_UP, | ||
1581 | [ 0x1d ] = KEY_DOWN, | ||
1582 | [ 0x1e ] = KEY_OPTION, /* RESERVED on Hauppauge */ | ||
1583 | [ 0x1f ] = KEY_BREAK, | ||
1584 | [ 0x20 ] = KEY_CHANNELUP, | ||
1585 | [ 0x21 ] = KEY_CHANNELDOWN, | ||
1586 | [ 0x22 ] = KEY_PREVIOUS, /* Prev. Ch on Zenith, SOURCE on Hauppauge */ | ||
1587 | [ 0x24 ] = KEY_RESTART, | ||
1588 | [ 0x25 ] = KEY_OK, | ||
1589 | [ 0x26 ] = KEY_CYCLEWINDOWS, /* MINIMIZE on Hauppauge */ | ||
1590 | [ 0x28 ] = KEY_ENTER, /* VCR mode on Zenith */ | ||
1591 | [ 0x29 ] = KEY_PAUSE, | ||
1592 | [ 0x2b ] = KEY_RIGHT, | ||
1593 | [ 0x2c ] = KEY_LEFT, | ||
1594 | [ 0x2e ] = KEY_MENU, /* FULL SCREEN on Hauppauge */ | ||
1595 | [ 0x30 ] = KEY_SLOW, | ||
1596 | [ 0x31 ] = KEY_PREVIOUS, /* VCR mode on Zenith */ | ||
1597 | [ 0x32 ] = KEY_REWIND, | ||
1598 | [ 0x34 ] = KEY_FASTFORWARD, | ||
1599 | [ 0x35 ] = KEY_PLAY, | ||
1600 | [ 0x36 ] = KEY_STOP, | ||
1601 | [ 0x37 ] = KEY_RECORD, | ||
1602 | [ 0x38 ] = KEY_TUNER, /* TV/VCR on Zenith */ | ||
1603 | [ 0x3a ] = KEY_C, | ||
1604 | [ 0x3c ] = KEY_EXIT, | ||
1605 | [ 0x3d ] = KEY_POWER2, | ||
1606 | [ 0x3e ] = KEY_TUNER, | ||
1607 | }; | ||
1608 | |||
1609 | EXPORT_SYMBOL_GPL(ir_codes_budget_ci_old); | ||
diff --git a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c index 5297a365c928..8c85efc26527 100644 --- a/drivers/media/common/saa7146_i2c.c +++ b/drivers/media/common/saa7146_i2c.c | |||
@@ -189,13 +189,21 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d | |||
189 | saa7146_write(dev, I2C_TRANSFER, *dword); | 189 | saa7146_write(dev, I2C_TRANSFER, *dword); |
190 | 190 | ||
191 | dev->i2c_op = 1; | 191 | dev->i2c_op = 1; |
192 | SAA7146_ISR_CLEAR(dev, MASK_16|MASK_17); | ||
192 | SAA7146_IER_ENABLE(dev, MASK_16|MASK_17); | 193 | SAA7146_IER_ENABLE(dev, MASK_16|MASK_17); |
193 | saa7146_write(dev, MC2, (MASK_00 | MASK_16)); | 194 | saa7146_write(dev, MC2, (MASK_00 | MASK_16)); |
194 | 195 | ||
195 | wait_event_interruptible(dev->i2c_wq, dev->i2c_op == 0); | 196 | timeout = HZ/100 + 1; /* 10ms */ |
196 | if (signal_pending (current)) { | 197 | timeout = wait_event_interruptible_timeout(dev->i2c_wq, dev->i2c_op == 0, timeout); |
197 | /* a signal arrived */ | 198 | if (timeout == -ERESTARTSYS || dev->i2c_op) { |
198 | return -ERESTARTSYS; | 199 | SAA7146_IER_DISABLE(dev, MASK_16|MASK_17); |
200 | SAA7146_ISR_CLEAR(dev, MASK_16|MASK_17); | ||
201 | if (timeout == -ERESTARTSYS) | ||
202 | /* a signal arrived */ | ||
203 | return -ERESTARTSYS; | ||
204 | |||
205 | printk(KERN_WARNING "saa7146_i2c_writeout: timed out waiting for end of xfer\n"); | ||
206 | return -EIO; | ||
199 | } | 207 | } |
200 | status = saa7146_read(dev, I2C_STATUS); | 208 | status = saa7146_read(dev, I2C_STATUS); |
201 | } else { | 209 | } else { |
diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig index a0dcd59da76e..79875958930e 100644 --- a/drivers/media/dvb/b2c2/Kconfig +++ b/drivers/media/dvb/b2c2/Kconfig | |||
@@ -9,6 +9,7 @@ config DVB_B2C2_FLEXCOP | |||
9 | select DVB_STV0297 if !DVB_FE_CUSTOMISE | 9 | select DVB_STV0297 if !DVB_FE_CUSTOMISE |
10 | select DVB_BCM3510 if !DVB_FE_CUSTOMISE | 10 | select DVB_BCM3510 if !DVB_FE_CUSTOMISE |
11 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE | 11 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE |
12 | select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE | ||
12 | help | 13 | help |
13 | Support for the digital TV receiver chip made by B2C2 Inc. included in | 14 | Support for the digital TV receiver chip made by B2C2 Inc. included in |
14 | Technisats PCI cards and USB boxes. | 15 | Technisats PCI cards and USB boxes. |
diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index b8ba87863457..c2b35e366242 100644 --- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c | |||
@@ -14,7 +14,7 @@ | |||
14 | #include "stv0297.h" | 14 | #include "stv0297.h" |
15 | #include "mt312.h" | 15 | #include "mt312.h" |
16 | #include "lgdt330x.h" | 16 | #include "lgdt330x.h" |
17 | #include "lg_h06xf.h" | 17 | #include "lgh06xf.h" |
18 | #include "dvb-pll.h" | 18 | #include "dvb-pll.h" |
19 | 19 | ||
20 | /* lnb control */ | 20 | /* lnb control */ |
@@ -303,12 +303,6 @@ static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct fir | |||
303 | return request_firmware(fw, name, fc->dev); | 303 | return request_firmware(fw, name, fc->dev); |
304 | } | 304 | } |
305 | 305 | ||
306 | static int lgdt3303_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) | ||
307 | { | ||
308 | struct flexcop_device *fc = fe->dvb->priv; | ||
309 | return lg_h06xf_pll_set(fe, &fc->i2c_adap, params); | ||
310 | } | ||
311 | |||
312 | static struct lgdt330x_config air2pc_atsc_hd5000_config = { | 306 | static struct lgdt330x_config air2pc_atsc_hd5000_config = { |
313 | .demod_address = 0x59, | 307 | .demod_address = 0x59, |
314 | .demod_chip = LGDT3303, | 308 | .demod_chip = LGDT3303, |
@@ -533,7 +527,7 @@ int flexcop_frontend_init(struct flexcop_device *fc) | |||
533 | /* try the air atsc 3nd generation (lgdt3303) */ | 527 | /* try the air atsc 3nd generation (lgdt3303) */ |
534 | if ((fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) { | 528 | if ((fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) { |
535 | fc->dev_type = FC_AIR_ATSC3; | 529 | fc->dev_type = FC_AIR_ATSC3; |
536 | fc->fe->ops.tuner_ops.set_params = lgdt3303_tuner_set_params; | 530 | dvb_attach(lgh06xf_attach, fc->fe, &fc->i2c_adap); |
537 | info("found the lgdt3303 at i2c address: 0x%02x",air2pc_atsc_hd5000_config.demod_address); | 531 | info("found the lgdt3303 at i2c address: 0x%02x",air2pc_atsc_hd5000_config.demod_address); |
538 | } else | 532 | } else |
539 | /* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */ | 533 | /* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */ |
diff --git a/drivers/media/dvb/bt8xx/Kconfig b/drivers/media/dvb/bt8xx/Kconfig index ae2ff5dc238d..dd66b60fbc98 100644 --- a/drivers/media/dvb/bt8xx/Kconfig +++ b/drivers/media/dvb/bt8xx/Kconfig | |||
@@ -1,13 +1,13 @@ | |||
1 | config DVB_BT8XX | 1 | config DVB_BT8XX |
2 | tristate "BT8xx based PCI cards" | 2 | tristate "BT8xx based PCI cards" |
3 | depends on DVB_CORE && PCI && I2C && VIDEO_BT848 | 3 | depends on DVB_CORE && PCI && I2C && VIDEO_BT848 |
4 | select DVB_PLL | ||
5 | select DVB_MT352 if !DVB_FE_CUSTOMISE | 4 | select DVB_MT352 if !DVB_FE_CUSTOMISE |
6 | select DVB_SP887X if !DVB_FE_CUSTOMISE | 5 | select DVB_SP887X if !DVB_FE_CUSTOMISE |
7 | select DVB_NXT6000 if !DVB_FE_CUSTOMISE | 6 | select DVB_NXT6000 if !DVB_FE_CUSTOMISE |
8 | select DVB_CX24110 if !DVB_FE_CUSTOMISE | 7 | select DVB_CX24110 if !DVB_FE_CUSTOMISE |
9 | select DVB_OR51211 if !DVB_FE_CUSTOMISE | 8 | select DVB_OR51211 if !DVB_FE_CUSTOMISE |
10 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE | 9 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE |
10 | select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE | ||
11 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE | 11 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE |
12 | select FW_LOADER | 12 | select FW_LOADER |
13 | help | 13 | help |
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index 14e69a736eda..80a85cb4975f 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include "dvb_frontend.h" | 34 | #include "dvb_frontend.h" |
35 | #include "dvb-bt8xx.h" | 35 | #include "dvb-bt8xx.h" |
36 | #include "bt878.h" | 36 | #include "bt878.h" |
37 | #include "dvb-pll.h" | ||
38 | 37 | ||
39 | static int debug; | 38 | static int debug; |
40 | 39 | ||
@@ -568,12 +567,6 @@ static struct mt352_config digitv_alps_tded4_config = { | |||
568 | .demod_init = digitv_alps_tded4_demod_init, | 567 | .demod_init = digitv_alps_tded4_demod_init, |
569 | }; | 568 | }; |
570 | 569 | ||
571 | static int tdvs_tua6034_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) | ||
572 | { | ||
573 | struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv; | ||
574 | return lg_h06xf_pll_set(fe, card->i2c_adapter, params); | ||
575 | } | ||
576 | |||
577 | static struct lgdt330x_config tdvs_tua6034_config = { | 570 | static struct lgdt330x_config tdvs_tua6034_config = { |
578 | .demod_address = 0x0e, | 571 | .demod_address = 0x0e, |
579 | .demod_chip = LGDT3303, | 572 | .demod_chip = LGDT3303, |
@@ -616,7 +609,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) | |||
616 | lgdt330x_reset(card); | 609 | lgdt330x_reset(card); |
617 | card->fe = dvb_attach(lgdt330x_attach, &tdvs_tua6034_config, card->i2c_adapter); | 610 | card->fe = dvb_attach(lgdt330x_attach, &tdvs_tua6034_config, card->i2c_adapter); |
618 | if (card->fe != NULL) { | 611 | if (card->fe != NULL) { |
619 | card->fe->ops.tuner_ops.set_params = tdvs_tua6034_tuner_set_params; | 612 | dvb_attach(lgh06xf_attach, card->fe, card->i2c_adapter); |
620 | dprintk ("dvb_bt8xx: lgdt330x detected\n"); | 613 | dprintk ("dvb_bt8xx: lgdt330x detected\n"); |
621 | } | 614 | } |
622 | break; | 615 | break; |
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.h b/drivers/media/dvb/bt8xx/dvb-bt8xx.h index 4745a9017a19..e75f4173c059 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.h +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.h | |||
@@ -37,7 +37,7 @@ | |||
37 | #include "cx24110.h" | 37 | #include "cx24110.h" |
38 | #include "or51211.h" | 38 | #include "or51211.h" |
39 | #include "lgdt330x.h" | 39 | #include "lgdt330x.h" |
40 | #include "lg_h06xf.h" | 40 | #include "lgh06xf.h" |
41 | #include "zl10353.h" | 41 | #include "zl10353.h" |
42 | 42 | ||
43 | struct dvb_bt8xx_card { | 43 | struct dvb_bt8xx_card { |
diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c index 9123147e376f..d64b96cb0c46 100644 --- a/drivers/media/dvb/cinergyT2/cinergyT2.c +++ b/drivers/media/dvb/cinergyT2/cinergyT2.c | |||
@@ -746,6 +746,7 @@ static void cinergyt2_query_rc (struct work_struct *work) | |||
746 | dprintk(1, "rc_input_event=%d Up\n", cinergyt2->rc_input_event); | 746 | dprintk(1, "rc_input_event=%d Up\n", cinergyt2->rc_input_event); |
747 | input_report_key(cinergyt2->rc_input_dev, | 747 | input_report_key(cinergyt2->rc_input_dev, |
748 | cinergyt2->rc_input_event, 0); | 748 | cinergyt2->rc_input_event, 0); |
749 | input_sync(cinergyt2->rc_input_dev); | ||
749 | cinergyt2->rc_input_event = KEY_MAX; | 750 | cinergyt2->rc_input_event = KEY_MAX; |
750 | } | 751 | } |
751 | cinergyt2->rc_last_code = ~0; | 752 | cinergyt2->rc_last_code = ~0; |
@@ -783,6 +784,7 @@ static void cinergyt2_query_rc (struct work_struct *work) | |||
783 | dprintk(1, "rc_input_event=%d\n", cinergyt2->rc_input_event); | 784 | dprintk(1, "rc_input_event=%d\n", cinergyt2->rc_input_event); |
784 | input_report_key(cinergyt2->rc_input_dev, | 785 | input_report_key(cinergyt2->rc_input_dev, |
785 | cinergyt2->rc_input_event, 1); | 786 | cinergyt2->rc_input_event, 1); |
787 | input_sync(cinergyt2->rc_input_dev); | ||
786 | cinergyt2->rc_last_code = rc_events[n].value; | 788 | cinergyt2->rc_last_code = rc_events[n].value; |
787 | } | 789 | } |
788 | } | 790 | } |
@@ -798,8 +800,9 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2) | |||
798 | { | 800 | { |
799 | struct input_dev *input_dev; | 801 | struct input_dev *input_dev; |
800 | int i; | 802 | int i; |
803 | int err; | ||
801 | 804 | ||
802 | cinergyt2->rc_input_dev = input_dev = input_allocate_device(); | 805 | input_dev = input_allocate_device(); |
803 | if (!input_dev) | 806 | if (!input_dev) |
804 | return -ENOMEM; | 807 | return -ENOMEM; |
805 | 808 | ||
@@ -817,7 +820,13 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2) | |||
817 | input_dev->keycodesize = 0; | 820 | input_dev->keycodesize = 0; |
818 | input_dev->keycodemax = 0; | 821 | input_dev->keycodemax = 0; |
819 | 822 | ||
820 | input_register_device(cinergyt2->rc_input_dev); | 823 | err = input_register_device(input_dev); |
824 | if (err) { | ||
825 | input_free_device(input_dev); | ||
826 | return err; | ||
827 | } | ||
828 | |||
829 | cinergyt2->rc_input_dev = input_dev; | ||
821 | schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2); | 830 | schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2); |
822 | 831 | ||
823 | return 0; | 832 | return 0; |
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index a263b3f3c21d..ad52143602cd 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig | |||
@@ -69,6 +69,8 @@ config DVB_USB_DIBUSB_MC | |||
69 | config DVB_USB_DIB0700 | 69 | config DVB_USB_DIB0700 |
70 | tristate "DiBcom DiB0700 USB DVB devices (see help for supported devices)" | 70 | tristate "DiBcom DiB0700 USB DVB devices (see help for supported devices)" |
71 | depends on DVB_USB | 71 | depends on DVB_USB |
72 | select DVB_DIB7000P | ||
73 | select DVB_DIB7000M | ||
72 | select DVB_DIB3000MC | 74 | select DVB_DIB3000MC |
73 | select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE | 75 | select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE |
74 | help | 76 | help |
@@ -96,6 +98,7 @@ config DVB_USB_CXUSB | |||
96 | depends on DVB_USB | 98 | depends on DVB_USB |
97 | select DVB_CX22702 if !DVB_FE_CUSTOMISE | 99 | select DVB_CX22702 if !DVB_FE_CUSTOMISE |
98 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE | 100 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE |
101 | select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE | ||
99 | select DVB_MT352 if !DVB_FE_CUSTOMISE | 102 | select DVB_MT352 if !DVB_FE_CUSTOMISE |
100 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE | 103 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE |
101 | help | 104 | help |
@@ -157,6 +160,17 @@ config DVB_USB_NOVA_T_USB2 | |||
157 | help | 160 | help |
158 | Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver. | 161 | Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver. |
159 | 162 | ||
163 | config DVB_USB_TTUSB2 | ||
164 | tristate "Pinnacle 400e DVB-S USB2.0 support" | ||
165 | depends on DVB_USB | ||
166 | select DVB_TDA10086 if !DVB_FE_CUSTOMISE | ||
167 | select DVB_LNBP21 if !DVB_FE_CUSTOMISE | ||
168 | select DVB_TDA826X if !DVB_FE_CUSTOMISE | ||
169 | help | ||
170 | Say Y here to support the Pinnacle 400e DVB-S USB2.0 receiver. The | ||
171 | firmware protocol used by this module is similar to the one used by the | ||
172 | old ttusb-driver - that's why the module is called dvb-usb-ttusb2.ko. | ||
173 | |||
160 | config DVB_USB_DTT200U | 174 | config DVB_USB_DTT200U |
161 | tristate "WideView WT-200U and WT-220U (pen) DVB-T USB2.0 support (Yakumo/Hama/Typhoon/Yuan)" | 175 | tristate "WideView WT-200U and WT-220U (pen) DVB-T USB2.0 support (Yakumo/Hama/Typhoon/Yuan)" |
162 | depends on DVB_USB | 176 | depends on DVB_USB |
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile index e239107998e5..154d593bbb02 100644 --- a/drivers/media/dvb/dvb-usb/Makefile +++ b/drivers/media/dvb/dvb-usb/Makefile | |||
@@ -36,6 +36,9 @@ obj-$(CONFIG_DVB_USB_DIGITV) += dvb-usb-digitv.o | |||
36 | dvb-usb-cxusb-objs = cxusb.o | 36 | dvb-usb-cxusb-objs = cxusb.o |
37 | obj-$(CONFIG_DVB_USB_CXUSB) += dvb-usb-cxusb.o | 37 | obj-$(CONFIG_DVB_USB_CXUSB) += dvb-usb-cxusb.o |
38 | 38 | ||
39 | dvb-usb-ttusb2-objs = ttusb2.o | ||
40 | obj-$(CONFIG_DVB_USB_TTUSB2) += dvb-usb-ttusb2.o | ||
41 | |||
39 | dvb-usb-dib0700-objs = dib0700_core.o dib0700_devices.o | 42 | dvb-usb-dib0700-objs = dib0700_core.o dib0700_devices.o |
40 | obj-$(CONFIG_DVB_USB_DIB0700) += dvb-usb-dib0700.o | 43 | obj-$(CONFIG_DVB_USB_DIB0700) += dvb-usb-dib0700.o |
41 | 44 | ||
diff --git a/drivers/media/dvb/dvb-usb/a800.c b/drivers/media/dvb/dvb-usb/a800.c index 2ed3eb62d787..a6c5f19f680d 100644 --- a/drivers/media/dvb/dvb-usb/a800.c +++ b/drivers/media/dvb/dvb-usb/a800.c | |||
@@ -116,24 +116,24 @@ static struct dvb_usb_device_properties a800_properties = { | |||
116 | { | 116 | { |
117 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | 117 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, |
118 | .pid_filter_count = 32, | 118 | .pid_filter_count = 32, |
119 | .streaming_ctrl = dibusb2_0_streaming_ctrl, | 119 | .streaming_ctrl = dibusb2_0_streaming_ctrl, |
120 | .pid_filter = dibusb_pid_filter, | 120 | .pid_filter = dibusb_pid_filter, |
121 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, | 121 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, |
122 | 122 | ||
123 | .frontend_attach = dibusb_dib3000mc_frontend_attach, | 123 | .frontend_attach = dibusb_dib3000mc_frontend_attach, |
124 | .tuner_attach = dibusb_dib3000mc_tuner_attach, | 124 | .tuner_attach = dibusb_dib3000mc_tuner_attach, |
125 | 125 | ||
126 | /* parameter for the MPEG2-data transfer */ | 126 | /* parameter for the MPEG2-data transfer */ |
127 | .stream = { | 127 | .stream = { |
128 | .type = USB_BULK, | 128 | .type = USB_BULK, |
129 | .count = 7, | 129 | .count = 7, |
130 | .endpoint = 0x06, | 130 | .endpoint = 0x06, |
131 | .u = { | 131 | .u = { |
132 | .bulk = { | 132 | .bulk = { |
133 | .buffersize = 4096, | 133 | .buffersize = 4096, |
134 | } | 134 | } |
135 | } | 135 | } |
136 | }, | 136 | }, |
137 | 137 | ||
138 | .size_of_priv = sizeof(struct dibusb_state), | 138 | .size_of_priv = sizeof(struct dibusb_state), |
139 | }, | 139 | }, |
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index 43f39069ef34..15d12fce34df 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c | |||
@@ -14,12 +14,12 @@ | |||
14 | * TODO: Use the cx25840-driver for the analogue part | 14 | * TODO: Use the cx25840-driver for the analogue part |
15 | * | 15 | * |
16 | * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de) | 16 | * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de) |
17 | * Copyright (C) 2005 Michael Krufky (mkrufky@m1k.net) | 17 | * Copyright (C) 2006 Michael Krufky (mkrufky@linuxtv.org) |
18 | * Copyright (C) 2006 Chris Pascoe (c.pascoe@itee.uq.edu.au) | 18 | * Copyright (C) 2006 Chris Pascoe (c.pascoe@itee.uq.edu.au) |
19 | * | 19 | * |
20 | * This program is free software; you can redistribute it and/or modify it | 20 | * This program is free software; you can redistribute it and/or modify it |
21 | * under the terms of the GNU General Public License as published by the Free | 21 | * under the terms of the GNU General Public License as published by the Free |
22 | * Software Foundation, version 2. | 22 | * Software Foundation, version 2. |
23 | * | 23 | * |
24 | * see Documentation/dvb/README.dvb-usb for more information | 24 | * see Documentation/dvb/README.dvb-usb for more information |
25 | */ | 25 | */ |
@@ -27,29 +27,29 @@ | |||
27 | 27 | ||
28 | #include "cx22702.h" | 28 | #include "cx22702.h" |
29 | #include "lgdt330x.h" | 29 | #include "lgdt330x.h" |
30 | #include "lg_h06xf.h" | 30 | #include "lgh06xf.h" |
31 | #include "mt352.h" | 31 | #include "mt352.h" |
32 | #include "mt352_priv.h" | 32 | #include "mt352_priv.h" |
33 | #include "zl10353.h" | 33 | #include "zl10353.h" |
34 | 34 | ||
35 | /* debug */ | 35 | /* debug */ |
36 | int dvb_usb_cxusb_debug; | 36 | int dvb_usb_cxusb_debug; |
37 | module_param_named(debug,dvb_usb_cxusb_debug, int, 0644); | 37 | module_param_named(debug, dvb_usb_cxusb_debug, int, 0644); |
38 | MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS); | 38 | MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS); |
39 | 39 | ||
40 | static int cxusb_ctrl_msg(struct dvb_usb_device *d, | 40 | static int cxusb_ctrl_msg(struct dvb_usb_device *d, |
41 | u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen) | 41 | u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen) |
42 | { | 42 | { |
43 | int wo = (rbuf == NULL || rlen == 0); /* write-only */ | 43 | int wo = (rbuf == NULL || rlen == 0); /* write-only */ |
44 | u8 sndbuf[1+wlen]; | 44 | u8 sndbuf[1+wlen]; |
45 | memset(sndbuf,0,1+wlen); | 45 | memset(sndbuf, 0, 1+wlen); |
46 | 46 | ||
47 | sndbuf[0] = cmd; | 47 | sndbuf[0] = cmd; |
48 | memcpy(&sndbuf[1],wbuf,wlen); | 48 | memcpy(&sndbuf[1], wbuf, wlen); |
49 | if (wo) | 49 | if (wo) |
50 | dvb_usb_generic_write(d,sndbuf,1+wlen); | 50 | dvb_usb_generic_write(d, sndbuf, 1+wlen); |
51 | else | 51 | else |
52 | dvb_usb_generic_rw(d,sndbuf,1+wlen,rbuf,rlen,0); | 52 | dvb_usb_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen, 0); |
53 | 53 | ||
54 | return 0; | 54 | return 0; |
55 | } | 55 | } |
@@ -58,14 +58,14 @@ static int cxusb_ctrl_msg(struct dvb_usb_device *d, | |||
58 | static void cxusb_gpio_tuner(struct dvb_usb_device *d, int onoff) | 58 | static void cxusb_gpio_tuner(struct dvb_usb_device *d, int onoff) |
59 | { | 59 | { |
60 | struct cxusb_state *st = d->priv; | 60 | struct cxusb_state *st = d->priv; |
61 | u8 o[2],i; | 61 | u8 o[2], i; |
62 | 62 | ||
63 | if (st->gpio_write_state[GPIO_TUNER] == onoff) | 63 | if (st->gpio_write_state[GPIO_TUNER] == onoff) |
64 | return; | 64 | return; |
65 | 65 | ||
66 | o[0] = GPIO_TUNER; | 66 | o[0] = GPIO_TUNER; |
67 | o[1] = onoff; | 67 | o[1] = onoff; |
68 | cxusb_ctrl_msg(d,CMD_GPIO_WRITE,o,2,&i,1); | 68 | cxusb_ctrl_msg(d, CMD_GPIO_WRITE, o, 2, &i, 1); |
69 | 69 | ||
70 | if (i != 0x01) | 70 | if (i != 0x01) |
71 | deb_info("gpio_write failed.\n"); | 71 | deb_info("gpio_write failed.\n"); |
@@ -74,7 +74,8 @@ static void cxusb_gpio_tuner(struct dvb_usb_device *d, int onoff) | |||
74 | } | 74 | } |
75 | 75 | ||
76 | /* I2C */ | 76 | /* I2C */ |
77 | static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) | 77 | static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], |
78 | int num) | ||
78 | { | 79 | { |
79 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | 80 | struct dvb_usb_device *d = i2c_get_adapdata(adap); |
80 | int i; | 81 | int i; |
@@ -89,12 +90,12 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) | |||
89 | 90 | ||
90 | if (d->udev->descriptor.idVendor == USB_VID_MEDION) | 91 | if (d->udev->descriptor.idVendor == USB_VID_MEDION) |
91 | switch (msg[i].addr) { | 92 | switch (msg[i].addr) { |
92 | case 0x63: | 93 | case 0x63: |
93 | cxusb_gpio_tuner(d,0); | 94 | cxusb_gpio_tuner(d, 0); |
94 | break; | 95 | break; |
95 | default: | 96 | default: |
96 | cxusb_gpio_tuner(d,1); | 97 | cxusb_gpio_tuner(d, 1); |
97 | break; | 98 | break; |
98 | } | 99 | } |
99 | 100 | ||
100 | /* read request */ | 101 | /* read request */ |
@@ -103,26 +104,27 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) | |||
103 | obuf[0] = msg[i].len; | 104 | obuf[0] = msg[i].len; |
104 | obuf[1] = msg[i+1].len; | 105 | obuf[1] = msg[i+1].len; |
105 | obuf[2] = msg[i].addr; | 106 | obuf[2] = msg[i].addr; |
106 | memcpy(&obuf[3],msg[i].buf,msg[i].len); | 107 | memcpy(&obuf[3], msg[i].buf, msg[i].len); |
107 | 108 | ||
108 | if (cxusb_ctrl_msg(d, CMD_I2C_READ, | 109 | if (cxusb_ctrl_msg(d, CMD_I2C_READ, |
109 | obuf, 3+msg[i].len, | 110 | obuf, 3+msg[i].len, |
110 | ibuf, 1+msg[i+1].len) < 0) | 111 | ibuf, 1+msg[i+1].len) < 0) |
111 | break; | 112 | break; |
112 | 113 | ||
113 | if (ibuf[0] != 0x08) | 114 | if (ibuf[0] != 0x08) |
114 | deb_i2c("i2c read may have failed\n"); | 115 | deb_i2c("i2c read may have failed\n"); |
115 | 116 | ||
116 | memcpy(msg[i+1].buf,&ibuf[1],msg[i+1].len); | 117 | memcpy(msg[i+1].buf, &ibuf[1], msg[i+1].len); |
117 | 118 | ||
118 | i++; | 119 | i++; |
119 | } else { /* write */ | 120 | } else { /* write */ |
120 | u8 obuf[2+msg[i].len], ibuf; | 121 | u8 obuf[2+msg[i].len], ibuf; |
121 | obuf[0] = msg[i].addr; | 122 | obuf[0] = msg[i].addr; |
122 | obuf[1] = msg[i].len; | 123 | obuf[1] = msg[i].len; |
123 | memcpy(&obuf[2],msg[i].buf,msg[i].len); | 124 | memcpy(&obuf[2], msg[i].buf, msg[i].len); |
124 | 125 | ||
125 | if (cxusb_ctrl_msg(d,CMD_I2C_WRITE, obuf, 2+msg[i].len, &ibuf,1) < 0) | 126 | if (cxusb_ctrl_msg(d, CMD_I2C_WRITE, obuf, |
127 | 2+msg[i].len, &ibuf,1) < 0) | ||
126 | break; | 128 | break; |
127 | if (ibuf != 0x08) | 129 | if (ibuf != 0x08) |
128 | deb_i2c("i2c write may have failed\n"); | 130 | deb_i2c("i2c write may have failed\n"); |
@@ -324,16 +326,8 @@ static int cxusb_mt352_demod_init(struct dvb_frontend* fe) | |||
324 | return 0; | 326 | return 0; |
325 | } | 327 | } |
326 | 328 | ||
327 | static int cxusb_lgh064f_tuner_set_params(struct dvb_frontend *fe, | ||
328 | struct dvb_frontend_parameters *fep) | ||
329 | { | ||
330 | struct dvb_usb_adapter *adap = fe->dvb->priv; | ||
331 | return lg_h06xf_pll_set(fe, &adap->dev->i2c_adap, fep); | ||
332 | } | ||
333 | |||
334 | static struct cx22702_config cxusb_cx22702_config = { | 329 | static struct cx22702_config cxusb_cx22702_config = { |
335 | .demod_address = 0x63, | 330 | .demod_address = 0x63, |
336 | |||
337 | .output_mode = CX22702_PARALLEL_OUTPUT, | 331 | .output_mode = CX22702_PARALLEL_OUTPUT, |
338 | }; | 332 | }; |
339 | 333 | ||
@@ -374,31 +368,27 @@ static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap) | |||
374 | 368 | ||
375 | static int cxusb_dee1601_tuner_attach(struct dvb_usb_adapter *adap) | 369 | static int cxusb_dee1601_tuner_attach(struct dvb_usb_adapter *adap) |
376 | { | 370 | { |
377 | adap->pll_addr = 0x61; | 371 | dvb_attach(dvb_pll_attach, adap->fe, 0x61, |
378 | adap->pll_desc = &dvb_pll_thomson_dtt7579; | 372 | NULL, &dvb_pll_thomson_dtt7579); |
379 | adap->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs; | ||
380 | return 0; | 373 | return 0; |
381 | } | 374 | } |
382 | 375 | ||
383 | static int cxusb_lgz201_tuner_attach(struct dvb_usb_adapter *adap) | 376 | static int cxusb_lgz201_tuner_attach(struct dvb_usb_adapter *adap) |
384 | { | 377 | { |
385 | adap->pll_addr = 0x61; | 378 | dvb_attach(dvb_pll_attach, adap->fe, 0x61, NULL, &dvb_pll_lg_z201); |
386 | adap->pll_desc = &dvb_pll_lg_z201; | ||
387 | adap->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs; | ||
388 | return 0; | 379 | return 0; |
389 | } | 380 | } |
390 | 381 | ||
391 | static int cxusb_dtt7579_tuner_attach(struct dvb_usb_adapter *adap) | 382 | static int cxusb_dtt7579_tuner_attach(struct dvb_usb_adapter *adap) |
392 | { | 383 | { |
393 | adap->pll_addr = 0x60; | 384 | dvb_attach(dvb_pll_attach, adap->fe, 0x60, |
394 | adap->pll_desc = &dvb_pll_thomson_dtt7579; | 385 | NULL, &dvb_pll_thomson_dtt7579); |
395 | adap->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs; | ||
396 | return 0; | 386 | return 0; |
397 | } | 387 | } |
398 | 388 | ||
399 | static int cxusb_lgdt3303_tuner_attach(struct dvb_usb_adapter *adap) | 389 | static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap) |
400 | { | 390 | { |
401 | adap->fe->ops.tuner_ops.set_params = cxusb_lgh064f_tuner_set_params; | 391 | dvb_attach(lgh06xf_attach, adap->fe, &adap->dev->i2c_adap); |
402 | return 0; | 392 | return 0; |
403 | } | 393 | } |
404 | 394 | ||
@@ -410,7 +400,8 @@ static int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap) | |||
410 | 400 | ||
411 | cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, &b, 1); | 401 | cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, &b, 1); |
412 | 402 | ||
413 | if ((adap->fe = dvb_attach(cx22702_attach, &cxusb_cx22702_config, &adap->dev->i2c_adap)) != NULL) | 403 | if ((adap->fe = dvb_attach(cx22702_attach, &cxusb_cx22702_config, |
404 | &adap->dev->i2c_adap)) != NULL) | ||
414 | return 0; | 405 | return 0; |
415 | 406 | ||
416 | return -EIO; | 407 | return -EIO; |
@@ -423,7 +414,8 @@ static int cxusb_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap) | |||
423 | 414 | ||
424 | cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); | 415 | cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); |
425 | 416 | ||
426 | if ((adap->fe = dvb_attach(lgdt330x_attach, &cxusb_lgdt3303_config, &adap->dev->i2c_adap)) != NULL) | 417 | if ((adap->fe = dvb_attach(lgdt330x_attach, &cxusb_lgdt3303_config, |
418 | &adap->dev->i2c_adap)) != NULL) | ||
427 | return 0; | 419 | return 0; |
428 | 420 | ||
429 | return -EIO; | 421 | return -EIO; |
@@ -437,7 +429,8 @@ static int cxusb_mt352_frontend_attach(struct dvb_usb_adapter *adap) | |||
437 | 429 | ||
438 | cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); | 430 | cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); |
439 | 431 | ||
440 | if ((adap->fe = dvb_attach(mt352_attach, &cxusb_mt352_config, &adap->dev->i2c_adap)) != NULL) | 432 | if ((adap->fe = dvb_attach(mt352_attach, &cxusb_mt352_config, |
433 | &adap->dev->i2c_adap)) != NULL) | ||
441 | return 0; | 434 | return 0; |
442 | 435 | ||
443 | return -EIO; | 436 | return -EIO; |
@@ -450,8 +443,11 @@ static int cxusb_dee1601_frontend_attach(struct dvb_usb_adapter *adap) | |||
450 | 443 | ||
451 | cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); | 444 | cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); |
452 | 445 | ||
453 | if (((adap->fe = dvb_attach(mt352_attach, &cxusb_dee1601_config, &adap->dev->i2c_adap)) != NULL) || | 446 | if (((adap->fe = dvb_attach(mt352_attach, &cxusb_dee1601_config, |
454 | ((adap->fe = dvb_attach(zl10353_attach, &cxusb_zl10353_dee1601_config, &adap->dev->i2c_adap)) != NULL)) | 447 | &adap->dev->i2c_adap)) != NULL) || |
448 | ((adap->fe = dvb_attach(zl10353_attach, | ||
449 | &cxusb_zl10353_dee1601_config, | ||
450 | &adap->dev->i2c_adap)) != NULL)) | ||
455 | return 0; | 451 | return 0; |
456 | 452 | ||
457 | return -EIO; | 453 | return -EIO; |
@@ -463,7 +459,8 @@ static int cxusb_dee1601_frontend_attach(struct dvb_usb_adapter *adap) | |||
463 | */ | 459 | */ |
464 | 460 | ||
465 | #define BLUEBIRD_01_ID_OFFSET 6638 | 461 | #define BLUEBIRD_01_ID_OFFSET 6638 |
466 | static int bluebird_patch_dvico_firmware_download(struct usb_device *udev, const struct firmware *fw) | 462 | static int bluebird_patch_dvico_firmware_download(struct usb_device *udev, |
463 | const struct firmware *fw) | ||
467 | { | 464 | { |
468 | if (fw->size < BLUEBIRD_01_ID_OFFSET + 4) | 465 | if (fw->size < BLUEBIRD_01_ID_OFFSET + 4) |
469 | return -EINVAL; | 466 | return -EINVAL; |
@@ -471,10 +468,12 @@ static int bluebird_patch_dvico_firmware_download(struct usb_device *udev, const | |||
471 | if (fw->data[BLUEBIRD_01_ID_OFFSET] == (USB_VID_DVICO & 0xff) && | 468 | if (fw->data[BLUEBIRD_01_ID_OFFSET] == (USB_VID_DVICO & 0xff) && |
472 | fw->data[BLUEBIRD_01_ID_OFFSET + 1] == USB_VID_DVICO >> 8) { | 469 | fw->data[BLUEBIRD_01_ID_OFFSET + 1] == USB_VID_DVICO >> 8) { |
473 | 470 | ||
474 | fw->data[BLUEBIRD_01_ID_OFFSET + 2] = udev->descriptor.idProduct + 1; | 471 | fw->data[BLUEBIRD_01_ID_OFFSET + 2] = |
475 | fw->data[BLUEBIRD_01_ID_OFFSET + 3] = udev->descriptor.idProduct >> 8; | 472 | udev->descriptor.idProduct + 1; |
473 | fw->data[BLUEBIRD_01_ID_OFFSET + 3] = | ||
474 | udev->descriptor.idProduct >> 8; | ||
476 | 475 | ||
477 | return usb_cypress_load_firmware(udev,fw,CYPRESS_FX2); | 476 | return usb_cypress_load_firmware(udev, fw, CYPRESS_FX2); |
478 | } | 477 | } |
479 | 478 | ||
480 | return -EINVAL; | 479 | return -EINVAL; |
@@ -488,7 +487,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties; | |||
488 | static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties; | 487 | static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties; |
489 | 488 | ||
490 | static int cxusb_probe(struct usb_interface *intf, | 489 | static int cxusb_probe(struct usb_interface *intf, |
491 | const struct usb_device_id *id) | 490 | const struct usb_device_id *id) |
492 | { | 491 | { |
493 | if (dvb_usb_device_init(intf,&cxusb_medion_properties,THIS_MODULE,NULL) == 0 || | 492 | if (dvb_usb_device_init(intf,&cxusb_medion_properties,THIS_MODULE,NULL) == 0 || |
494 | dvb_usb_device_init(intf,&cxusb_bluebird_lgh064f_properties,THIS_MODULE,NULL) == 0 || | 493 | dvb_usb_device_init(intf,&cxusb_bluebird_lgh064f_properties,THIS_MODULE,NULL) == 0 || |
@@ -502,20 +501,20 @@ static int cxusb_probe(struct usb_interface *intf, | |||
502 | } | 501 | } |
503 | 502 | ||
504 | static struct usb_device_id cxusb_table [] = { | 503 | static struct usb_device_id cxusb_table [] = { |
505 | { USB_DEVICE(USB_VID_MEDION, USB_PID_MEDION_MD95700) }, | 504 | { USB_DEVICE(USB_VID_MEDION, USB_PID_MEDION_MD95700) }, |
506 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_COLD) }, | 505 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_COLD) }, |
507 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_WARM) }, | 506 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_WARM) }, |
508 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_COLD) }, | 507 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_COLD) }, |
509 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM) }, | 508 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM) }, |
510 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_COLD) }, | 509 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_COLD) }, |
511 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_WARM) }, | 510 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_WARM) }, |
512 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_COLD) }, | 511 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_COLD) }, |
513 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_WARM) }, | 512 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_WARM) }, |
514 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD) }, | 513 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD) }, |
515 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM) }, | 514 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM) }, |
516 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD) }, | 515 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD) }, |
517 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM) }, | 516 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM) }, |
518 | {} /* Terminating entry */ | 517 | {} /* Terminating entry */ |
519 | }; | 518 | }; |
520 | MODULE_DEVICE_TABLE (usb, cxusb_table); | 519 | MODULE_DEVICE_TABLE (usb, cxusb_table); |
521 | 520 | ||
@@ -529,20 +528,20 @@ static struct dvb_usb_device_properties cxusb_medion_properties = { | |||
529 | .num_adapters = 1, | 528 | .num_adapters = 1, |
530 | .adapter = { | 529 | .adapter = { |
531 | { | 530 | { |
532 | .streaming_ctrl = cxusb_streaming_ctrl, | 531 | .streaming_ctrl = cxusb_streaming_ctrl, |
533 | .frontend_attach = cxusb_cx22702_frontend_attach, | 532 | .frontend_attach = cxusb_cx22702_frontend_attach, |
534 | .tuner_attach = cxusb_fmd1216me_tuner_attach, | 533 | .tuner_attach = cxusb_fmd1216me_tuner_attach, |
535 | /* parameter for the MPEG2-data transfer */ | 534 | /* parameter for the MPEG2-data transfer */ |
536 | .stream = { | 535 | .stream = { |
537 | .type = USB_BULK, | 536 | .type = USB_BULK, |
538 | .count = 5, | 537 | .count = 5, |
539 | .endpoint = 0x02, | 538 | .endpoint = 0x02, |
540 | .u = { | 539 | .u = { |
541 | .bulk = { | 540 | .bulk = { |
542 | .buffersize = 8192, | 541 | .buffersize = 8192, |
543 | } | 542 | } |
544 | } | 543 | } |
545 | }, | 544 | }, |
546 | 545 | ||
547 | }, | 546 | }, |
548 | }, | 547 | }, |
@@ -575,21 +574,21 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties = { | |||
575 | .num_adapters = 1, | 574 | .num_adapters = 1, |
576 | .adapter = { | 575 | .adapter = { |
577 | { | 576 | { |
578 | .streaming_ctrl = cxusb_streaming_ctrl, | 577 | .streaming_ctrl = cxusb_streaming_ctrl, |
579 | .frontend_attach = cxusb_lgdt3303_frontend_attach, | 578 | .frontend_attach = cxusb_lgdt3303_frontend_attach, |
580 | .tuner_attach = cxusb_lgdt3303_tuner_attach, | 579 | .tuner_attach = cxusb_lgh064f_tuner_attach, |
581 | 580 | ||
582 | /* parameter for the MPEG2-data transfer */ | 581 | /* parameter for the MPEG2-data transfer */ |
583 | .stream = { | 582 | .stream = { |
584 | .type = USB_BULK, | 583 | .type = USB_BULK, |
585 | .count = 5, | 584 | .count = 5, |
586 | .endpoint = 0x02, | 585 | .endpoint = 0x02, |
587 | .u = { | 586 | .u = { |
588 | .bulk = { | 587 | .bulk = { |
589 | .buffersize = 8192, | 588 | .buffersize = 8192, |
590 | } | 589 | } |
591 | } | 590 | } |
592 | }, | 591 | }, |
593 | }, | 592 | }, |
594 | }, | 593 | }, |
595 | 594 | ||
@@ -627,20 +626,20 @@ static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties = { | |||
627 | .num_adapters = 1, | 626 | .num_adapters = 1, |
628 | .adapter = { | 627 | .adapter = { |
629 | { | 628 | { |
630 | .streaming_ctrl = cxusb_streaming_ctrl, | 629 | .streaming_ctrl = cxusb_streaming_ctrl, |
631 | .frontend_attach = cxusb_dee1601_frontend_attach, | 630 | .frontend_attach = cxusb_dee1601_frontend_attach, |
632 | .tuner_attach = cxusb_dee1601_tuner_attach, | 631 | .tuner_attach = cxusb_dee1601_tuner_attach, |
633 | /* parameter for the MPEG2-data transfer */ | 632 | /* parameter for the MPEG2-data transfer */ |
634 | .stream = { | 633 | .stream = { |
635 | .type = USB_BULK, | 634 | .type = USB_BULK, |
636 | .count = 5, | 635 | .count = 5, |
637 | .endpoint = 0x04, | 636 | .endpoint = 0x04, |
638 | .u = { | 637 | .u = { |
639 | .bulk = { | 638 | .bulk = { |
640 | .buffersize = 8192, | 639 | .buffersize = 8192, |
641 | } | 640 | } |
642 | } | 641 | } |
643 | }, | 642 | }, |
644 | }, | 643 | }, |
645 | }, | 644 | }, |
646 | 645 | ||
@@ -686,21 +685,21 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties = { | |||
686 | .num_adapters = 2, | 685 | .num_adapters = 2, |
687 | .adapter = { | 686 | .adapter = { |
688 | { | 687 | { |
689 | .streaming_ctrl = cxusb_streaming_ctrl, | 688 | .streaming_ctrl = cxusb_streaming_ctrl, |
690 | .frontend_attach = cxusb_mt352_frontend_attach, | 689 | .frontend_attach = cxusb_mt352_frontend_attach, |
691 | .tuner_attach = cxusb_lgz201_tuner_attach, | 690 | .tuner_attach = cxusb_lgz201_tuner_attach, |
692 | 691 | ||
693 | /* parameter for the MPEG2-data transfer */ | 692 | /* parameter for the MPEG2-data transfer */ |
694 | .stream = { | 693 | .stream = { |
695 | .type = USB_BULK, | 694 | .type = USB_BULK, |
696 | .count = 5, | 695 | .count = 5, |
697 | .endpoint = 0x04, | 696 | .endpoint = 0x04, |
698 | .u = { | 697 | .u = { |
699 | .bulk = { | 698 | .bulk = { |
700 | .buffersize = 8192, | 699 | .buffersize = 8192, |
701 | } | 700 | } |
702 | } | 701 | } |
703 | }, | 702 | }, |
704 | }, | 703 | }, |
705 | }, | 704 | }, |
706 | .power_ctrl = cxusb_bluebird_power_ctrl, | 705 | .power_ctrl = cxusb_bluebird_power_ctrl, |
@@ -736,21 +735,21 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = { | |||
736 | .num_adapters = 1, | 735 | .num_adapters = 1, |
737 | .adapter = { | 736 | .adapter = { |
738 | { | 737 | { |
739 | .streaming_ctrl = cxusb_streaming_ctrl, | 738 | .streaming_ctrl = cxusb_streaming_ctrl, |
740 | .frontend_attach = cxusb_mt352_frontend_attach, | 739 | .frontend_attach = cxusb_mt352_frontend_attach, |
741 | .tuner_attach = cxusb_dtt7579_tuner_attach, | 740 | .tuner_attach = cxusb_dtt7579_tuner_attach, |
742 | 741 | ||
743 | /* parameter for the MPEG2-data transfer */ | 742 | /* parameter for the MPEG2-data transfer */ |
744 | .stream = { | 743 | .stream = { |
745 | .type = USB_BULK, | 744 | .type = USB_BULK, |
746 | .count = 5, | 745 | .count = 5, |
747 | .endpoint = 0x04, | 746 | .endpoint = 0x04, |
748 | .u = { | 747 | .u = { |
749 | .bulk = { | 748 | .bulk = { |
750 | .buffersize = 8192, | 749 | .buffersize = 8192, |
751 | } | 750 | } |
752 | } | 751 | } |
753 | }, | 752 | }, |
754 | }, | 753 | }, |
755 | }, | 754 | }, |
756 | .power_ctrl = cxusb_bluebird_power_ctrl, | 755 | .power_ctrl = cxusb_bluebird_power_ctrl, |
@@ -776,7 +775,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = { | |||
776 | static struct usb_driver cxusb_driver = { | 775 | static struct usb_driver cxusb_driver = { |
777 | .name = "dvb_usb_cxusb", | 776 | .name = "dvb_usb_cxusb", |
778 | .probe = cxusb_probe, | 777 | .probe = cxusb_probe, |
779 | .disconnect = dvb_usb_device_exit, | 778 | .disconnect = dvb_usb_device_exit, |
780 | .id_table = cxusb_table, | 779 | .id_table = cxusb_table, |
781 | }; | 780 | }; |
782 | 781 | ||
@@ -802,7 +801,7 @@ module_init (cxusb_module_init); | |||
802 | module_exit (cxusb_module_exit); | 801 | module_exit (cxusb_module_exit); |
803 | 802 | ||
804 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | 803 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); |
805 | MODULE_AUTHOR("Michael Krufky <mkrufky@m1k.net>"); | 804 | MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>"); |
806 | MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>"); | 805 | MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>"); |
807 | MODULE_DESCRIPTION("Driver for Conexant USB2.0 hybrid reference design"); | 806 | MODULE_DESCRIPTION("Driver for Conexant USB2.0 hybrid reference design"); |
808 | MODULE_VERSION("1.0-alpha"); | 807 | MODULE_VERSION("1.0-alpha"); |
diff --git a/drivers/media/dvb/dvb-usb/dib0700.h b/drivers/media/dvb/dvb-usb/dib0700.h index ac84347f9d4c..cda3adea24fb 100644 --- a/drivers/media/dvb/dvb-usb/dib0700.h +++ b/drivers/media/dvb/dvb-usb/dib0700.h | |||
@@ -24,18 +24,23 @@ extern int dvb_usb_dib0700_debug; | |||
24 | #define REQUEST_I2C_WRITE 0x3 | 24 | #define REQUEST_I2C_WRITE 0x3 |
25 | #define REQUEST_POLL_RC 0x4 | 25 | #define REQUEST_POLL_RC 0x4 |
26 | #define REQUEST_JUMPRAM 0x8 | 26 | #define REQUEST_JUMPRAM 0x8 |
27 | #define REQUEST_SET_CLOCK 0xB | ||
27 | #define REQUEST_SET_GPIO 0xC | 28 | #define REQUEST_SET_GPIO 0xC |
28 | #define REQUEST_ENABLE_VIDEO 0xF | 29 | #define REQUEST_ENABLE_VIDEO 0xF |
29 | // 1 Byte: 4MSB(1 = enable streaming, 0 = disable streaming) 4LSB(Video Mode: 0 = MPEG2 188Bytes, 1 = Analog) | 30 | // 1 Byte: 4MSB(1 = enable streaming, 0 = disable streaming) 4LSB(Video Mode: 0 = MPEG2 188Bytes, 1 = Analog) |
30 | // 2 Byte: MPEG2 mode: 4MSB(1 = Master Mode, 0 = Slave Mode) 4LSB(Channel 1 = bit0, Channel 2 = bit1) | 31 | // 2 Byte: MPEG2 mode: 4MSB(1 = Master Mode, 0 = Slave Mode) 4LSB(Channel 1 = bit0, Channel 2 = bit1) |
31 | // 2 Byte: Analog mode: 4MSB(0 = 625 lines, 1 = 525 lines) 4LSB( " " ) | 32 | // 2 Byte: Analog mode: 4MSB(0 = 625 lines, 1 = 525 lines) 4LSB( " " ) |
33 | #define REQUEST_GET_VERSION 0x15 | ||
32 | 34 | ||
33 | struct dib0700_state { | 35 | struct dib0700_state { |
34 | u8 channel_state; | 36 | u8 channel_state; |
35 | u16 mt2060_if1[2]; | 37 | u16 mt2060_if1[2]; |
38 | |||
39 | u8 is_dib7000pc; | ||
36 | }; | 40 | }; |
37 | 41 | ||
38 | extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val); | 42 | extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val); |
43 | extern int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3); | ||
39 | extern int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw); | 44 | extern int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw); |
40 | extern int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff); | 45 | extern int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff); |
41 | extern struct i2c_algorithm dib0700_i2c_algo; | 46 | extern struct i2c_algorithm dib0700_i2c_algo; |
diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c index dca6c6985661..6a4d150784a6 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_core.c +++ b/drivers/media/dvb/dvb-usb/dib0700_core.c | |||
@@ -135,14 +135,46 @@ struct i2c_algorithm dib0700_i2c_algo = { | |||
135 | int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props, | 135 | int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props, |
136 | struct dvb_usb_device_description **desc, int *cold) | 136 | struct dvb_usb_device_description **desc, int *cold) |
137 | { | 137 | { |
138 | u8 buf[3] = { REQUEST_SET_GPIO, 4, (GPIO_IN << 7) | (0 << 6) }; // GPIO4 is save - used for I2C | 138 | u8 b[16]; |
139 | *cold = usb_control_msg(udev, usb_sndctrlpipe(udev,0), | 139 | s16 ret = usb_control_msg(udev, usb_rcvctrlpipe(udev,0), |
140 | buf[0], USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0, buf, 3, USB_CTRL_GET_TIMEOUT) != 3; | 140 | REQUEST_GET_VERSION, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, b, 16, USB_CTRL_GET_TIMEOUT); |
141 | |||
142 | deb_info("FW GET_VERSION length: %d\n",ret); | ||
143 | |||
144 | *cold = ret <= 0; | ||
141 | 145 | ||
142 | deb_info("cold: %d\n", *cold); | 146 | deb_info("cold: %d\n", *cold); |
143 | return 0; | 147 | return 0; |
144 | } | 148 | } |
145 | 149 | ||
150 | static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll, | ||
151 | u8 pll_src, u8 pll_range, u8 clock_gpio3, u16 pll_prediv, | ||
152 | u16 pll_loopdiv, u16 free_div, u16 dsuScaler) | ||
153 | { | ||
154 | u8 b[10]; | ||
155 | b[0] = REQUEST_SET_CLOCK; | ||
156 | b[1] = (en_pll << 7) | (pll_src << 6) | (pll_range << 5) | (clock_gpio3 << 4); | ||
157 | b[2] = (pll_prediv >> 8) & 0xff; // MSB | ||
158 | b[3] = pll_prediv & 0xff; // LSB | ||
159 | b[4] = (pll_loopdiv >> 8) & 0xff; // MSB | ||
160 | b[5] = pll_loopdiv & 0xff; // LSB | ||
161 | b[6] = (free_div >> 8) & 0xff; // MSB | ||
162 | b[7] = free_div & 0xff; // LSB | ||
163 | b[8] = (dsuScaler >> 8) & 0xff; // MSB | ||
164 | b[9] = dsuScaler & 0xff; // LSB | ||
165 | |||
166 | return dib0700_ctrl_wr(d, b, 10); | ||
167 | } | ||
168 | |||
169 | int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3) | ||
170 | { | ||
171 | switch (clk_MHz) { | ||
172 | case 72: dib0700_set_clock(d, 1, 0, 1, clock_out_gp3, 2, 24, 0, 0x4c); break; | ||
173 | default: return -EINVAL; | ||
174 | } | ||
175 | return 0; | ||
176 | } | ||
177 | |||
146 | static int dib0700_jumpram(struct usb_device *udev, u32 address) | 178 | static int dib0700_jumpram(struct usb_device *udev, u32 address) |
147 | { | 179 | { |
148 | int ret, actlen; | 180 | int ret, actlen; |
@@ -197,7 +229,7 @@ int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw | |||
197 | /* start the firmware */ | 229 | /* start the firmware */ |
198 | if ((ret = dib0700_jumpram(udev, 0x70000000)) == 0) { | 230 | if ((ret = dib0700_jumpram(udev, 0x70000000)) == 0) { |
199 | info("firmware started successfully."); | 231 | info("firmware started successfully."); |
200 | msleep(100); | 232 | msleep(500); |
201 | } | 233 | } |
202 | } else | 234 | } else |
203 | ret = -EIO; | 235 | ret = -EIO; |
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index e473bfed226b..2208757d9017 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c | |||
@@ -9,6 +9,8 @@ | |||
9 | #include "dib0700.h" | 9 | #include "dib0700.h" |
10 | 10 | ||
11 | #include "dib3000mc.h" | 11 | #include "dib3000mc.h" |
12 | #include "dib7000m.h" | ||
13 | #include "dib7000p.h" | ||
12 | #include "mt2060.h" | 14 | #include "mt2060.h" |
13 | 15 | ||
14 | static int force_lna_activation; | 16 | static int force_lna_activation; |
@@ -95,37 +97,189 @@ static int bristol_tuner_attach(struct dvb_usb_adapter *adap) | |||
95 | } | 97 | } |
96 | 98 | ||
97 | /* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */ | 99 | /* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */ |
98 | /* | 100 | static struct dibx000_agc_config stk7700p_7000m_mt2060_agc_config = { |
99 | static struct mt2060_config stk7000p_mt2060_config = { | 101 | BAND_UHF | BAND_VHF, // band_caps |
100 | 0x60 | 102 | |
103 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, | ||
104 | * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */ | ||
105 | (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup | ||
106 | |||
107 | 712, // inv_gain | ||
108 | 41, // time_stabiliz | ||
109 | |||
110 | 0, // alpha_level | ||
111 | 118, // thlock | ||
112 | |||
113 | 0, // wbd_inv | ||
114 | 4095, // wbd_ref | ||
115 | 0, // wbd_sel | ||
116 | 0, // wbd_alpha | ||
117 | |||
118 | 42598, // agc1_max | ||
119 | 17694, // agc1_min | ||
120 | 45875, // agc2_max | ||
121 | 2621, // agc2_min | ||
122 | 0, // agc1_pt1 | ||
123 | 76, // agc1_pt2 | ||
124 | 139, // agc1_pt3 | ||
125 | 52, // agc1_slope1 | ||
126 | 59, // agc1_slope2 | ||
127 | 107, // agc2_pt1 | ||
128 | 172, // agc2_pt2 | ||
129 | 57, // agc2_slope1 | ||
130 | 70, // agc2_slope2 | ||
131 | |||
132 | 21, // alpha_mant | ||
133 | 25, // alpha_exp | ||
134 | 28, // beta_mant | ||
135 | 48, // beta_exp | ||
136 | |||
137 | 1, // perform_agc_softsplit | ||
138 | { 0, // split_min | ||
139 | 107, // split_max | ||
140 | 51800, // global_split_min | ||
141 | 24700 // global_split_max | ||
142 | }, | ||
143 | }; | ||
144 | |||
145 | static struct dibx000_agc_config stk7700p_7000p_mt2060_agc_config = { | ||
146 | BAND_UHF | BAND_VHF, | ||
147 | |||
148 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, | ||
149 | * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */ | ||
150 | (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup | ||
151 | |||
152 | 712, // inv_gain | ||
153 | 41, // time_stabiliz | ||
154 | |||
155 | 0, // alpha_level | ||
156 | 118, // thlock | ||
157 | |||
158 | 0, // wbd_inv | ||
159 | 4095, // wbd_ref | ||
160 | 0, // wbd_sel | ||
161 | 0, // wbd_alpha | ||
162 | |||
163 | 42598, // agc1_max | ||
164 | 16384, // agc1_min | ||
165 | 42598, // agc2_max | ||
166 | 0, // agc2_min | ||
167 | |||
168 | 0, // agc1_pt1 | ||
169 | 137, // agc1_pt2 | ||
170 | 255, // agc1_pt3 | ||
171 | |||
172 | 0, // agc1_slope1 | ||
173 | 255, // agc1_slope2 | ||
174 | |||
175 | 0, // agc2_pt1 | ||
176 | 0, // agc2_pt2 | ||
177 | |||
178 | 0, // agc2_slope1 | ||
179 | 41, // agc2_slope2 | ||
180 | |||
181 | 15, // alpha_mant | ||
182 | 25, // alpha_exp | ||
183 | |||
184 | 28, // beta_mant | ||
185 | 48, // beta_exp | ||
186 | |||
187 | 0, // perform_agc_softsplit | ||
188 | }; | ||
189 | |||
190 | static struct dibx000_bandwidth_config stk7700p_pll_config = { | ||
191 | 60000, 30000, // internal, sampling | ||
192 | 1, 8, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass | ||
193 | 0, 0, 1, 1, 0, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo | ||
194 | (3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k | ||
195 | 60258167, // ifreq | ||
196 | 20452225, // timf | ||
197 | }; | ||
198 | |||
199 | static struct dib7000m_config stk7700p_dib7000m_config = { | ||
200 | .dvbt_mode = 1, | ||
201 | .output_mpeg2_in_188_bytes = 1, | ||
202 | .quartz_direct = 1, | ||
203 | |||
204 | .agc_config_count = 1, | ||
205 | .agc = &stk7700p_7000m_mt2060_agc_config, | ||
206 | .bw = &stk7700p_pll_config, | ||
207 | |||
208 | .gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS, | ||
209 | .gpio_val = DIB7000M_GPIO_DEFAULT_VALUES, | ||
210 | .gpio_pwm_pos = DIB7000M_GPIO_DEFAULT_PWM_POS, | ||
211 | }; | ||
212 | |||
213 | static struct dib7000p_config stk7700p_dib7000p_config = { | ||
214 | .output_mpeg2_in_188_bytes = 1, | ||
215 | |||
216 | .agc = &stk7700p_7000p_mt2060_agc_config, | ||
217 | .bw = &stk7700p_pll_config, | ||
218 | |||
219 | .gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS, | ||
220 | .gpio_val = DIB7000M_GPIO_DEFAULT_VALUES, | ||
221 | .gpio_pwm_pos = DIB7000M_GPIO_DEFAULT_PWM_POS, | ||
101 | }; | 222 | }; |
102 | */ | ||
103 | 223 | ||
104 | static int stk7700p_frontend_attach(struct dvb_usb_adapter *adap) | 224 | static int stk7700p_frontend_attach(struct dvb_usb_adapter *adap) |
105 | { | 225 | { |
226 | struct dib0700_state *st = adap->dev->priv; | ||
106 | /* unless there is no real power management in DVB - we leave the device on GPIO6 */ | 227 | /* unless there is no real power management in DVB - we leave the device on GPIO6 */ |
107 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); msleep(10); | 228 | |
108 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); msleep(10); | 229 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); |
109 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); msleep(10); | 230 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); msleep(50); |
231 | |||
232 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); msleep(10); | ||
233 | dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); | ||
234 | |||
110 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); msleep(10); | 235 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); msleep(10); |
236 | dib0700_ctrl_clock(adap->dev, 72, 1); | ||
237 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); msleep(100); | ||
238 | |||
239 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | ||
240 | |||
241 | st->mt2060_if1[0] = 1220; | ||
242 | |||
243 | if (dib7000pc_detection(&adap->dev->i2c_adap)) { | ||
244 | adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000p_config); | ||
245 | st->is_dib7000pc = 1; | ||
246 | } else | ||
247 | adap->fe = dvb_attach(dib7000m_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000m_config); | ||
111 | 248 | ||
112 | // adap->fe = dib7000m_attach(&adap->dev->i2c_adap, &stk7700p_dib7000m_config, 18); | 249 | return adap->fe == NULL ? -ENODEV : 0; |
113 | return 0; | ||
114 | } | 250 | } |
115 | 251 | ||
252 | static struct mt2060_config stk7700p_mt2060_config = { | ||
253 | 0x60 | ||
254 | }; | ||
255 | |||
116 | static int stk7700p_tuner_attach(struct dvb_usb_adapter *adap) | 256 | static int stk7700p_tuner_attach(struct dvb_usb_adapter *adap) |
117 | { | 257 | { |
118 | // tun_i2c = dib7000m_get_tuner_i2c_master(adap->fe, 1); | 258 | struct dib0700_state *st = adap->dev->priv; |
119 | // return mt2060_attach(adap->fe, tun_i2c, &stk3000p_mt2060_config, if1); | 259 | struct i2c_adapter *tun_i2c; |
120 | return 0; | 260 | |
261 | if (st->is_dib7000pc) | ||
262 | tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1); | ||
263 | else | ||
264 | tun_i2c = dib7000m_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1); | ||
265 | |||
266 | return dvb_attach(mt2060_attach, adap->fe, tun_i2c, &stk7700p_mt2060_config, | ||
267 | st->mt2060_if1[0]) == NULL ? -ENODEV : 0; | ||
121 | } | 268 | } |
122 | 269 | ||
123 | struct usb_device_id dib0700_usb_id_table[] = { | 270 | struct usb_device_id dib0700_usb_id_table[] = { |
124 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P) }, | 271 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P) }, |
272 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P_PC) }, | ||
273 | |||
125 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500) }, | 274 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500) }, |
126 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_2) }, | 275 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_2) }, |
127 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK) }, | 276 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK) }, |
128 | { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR) }, | 277 | { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR) }, |
278 | { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_VIDEOMATE_U500) }, | ||
279 | { USB_DEVICE(USB_VID_UNIWILL, USB_PID_UNIWILL_STK7700P) }, | ||
280 | { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_STK7700P) }, | ||
281 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_2) }, | ||
282 | { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_2) }, | ||
129 | { } /* Terminating entry */ | 283 | { } /* Terminating entry */ |
130 | }; | 284 | }; |
131 | MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); | 285 | MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); |
@@ -167,20 +321,32 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
167 | }, | 321 | }, |
168 | }, | 322 | }, |
169 | 323 | ||
170 | .num_device_descs = 3, | 324 | .num_device_descs = 6, |
171 | .devices = { | 325 | .devices = { |
172 | { "DiBcom STK7700P reference design", | 326 | { "DiBcom STK7700P reference design", |
173 | { &dib0700_usb_id_table[0], NULL }, | 327 | { &dib0700_usb_id_table[0], &dib0700_usb_id_table[1] }, |
174 | { NULL }, | 328 | { NULL }, |
175 | }, | 329 | }, |
176 | { "Hauppauge Nova-T Stick", | 330 | { "Hauppauge Nova-T Stick", |
177 | { &dib0700_usb_id_table[3], NULL }, | 331 | { &dib0700_usb_id_table[4], &dib0700_usb_id_table[9], NULL }, |
178 | { NULL }, | 332 | { NULL }, |
179 | }, | 333 | }, |
180 | { "AVerMedia AVerTV DVB-T Volar", | 334 | { "AVerMedia AVerTV DVB-T Volar", |
181 | { &dib0700_usb_id_table[4], NULL }, | 335 | { &dib0700_usb_id_table[5], &dib0700_usb_id_table[10] }, |
182 | { NULL }, | 336 | { NULL }, |
183 | }, | 337 | }, |
338 | { "Compro Videomate U500", | ||
339 | { &dib0700_usb_id_table[6], NULL }, | ||
340 | { NULL }, | ||
341 | }, | ||
342 | { "Uniwill STK7700P based (Hama and others)", | ||
343 | { &dib0700_usb_id_table[7], NULL }, | ||
344 | { NULL }, | ||
345 | }, | ||
346 | { "Leadtek Winfast DTV Dongle (STK7700P based)", | ||
347 | { &dib0700_usb_id_table[8], NULL }, | ||
348 | { NULL }, | ||
349 | } | ||
184 | } | 350 | } |
185 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | 351 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, |
186 | 352 | ||
@@ -202,7 +368,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
202 | .num_device_descs = 1, | 368 | .num_device_descs = 1, |
203 | .devices = { | 369 | .devices = { |
204 | { "Hauppauge Nova-T 500 Dual DVB-T", | 370 | { "Hauppauge Nova-T 500 Dual DVB-T", |
205 | { &dib0700_usb_id_table[1], &dib0700_usb_id_table[2], NULL }, | 371 | { &dib0700_usb_id_table[2], &dib0700_usb_id_table[3], NULL }, |
206 | { NULL }, | 372 | { NULL }, |
207 | }, | 373 | }, |
208 | } | 374 | } |
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/dvb/dvb-usb/dibusb-mb.c index 4fe363e48352..7a6ae8f482e0 100644 --- a/drivers/media/dvb/dvb-usb/dibusb-mb.c +++ b/drivers/media/dvb/dvb-usb/dibusb-mb.c | |||
@@ -163,23 +163,23 @@ static struct dvb_usb_device_properties dibusb1_1_properties = { | |||
163 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | 163 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, |
164 | .pid_filter_count = 16, | 164 | .pid_filter_count = 16, |
165 | 165 | ||
166 | .streaming_ctrl = dibusb_streaming_ctrl, | 166 | .streaming_ctrl = dibusb_streaming_ctrl, |
167 | .pid_filter = dibusb_pid_filter, | 167 | .pid_filter = dibusb_pid_filter, |
168 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, | 168 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, |
169 | .frontend_attach = dibusb_dib3000mb_frontend_attach, | 169 | .frontend_attach = dibusb_dib3000mb_frontend_attach, |
170 | .tuner_attach = dibusb_tuner_probe_and_attach, | 170 | .tuner_attach = dibusb_tuner_probe_and_attach, |
171 | 171 | ||
172 | /* parameter for the MPEG2-data transfer */ | 172 | /* parameter for the MPEG2-data transfer */ |
173 | .stream = { | 173 | .stream = { |
174 | .type = USB_BULK, | 174 | .type = USB_BULK, |
175 | .count = 7, | 175 | .count = 7, |
176 | .endpoint = 0x02, | 176 | .endpoint = 0x02, |
177 | .u = { | 177 | .u = { |
178 | .bulk = { | 178 | .bulk = { |
179 | .buffersize = 4096, | 179 | .buffersize = 4096, |
180 | } | 180 | } |
181 | } | 181 | } |
182 | }, | 182 | }, |
183 | .size_of_priv = sizeof(struct dibusb_state), | 183 | .size_of_priv = sizeof(struct dibusb_state), |
184 | } | 184 | } |
185 | }, | 185 | }, |
@@ -248,23 +248,23 @@ static struct dvb_usb_device_properties dibusb1_1_an2235_properties = { | |||
248 | .caps = DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_ADAP_HAS_PID_FILTER, | 248 | .caps = DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_ADAP_HAS_PID_FILTER, |
249 | .pid_filter_count = 16, | 249 | .pid_filter_count = 16, |
250 | 250 | ||
251 | .streaming_ctrl = dibusb_streaming_ctrl, | 251 | .streaming_ctrl = dibusb_streaming_ctrl, |
252 | .pid_filter = dibusb_pid_filter, | 252 | .pid_filter = dibusb_pid_filter, |
253 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, | 253 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, |
254 | .frontend_attach = dibusb_dib3000mb_frontend_attach, | 254 | .frontend_attach = dibusb_dib3000mb_frontend_attach, |
255 | .tuner_attach = dibusb_tuner_probe_and_attach, | 255 | .tuner_attach = dibusb_tuner_probe_and_attach, |
256 | 256 | ||
257 | /* parameter for the MPEG2-data transfer */ | 257 | /* parameter for the MPEG2-data transfer */ |
258 | .stream = { | 258 | .stream = { |
259 | .type = USB_BULK, | 259 | .type = USB_BULK, |
260 | .count = 7, | 260 | .count = 7, |
261 | .endpoint = 0x02, | 261 | .endpoint = 0x02, |
262 | .u = { | 262 | .u = { |
263 | .bulk = { | 263 | .bulk = { |
264 | .buffersize = 4096, | 264 | .buffersize = 4096, |
265 | } | 265 | } |
266 | } | 266 | } |
267 | }, | 267 | }, |
268 | .size_of_priv = sizeof(struct dibusb_state), | 268 | .size_of_priv = sizeof(struct dibusb_state), |
269 | }, | 269 | }, |
270 | }, | 270 | }, |
@@ -312,22 +312,23 @@ static struct dvb_usb_device_properties dibusb2_0b_properties = { | |||
312 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | 312 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, |
313 | .pid_filter_count = 16, | 313 | .pid_filter_count = 16, |
314 | 314 | ||
315 | .streaming_ctrl = dibusb2_0_streaming_ctrl, | 315 | .streaming_ctrl = dibusb2_0_streaming_ctrl, |
316 | .pid_filter = dibusb_pid_filter, | 316 | .pid_filter = dibusb_pid_filter, |
317 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, | 317 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, |
318 | .frontend_attach = dibusb_dib3000mb_frontend_attach, | 318 | .frontend_attach = dibusb_dib3000mb_frontend_attach, |
319 | .tuner_attach = dibusb_thomson_tuner_attach, | 319 | .tuner_attach = dibusb_thomson_tuner_attach, |
320 | /* parameter for the MPEG2-data transfer */ | 320 | |
321 | /* parameter for the MPEG2-data transfer */ | ||
321 | .stream = { | 322 | .stream = { |
322 | .type = USB_BULK, | 323 | .type = USB_BULK, |
323 | .count = 7, | 324 | .count = 7, |
324 | .endpoint = 0x06, | 325 | .endpoint = 0x06, |
325 | .u = { | 326 | .u = { |
326 | .bulk = { | 327 | .bulk = { |
327 | .buffersize = 4096, | 328 | .buffersize = 4096, |
328 | } | 329 | } |
329 | } | 330 | } |
330 | }, | 331 | }, |
331 | .size_of_priv = sizeof(struct dibusb_state), | 332 | .size_of_priv = sizeof(struct dibusb_state), |
332 | } | 333 | } |
333 | }, | 334 | }, |
@@ -369,22 +370,22 @@ static struct dvb_usb_device_properties artec_t1_usb2_properties = { | |||
369 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | 370 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, |
370 | .pid_filter_count = 16, | 371 | .pid_filter_count = 16, |
371 | 372 | ||
372 | .streaming_ctrl = dibusb2_0_streaming_ctrl, | 373 | .streaming_ctrl = dibusb2_0_streaming_ctrl, |
373 | .pid_filter = dibusb_pid_filter, | 374 | .pid_filter = dibusb_pid_filter, |
374 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, | 375 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, |
375 | .frontend_attach = dibusb_dib3000mb_frontend_attach, | 376 | .frontend_attach = dibusb_dib3000mb_frontend_attach, |
376 | .tuner_attach = dibusb_tuner_probe_and_attach, | 377 | .tuner_attach = dibusb_tuner_probe_and_attach, |
377 | /* parameter for the MPEG2-data transfer */ | 378 | /* parameter for the MPEG2-data transfer */ |
378 | .stream = { | 379 | .stream = { |
379 | .type = USB_BULK, | 380 | .type = USB_BULK, |
380 | .count = 7, | 381 | .count = 7, |
381 | .endpoint = 0x06, | 382 | .endpoint = 0x06, |
382 | .u = { | 383 | .u = { |
383 | .bulk = { | 384 | .bulk = { |
384 | .buffersize = 4096, | 385 | .buffersize = 4096, |
385 | } | 386 | } |
386 | } | 387 | } |
387 | }, | 388 | }, |
388 | .size_of_priv = sizeof(struct dibusb_state), | 389 | .size_of_priv = sizeof(struct dibusb_state), |
389 | } | 390 | } |
390 | }, | 391 | }, |
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mc.c b/drivers/media/dvb/dvb-usb/dibusb-mc.c index a0fd37efc04b..e7ea3e753d6d 100644 --- a/drivers/media/dvb/dvb-usb/dibusb-mc.c +++ b/drivers/media/dvb/dvb-usb/dibusb-mc.c | |||
@@ -54,23 +54,23 @@ static struct dvb_usb_device_properties dibusb_mc_properties = { | |||
54 | { | 54 | { |
55 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | 55 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, |
56 | .pid_filter_count = 32, | 56 | .pid_filter_count = 32, |
57 | .streaming_ctrl = dibusb2_0_streaming_ctrl, | 57 | .streaming_ctrl = dibusb2_0_streaming_ctrl, |
58 | .pid_filter = dibusb_pid_filter, | 58 | .pid_filter = dibusb_pid_filter, |
59 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, | 59 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, |
60 | .frontend_attach = dibusb_dib3000mc_frontend_attach, | 60 | .frontend_attach = dibusb_dib3000mc_frontend_attach, |
61 | .tuner_attach = dibusb_dib3000mc_tuner_attach, | 61 | .tuner_attach = dibusb_dib3000mc_tuner_attach, |
62 | 62 | ||
63 | /* parameter for the MPEG2-data transfer */ | 63 | /* parameter for the MPEG2-data transfer */ |
64 | .stream = { | 64 | .stream = { |
65 | .type = USB_BULK, | 65 | .type = USB_BULK, |
66 | .count = 7, | 66 | .count = 7, |
67 | .endpoint = 0x06, | 67 | .endpoint = 0x06, |
68 | .u = { | 68 | .u = { |
69 | .bulk = { | 69 | .bulk = { |
70 | .buffersize = 4096, | 70 | .buffersize = 4096, |
71 | } | 71 | } |
72 | } | 72 | } |
73 | }, | 73 | }, |
74 | .size_of_priv = sizeof(struct dibusb_state), | 74 | .size_of_priv = sizeof(struct dibusb_state), |
75 | } | 75 | } |
76 | }, | 76 | }, |
diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c index 8fb34375c1fb..4a198d4755b0 100644 --- a/drivers/media/dvb/dvb-usb/digitv.c +++ b/drivers/media/dvb/dvb-usb/digitv.c | |||
@@ -274,20 +274,20 @@ static struct dvb_usb_device_properties digitv_properties = { | |||
274 | .num_adapters = 1, | 274 | .num_adapters = 1, |
275 | .adapter = { | 275 | .adapter = { |
276 | { | 276 | { |
277 | .frontend_attach = digitv_frontend_attach, | 277 | .frontend_attach = digitv_frontend_attach, |
278 | .tuner_attach = digitv_tuner_attach, | 278 | .tuner_attach = digitv_tuner_attach, |
279 | 279 | ||
280 | /* parameter for the MPEG2-data transfer */ | 280 | /* parameter for the MPEG2-data transfer */ |
281 | .stream = { | 281 | .stream = { |
282 | .type = USB_BULK, | 282 | .type = USB_BULK, |
283 | .count = 7, | 283 | .count = 7, |
284 | .endpoint = 0x02, | 284 | .endpoint = 0x02, |
285 | .u = { | 285 | .u = { |
286 | .bulk = { | 286 | .bulk = { |
287 | .buffersize = 4096, | 287 | .buffersize = 4096, |
288 | } | 288 | } |
289 | } | 289 | } |
290 | }, | 290 | }, |
291 | } | 291 | } |
292 | }, | 292 | }, |
293 | .identify_state = digitv_identify_state, | 293 | .identify_state = digitv_identify_state, |
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c index fa43a41d753b..7dbe14321019 100644 --- a/drivers/media/dvb/dvb-usb/dtt200u.c +++ b/drivers/media/dvb/dvb-usb/dtt200u.c | |||
@@ -268,20 +268,20 @@ static struct dvb_usb_device_properties wt220u_zl0353_properties = { | |||
268 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING, | 268 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING, |
269 | .pid_filter_count = 15, | 269 | .pid_filter_count = 15, |
270 | 270 | ||
271 | .streaming_ctrl = dtt200u_streaming_ctrl, | 271 | .streaming_ctrl = dtt200u_streaming_ctrl, |
272 | .pid_filter = dtt200u_pid_filter, | 272 | .pid_filter = dtt200u_pid_filter, |
273 | .frontend_attach = dtt200u_frontend_attach, | 273 | .frontend_attach = dtt200u_frontend_attach, |
274 | /* parameter for the MPEG2-data transfer */ | 274 | /* parameter for the MPEG2-data transfer */ |
275 | .stream = { | 275 | .stream = { |
276 | .type = USB_BULK, | 276 | .type = USB_BULK, |
277 | .count = 7, | 277 | .count = 7, |
278 | .endpoint = 0x02, | 278 | .endpoint = 0x02, |
279 | .u = { | 279 | .u = { |
280 | .bulk = { | 280 | .bulk = { |
281 | .buffersize = 4096, | 281 | .buffersize = 4096, |
282 | } | 282 | } |
283 | } | 283 | } |
284 | }, | 284 | }, |
285 | } | 285 | } |
286 | }, | 286 | }, |
287 | .power_ctrl = dtt200u_power_ctrl, | 287 | .power_ctrl = dtt200u_power_ctrl, |
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 4d6b069536ce..299382dcb81d 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | |||
@@ -33,6 +33,7 @@ | |||
33 | #define USB_VID_VISIONPLUS 0x13d3 | 33 | #define USB_VID_VISIONPLUS 0x13d3 |
34 | #define USB_VID_TWINHAN 0x1822 | 34 | #define USB_VID_TWINHAN 0x1822 |
35 | #define USB_VID_ULTIMA_ELECTRONIC 0x05d8 | 35 | #define USB_VID_ULTIMA_ELECTRONIC 0x05d8 |
36 | #define USB_VID_UNIWILL 0x1584 | ||
36 | #define USB_VID_WIDEVIEW 0x14aa | 37 | #define USB_VID_WIDEVIEW 0x14aa |
37 | 38 | ||
38 | /* Product IDs */ | 39 | /* Product IDs */ |
@@ -46,6 +47,7 @@ | |||
46 | #define USB_PID_COMPRO_DVBU2000_WARM 0xd001 | 47 | #define USB_PID_COMPRO_DVBU2000_WARM 0xd001 |
47 | #define USB_PID_COMPRO_DVBU2000_UNK_COLD 0x010c | 48 | #define USB_PID_COMPRO_DVBU2000_UNK_COLD 0x010c |
48 | #define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d | 49 | #define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d |
50 | #define USB_PID_COMPRO_VIDEOMATE_U500 0x1e78 | ||
49 | #define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064 | 51 | #define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064 |
50 | #define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065 | 52 | #define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065 |
51 | #define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8 | 53 | #define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8 |
@@ -53,7 +55,9 @@ | |||
53 | #define USB_PID_DIBCOM_MOD3001_COLD 0x0bc6 | 55 | #define USB_PID_DIBCOM_MOD3001_COLD 0x0bc6 |
54 | #define USB_PID_DIBCOM_MOD3001_WARM 0x0bc7 | 56 | #define USB_PID_DIBCOM_MOD3001_WARM 0x0bc7 |
55 | #define USB_PID_DIBCOM_STK7700P 0x1e14 | 57 | #define USB_PID_DIBCOM_STK7700P 0x1e14 |
58 | #define USB_PID_DIBCOM_STK7700P_PC 0x1e78 | ||
56 | #define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131 | 59 | #define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131 |
60 | #define USB_PID_UNIWILL_STK7700P 0x6003 | ||
57 | #define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 | 61 | #define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 |
58 | #define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1 | 62 | #define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1 |
59 | #define USB_PID_KWORLD_VSTREAM_COLD 0x17de | 63 | #define USB_PID_KWORLD_VSTREAM_COLD 0x17de |
@@ -97,7 +101,9 @@ | |||
97 | #define USB_PID_HAUPPAUGE_NOVA_T_500 0x9941 | 101 | #define USB_PID_HAUPPAUGE_NOVA_T_500 0x9941 |
98 | #define USB_PID_HAUPPAUGE_NOVA_T_500_2 0x9950 | 102 | #define USB_PID_HAUPPAUGE_NOVA_T_500_2 0x9950 |
99 | #define USB_PID_HAUPPAUGE_NOVA_T_STICK 0x7050 | 103 | #define USB_PID_HAUPPAUGE_NOVA_T_STICK 0x7050 |
100 | #define USB_PID_AVERMEDIA_VOLAR 0x1234 | 104 | #define USB_PID_HAUPPAUGE_NOVA_T_STICK_2 0x7060 |
105 | #define USB_PID_AVERMEDIA_VOLAR 0xa807 | ||
106 | #define USB_PID_AVERMEDIA_VOLAR_2 0xb808 | ||
101 | #define USB_PID_NEBULA_DIGITV 0x0201 | 107 | #define USB_PID_NEBULA_DIGITV 0x0201 |
102 | #define USB_PID_DVICO_BLUEBIRD_LGDT 0xd820 | 108 | #define USB_PID_DVICO_BLUEBIRD_LGDT 0xd820 |
103 | #define USB_PID_DVICO_BLUEBIRD_LG064F_COLD 0xd500 | 109 | #define USB_PID_DVICO_BLUEBIRD_LG064F_COLD 0xd500 |
@@ -110,8 +116,8 @@ | |||
110 | #define USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM 0xdb51 | 116 | #define USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM 0xdb51 |
111 | #define USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD 0xdb58 | 117 | #define USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD 0xdb58 |
112 | #define USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM 0xdb59 | 118 | #define USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM 0xdb59 |
113 | #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD 0xdb54 | 119 | #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD 0xdb54 |
114 | #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM 0xdb55 | 120 | #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM 0xdb55 |
115 | #define USB_PID_MEDION_MD95700 0x0932 | 121 | #define USB_PID_MEDION_MD95700 0x0932 |
116 | #define USB_PID_KYE_DVB_T_COLD 0x701e | 122 | #define USB_PID_KYE_DVB_T_COLD 0x701e |
117 | #define USB_PID_KYE_DVB_T_WARM 0x701f | 123 | #define USB_PID_KYE_DVB_T_WARM 0x701f |
@@ -125,7 +131,9 @@ | |||
125 | #define USB_PID_GRANDTEC_DVBT_USB2_WARM 0x0bc7 | 131 | #define USB_PID_GRANDTEC_DVBT_USB2_WARM 0x0bc7 |
126 | #define USB_PID_WINFAST_DTV_DONGLE_COLD 0x6025 | 132 | #define USB_PID_WINFAST_DTV_DONGLE_COLD 0x6025 |
127 | #define USB_PID_WINFAST_DTV_DONGLE_WARM 0x6026 | 133 | #define USB_PID_WINFAST_DTV_DONGLE_WARM 0x6026 |
134 | #define USB_PID_WINFAST_DTV_DONGLE_STK7700P 0x6f00 | ||
128 | #define USB_PID_GENPIX_8PSK_COLD 0x0200 | 135 | #define USB_PID_GENPIX_8PSK_COLD 0x0200 |
129 | #define USB_PID_GENPIX_8PSK_WARM 0x0201 | 136 | #define USB_PID_GENPIX_8PSK_WARM 0x0201 |
130 | 137 | ||
138 | |||
131 | #endif | 139 | #endif |
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c index 794e4471561c..19ff5978bc91 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c | |||
@@ -90,7 +90,9 @@ schedule: | |||
90 | 90 | ||
91 | int dvb_usb_remote_init(struct dvb_usb_device *d) | 91 | int dvb_usb_remote_init(struct dvb_usb_device *d) |
92 | { | 92 | { |
93 | struct input_dev *input_dev; | ||
93 | int i; | 94 | int i; |
95 | int err; | ||
94 | 96 | ||
95 | if (d->props.rc_key_map == NULL || | 97 | if (d->props.rc_key_map == NULL || |
96 | d->props.rc_query == NULL || | 98 | d->props.rc_query == NULL || |
@@ -100,23 +102,24 @@ int dvb_usb_remote_init(struct dvb_usb_device *d) | |||
100 | usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys)); | 102 | usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys)); |
101 | strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys)); | 103 | strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys)); |
102 | 104 | ||
103 | d->rc_input_dev = input_allocate_device(); | 105 | input_dev = input_allocate_device(); |
104 | if (!d->rc_input_dev) | 106 | if (!input_dev) |
105 | return -ENOMEM; | 107 | return -ENOMEM; |
106 | 108 | ||
107 | d->rc_input_dev->evbit[0] = BIT(EV_KEY); | 109 | input_dev->evbit[0] = BIT(EV_KEY); |
108 | d->rc_input_dev->keycodesize = sizeof(unsigned char); | 110 | input_dev->keycodesize = sizeof(unsigned char); |
109 | d->rc_input_dev->keycodemax = KEY_MAX; | 111 | input_dev->keycodemax = KEY_MAX; |
110 | d->rc_input_dev->name = "IR-receiver inside an USB DVB receiver"; | 112 | input_dev->name = "IR-receiver inside an USB DVB receiver"; |
111 | d->rc_input_dev->phys = d->rc_phys; | 113 | input_dev->phys = d->rc_phys; |
112 | usb_to_input_id(d->udev, &d->rc_input_dev->id); | 114 | usb_to_input_id(d->udev, &input_dev->id); |
113 | d->rc_input_dev->cdev.dev = &d->udev->dev; | 115 | input_dev->cdev.dev = &d->udev->dev; |
114 | 116 | ||
115 | /* set the bits for the keys */ | 117 | /* set the bits for the keys */ |
116 | deb_rc("key map size: %d\n", d->props.rc_key_map_size); | 118 | deb_rc("key map size: %d\n", d->props.rc_key_map_size); |
117 | for (i = 0; i < d->props.rc_key_map_size; i++) { | 119 | for (i = 0; i < d->props.rc_key_map_size; i++) { |
118 | deb_rc("setting bit for event %d item %d\n",d->props.rc_key_map[i].event, i); | 120 | deb_rc("setting bit for event %d item %d\n", |
119 | set_bit(d->props.rc_key_map[i].event, d->rc_input_dev->keybit); | 121 | d->props.rc_key_map[i].event, i); |
122 | set_bit(d->props.rc_key_map[i].event, input_dev->keybit); | ||
120 | } | 123 | } |
121 | 124 | ||
122 | /* Start the remote-control polling. */ | 125 | /* Start the remote-control polling. */ |
@@ -124,10 +127,16 @@ int dvb_usb_remote_init(struct dvb_usb_device *d) | |||
124 | d->props.rc_interval = 100; /* default */ | 127 | d->props.rc_interval = 100; /* default */ |
125 | 128 | ||
126 | /* setting these two values to non-zero, we have to manage key repeats */ | 129 | /* setting these two values to non-zero, we have to manage key repeats */ |
127 | d->rc_input_dev->rep[REP_PERIOD] = d->props.rc_interval; | 130 | input_dev->rep[REP_PERIOD] = d->props.rc_interval; |
128 | d->rc_input_dev->rep[REP_DELAY] = d->props.rc_interval + 150; | 131 | input_dev->rep[REP_DELAY] = d->props.rc_interval + 150; |
129 | 132 | ||
130 | input_register_device(d->rc_input_dev); | 133 | err = input_register_device(input_dev); |
134 | if (err) { | ||
135 | input_free_device(input_dev); | ||
136 | return err; | ||
137 | } | ||
138 | |||
139 | d->rc_input_dev = input_dev; | ||
131 | 140 | ||
132 | INIT_DELAYED_WORK(&d->rc_query_work, dvb_usb_read_remote_control); | 141 | INIT_DELAYED_WORK(&d->rc_query_work, dvb_usb_read_remote_control); |
133 | 142 | ||
diff --git a/drivers/media/dvb/dvb-usb/gp8psk.c b/drivers/media/dvb/dvb-usb/gp8psk.c index 7375eb20166d..518d67fca5e8 100644 --- a/drivers/media/dvb/dvb-usb/gp8psk.c +++ b/drivers/media/dvb/dvb-usb/gp8psk.c | |||
@@ -194,19 +194,19 @@ static struct dvb_usb_device_properties gp8psk_properties = { | |||
194 | .num_adapters = 1, | 194 | .num_adapters = 1, |
195 | .adapter = { | 195 | .adapter = { |
196 | { | 196 | { |
197 | .streaming_ctrl = gp8psk_streaming_ctrl, | 197 | .streaming_ctrl = gp8psk_streaming_ctrl, |
198 | .frontend_attach = gp8psk_frontend_attach, | 198 | .frontend_attach = gp8psk_frontend_attach, |
199 | /* parameter for the MPEG2-data transfer */ | 199 | /* parameter for the MPEG2-data transfer */ |
200 | .stream = { | 200 | .stream = { |
201 | .type = USB_BULK, | 201 | .type = USB_BULK, |
202 | .count = 7, | 202 | .count = 7, |
203 | .endpoint = 0x82, | 203 | .endpoint = 0x82, |
204 | .u = { | 204 | .u = { |
205 | .bulk = { | 205 | .bulk = { |
206 | .buffersize = 8192, | 206 | .buffersize = 8192, |
207 | } | 207 | } |
208 | } | 208 | } |
209 | }, | 209 | }, |
210 | } | 210 | } |
211 | }, | 211 | }, |
212 | .power_ctrl = gp8psk_power_ctrl, | 212 | .power_ctrl = gp8psk_power_ctrl, |
diff --git a/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/drivers/media/dvb/dvb-usb/nova-t-usb2.c index a58874c790b2..d48622e76b1b 100644 --- a/drivers/media/dvb/dvb-usb/nova-t-usb2.c +++ b/drivers/media/dvb/dvb-usb/nova-t-usb2.c | |||
@@ -163,23 +163,23 @@ static struct dvb_usb_device_properties nova_t_properties = { | |||
163 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | 163 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, |
164 | .pid_filter_count = 32, | 164 | .pid_filter_count = 32, |
165 | 165 | ||
166 | .streaming_ctrl = dibusb2_0_streaming_ctrl, | 166 | .streaming_ctrl = dibusb2_0_streaming_ctrl, |
167 | .pid_filter = dibusb_pid_filter, | 167 | .pid_filter = dibusb_pid_filter, |
168 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, | 168 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, |
169 | .frontend_attach = dibusb_dib3000mc_frontend_attach, | 169 | .frontend_attach = dibusb_dib3000mc_frontend_attach, |
170 | .tuner_attach = dibusb_dib3000mc_tuner_attach, | 170 | .tuner_attach = dibusb_dib3000mc_tuner_attach, |
171 | 171 | ||
172 | /* parameter for the MPEG2-data transfer */ | 172 | /* parameter for the MPEG2-data transfer */ |
173 | .stream = { | 173 | .stream = { |
174 | .type = USB_BULK, | 174 | .type = USB_BULK, |
175 | .count = 7, | 175 | .count = 7, |
176 | .endpoint = 0x06, | 176 | .endpoint = 0x06, |
177 | .u = { | 177 | .u = { |
178 | .bulk = { | 178 | .bulk = { |
179 | .buffersize = 4096, | 179 | .buffersize = 4096, |
180 | } | 180 | } |
181 | } | 181 | } |
182 | }, | 182 | }, |
183 | 183 | ||
184 | .size_of_priv = sizeof(struct dibusb_state), | 184 | .size_of_priv = sizeof(struct dibusb_state), |
185 | } | 185 | } |
diff --git a/drivers/media/dvb/dvb-usb/ttusb2.c b/drivers/media/dvb/dvb-usb/ttusb2.c new file mode 100644 index 000000000000..95d29976ed78 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/ttusb2.c | |||
@@ -0,0 +1,270 @@ | |||
1 | /* DVB USB compliant linux driver for Technotrend DVB USB boxes and clones | ||
2 | * (e.g. Pinnacle 400e DVB-S USB2.0). | ||
3 | * | ||
4 | * The Pinnacle 400e uses the same protocol as the Technotrend USB1.1 boxes. | ||
5 | * | ||
6 | * TDA8263 + TDA10086 | ||
7 | * | ||
8 | * I2C addresses: | ||
9 | * 0x08 - LNBP21PD - LNB power supply | ||
10 | * 0x0e - TDA10086 - Demodulator | ||
11 | * 0x50 - FX2 eeprom | ||
12 | * 0x60 - TDA8263 - Tuner | ||
13 | * 0x78 ??? | ||
14 | * | ||
15 | * Copyright (c) 2002 Holger Waechtler <holger@convergence.de> | ||
16 | * Copyright (c) 2003 Felix Domke <tmbinc@elitedvb.net> | ||
17 | * Copyright (C) 2005-6 Patrick Boettcher <pb@linuxtv.org> | ||
18 | * | ||
19 | * This program is free software; you can redistribute it and/or modify it | ||
20 | * under the terms of the GNU General Public License as published by the Free | ||
21 | * Software Foundation, version 2. | ||
22 | * | ||
23 | * see Documentation/dvb/README.dvb-usb for more information | ||
24 | */ | ||
25 | #define DVB_USB_LOG_PREFIX "ttusb2" | ||
26 | #include "dvb-usb.h" | ||
27 | |||
28 | #include "ttusb2.h" | ||
29 | |||
30 | #include "tda826x.h" | ||
31 | #include "tda10086.h" | ||
32 | #include "lnbp21.h" | ||
33 | |||
34 | /* debug */ | ||
35 | static int dvb_usb_ttusb2_debug; | ||
36 | #define deb_info(args...) dprintk(dvb_usb_ttusb2_debug,0x01,args) | ||
37 | module_param_named(debug,dvb_usb_ttusb2_debug, int, 0644); | ||
38 | MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))." DVB_USB_DEBUG_STATUS); | ||
39 | |||
40 | struct ttusb2_state { | ||
41 | u8 id; | ||
42 | }; | ||
43 | |||
44 | static int ttusb2_msg(struct dvb_usb_device *d, u8 cmd, | ||
45 | u8 *wbuf, int wlen, u8 *rbuf, int rlen) | ||
46 | { | ||
47 | struct ttusb2_state *st = d->priv; | ||
48 | u8 s[wlen+4],r[64] = { 0 }; | ||
49 | int ret = 0; | ||
50 | |||
51 | memset(s,0,wlen+4); | ||
52 | |||
53 | s[0] = 0xaa; | ||
54 | s[1] = ++st->id; | ||
55 | s[2] = cmd; | ||
56 | s[3] = wlen; | ||
57 | memcpy(&s[4],wbuf,wlen); | ||
58 | |||
59 | ret = dvb_usb_generic_rw(d, s, wlen+4, r, 64, 0); | ||
60 | |||
61 | if (ret != 0 || | ||
62 | r[0] != 0x55 || | ||
63 | r[1] != s[1] || | ||
64 | r[2] != cmd || | ||
65 | (rlen > 0 && r[3] != rlen)) { | ||
66 | warn("there might have been an error during control message transfer. (rlen = %d, was %d)",rlen,r[3]); | ||
67 | return -EIO; | ||
68 | } | ||
69 | |||
70 | if (rlen > 0) | ||
71 | memcpy(rbuf, &r[4], rlen); | ||
72 | |||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | static int ttusb2_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) | ||
77 | { | ||
78 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
79 | static u8 obuf[60], ibuf[60]; | ||
80 | int i,read; | ||
81 | |||
82 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
83 | return -EAGAIN; | ||
84 | |||
85 | if (num > 2) | ||
86 | warn("more than 2 i2c messages at a time is not handled yet. TODO."); | ||
87 | |||
88 | for (i = 0; i < num; i++) { | ||
89 | read = i+1 < num && (msg[i+1].flags & I2C_M_RD); | ||
90 | |||
91 | obuf[0] = (msg[i].addr << 1) | read; | ||
92 | obuf[1] = msg[i].len; | ||
93 | |||
94 | /* read request */ | ||
95 | if (read) | ||
96 | obuf[2] = msg[i+1].len; | ||
97 | else | ||
98 | obuf[2] = 0; | ||
99 | |||
100 | memcpy(&obuf[3],msg[i].buf,msg[i].len); | ||
101 | |||
102 | if (ttusb2_msg(d, CMD_I2C_XFER, obuf, msg[i].len+3, ibuf, obuf[2] + 3) < 0) { | ||
103 | err("i2c transfer failed."); | ||
104 | break; | ||
105 | } | ||
106 | |||
107 | if (read) { | ||
108 | memcpy(msg[i+1].buf,&ibuf[3],msg[i+1].len); | ||
109 | i++; | ||
110 | } | ||
111 | } | ||
112 | |||
113 | mutex_unlock(&d->i2c_mutex); | ||
114 | return i; | ||
115 | } | ||
116 | |||
117 | static u32 ttusb2_i2c_func(struct i2c_adapter *adapter) | ||
118 | { | ||
119 | return I2C_FUNC_I2C; | ||
120 | } | ||
121 | |||
122 | static struct i2c_algorithm ttusb2_i2c_algo = { | ||
123 | .master_xfer = ttusb2_i2c_xfer, | ||
124 | .functionality = ttusb2_i2c_func, | ||
125 | }; | ||
126 | |||
127 | /* Callbacks for DVB USB */ | ||
128 | static int ttusb2_identify_state (struct usb_device *udev, struct | ||
129 | dvb_usb_device_properties *props, struct dvb_usb_device_description **desc, | ||
130 | int *cold) | ||
131 | { | ||
132 | *cold = udev->descriptor.iManufacturer == 0 && udev->descriptor.iProduct == 0; | ||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | static int ttusb2_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
137 | { | ||
138 | u8 b = onoff; | ||
139 | ttusb2_msg(d, CMD_POWER, &b, 0, NULL, 0); | ||
140 | return ttusb2_msg(d, CMD_POWER, &b, 1, NULL, 0); | ||
141 | } | ||
142 | |||
143 | |||
144 | static struct tda10086_config tda10086_config = { | ||
145 | .demod_address = 0x0e, | ||
146 | .invert = 0, | ||
147 | }; | ||
148 | |||
149 | static int ttusb2_frontend_attach(struct dvb_usb_adapter *adap) | ||
150 | { | ||
151 | if (usb_set_interface(adap->dev->udev,0,3) < 0) | ||
152 | err("set interface to alts=3 failed"); | ||
153 | |||
154 | if ((adap->fe = dvb_attach(tda10086_attach, &tda10086_config, &adap->dev->i2c_adap)) == NULL) { | ||
155 | deb_info("TDA10086 attach failed\n"); | ||
156 | return -ENODEV; | ||
157 | } | ||
158 | |||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | static int ttusb2_tuner_attach(struct dvb_usb_adapter *adap) | ||
163 | { | ||
164 | if (dvb_attach(tda826x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, 0) == NULL) { | ||
165 | deb_info("TDA8263 attach failed\n"); | ||
166 | return -ENODEV; | ||
167 | } | ||
168 | |||
169 | if (dvb_attach(lnbp21_attach, adap->fe, &adap->dev->i2c_adap, 0, 0) == NULL) { | ||
170 | deb_info("LNBP21 attach failed\n"); | ||
171 | return -ENODEV; | ||
172 | } | ||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | /* DVB USB Driver stuff */ | ||
177 | static struct dvb_usb_device_properties ttusb2_properties; | ||
178 | |||
179 | static int ttusb2_probe(struct usb_interface *intf, | ||
180 | const struct usb_device_id *id) | ||
181 | { | ||
182 | return dvb_usb_device_init(intf,&ttusb2_properties,THIS_MODULE,NULL); | ||
183 | } | ||
184 | |||
185 | static struct usb_device_id ttusb2_table [] = { | ||
186 | { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_400E) }, | ||
187 | {} /* Terminating entry */ | ||
188 | }; | ||
189 | MODULE_DEVICE_TABLE (usb, ttusb2_table); | ||
190 | |||
191 | static struct dvb_usb_device_properties ttusb2_properties = { | ||
192 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
193 | |||
194 | .usb_ctrl = CYPRESS_FX2, | ||
195 | .firmware = "dvb-usb-pctv-400e-01.fw", | ||
196 | |||
197 | .size_of_priv = sizeof(struct ttusb2_state), | ||
198 | |||
199 | .num_adapters = 1, | ||
200 | .adapter = { | ||
201 | { | ||
202 | .streaming_ctrl = NULL, // ttusb2_streaming_ctrl, | ||
203 | |||
204 | .frontend_attach = ttusb2_frontend_attach, | ||
205 | .tuner_attach = ttusb2_tuner_attach, | ||
206 | |||
207 | /* parameter for the MPEG2-data transfer */ | ||
208 | .stream = { | ||
209 | .type = USB_ISOC, | ||
210 | .count = 5, | ||
211 | .endpoint = 0x02, | ||
212 | .u = { | ||
213 | .isoc = { | ||
214 | .framesperurb = 4, | ||
215 | .framesize = 940, | ||
216 | .interval = 1, | ||
217 | } | ||
218 | } | ||
219 | } | ||
220 | } | ||
221 | }, | ||
222 | |||
223 | .power_ctrl = ttusb2_power_ctrl, | ||
224 | .identify_state = ttusb2_identify_state, | ||
225 | |||
226 | .i2c_algo = &ttusb2_i2c_algo, | ||
227 | |||
228 | .generic_bulk_ctrl_endpoint = 0x01, | ||
229 | |||
230 | .num_device_descs = 1, | ||
231 | .devices = { | ||
232 | { "Pinnacle 400e DVB-S USB2.0", | ||
233 | { &ttusb2_table[0], NULL }, | ||
234 | { NULL }, | ||
235 | }, | ||
236 | } | ||
237 | }; | ||
238 | |||
239 | static struct usb_driver ttusb2_driver = { | ||
240 | .name = "dvb_usb_ttusb2", | ||
241 | .probe = ttusb2_probe, | ||
242 | .disconnect = dvb_usb_device_exit, | ||
243 | .id_table = ttusb2_table, | ||
244 | }; | ||
245 | |||
246 | /* module stuff */ | ||
247 | static int __init ttusb2_module_init(void) | ||
248 | { | ||
249 | int result; | ||
250 | if ((result = usb_register(&ttusb2_driver))) { | ||
251 | err("usb_register failed. Error number %d",result); | ||
252 | return result; | ||
253 | } | ||
254 | |||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | static void __exit ttusb2_module_exit(void) | ||
259 | { | ||
260 | /* deregister this driver from the USB subsystem */ | ||
261 | usb_deregister(&ttusb2_driver); | ||
262 | } | ||
263 | |||
264 | module_init (ttusb2_module_init); | ||
265 | module_exit (ttusb2_module_exit); | ||
266 | |||
267 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | ||
268 | MODULE_DESCRIPTION("Driver for Pinnacle PCTV 400e DVB-S USB2.0"); | ||
269 | MODULE_VERSION("1.0"); | ||
270 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/ttusb2.h b/drivers/media/dvb/dvb-usb/ttusb2.h new file mode 100644 index 000000000000..52a63af40896 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/ttusb2.h | |||
@@ -0,0 +1,70 @@ | |||
1 | /* DVB USB compliant linux driver for Technotrend DVB USB boxes and clones | ||
2 | * (e.g. Pinnacle 400e DVB-S USB2.0). | ||
3 | * | ||
4 | * Copyright (c) 2002 Holger Waechtler <holger@convergence.de> | ||
5 | * Copyright (c) 2003 Felix Domke <tmbinc@elitedvb.net> | ||
6 | * Copyright (C) 2005-6 Patrick Boettcher <pb@linuxtv.de> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the Free | ||
10 | * Software Foundation, version 2. | ||
11 | * | ||
12 | * see Documentation/dvb/README.dvb-usb for more information | ||
13 | */ | ||
14 | #ifndef _DVB_USB_TTUSB2_H_ | ||
15 | #define _DVB_USB_TTUSB2_H_ | ||
16 | |||
17 | /* TTUSB protocol | ||
18 | * | ||
19 | * always to messages (out/in) | ||
20 | * out message: | ||
21 | * 0xaa <id> <cmdbyte> <datalen> <data...> | ||
22 | * | ||
23 | * in message (complete block is always 0x40 bytes long) | ||
24 | * 0x55 <id> <cmdbyte> <datalen> <data...> | ||
25 | * | ||
26 | * id is incremented for each transaction | ||
27 | */ | ||
28 | |||
29 | #define CMD_DSP_DOWNLOAD 0x13 | ||
30 | /* out data: <byte>[28] | ||
31 | * last block must be empty */ | ||
32 | |||
33 | #define CMD_DSP_BOOT 0x14 | ||
34 | /* out data: nothing */ | ||
35 | |||
36 | #define CMD_POWER 0x15 | ||
37 | /* out data: <on=1/off=0> */ | ||
38 | |||
39 | #define CMD_LNB 0x16 | ||
40 | /* out data: <power=1> <18V=0,13V=1> <tone> <??=1> <??=1> */ | ||
41 | |||
42 | #define CMD_GET_VERSION 0x17 | ||
43 | /* in data: <version_byte>[5] */ | ||
44 | |||
45 | #define CMD_DISEQC 0x18 | ||
46 | /* out data: <master=0xff/burst=??> <cmdlen> <cmdbytes>[cmdlen] */ | ||
47 | |||
48 | #define CMD_PID_ENABLE 0x22 | ||
49 | /* out data: <index> <type: ts=1/sec=2> <pid msb> <pid lsb> */ | ||
50 | |||
51 | #define CMD_PID_DISABLE 0x23 | ||
52 | /* out data: <index> */ | ||
53 | |||
54 | #define CMD_FILTER_ENABLE 0x24 | ||
55 | /* out data: <index> <pid_idx> <filter>[12] <mask>[12] */ | ||
56 | |||
57 | #define CMD_FILTER_DISABLE 0x25 | ||
58 | /* out data: <index> */ | ||
59 | |||
60 | #define CMD_GET_DSP_VERSION 0x26 | ||
61 | /* in data: <version_byte>[28] */ | ||
62 | |||
63 | #define CMD_I2C_XFER 0x31 | ||
64 | /* out data: <addr << 1> <sndlen> <rcvlen> <data>[sndlen] | ||
65 | * in data: <addr << 1> <sndlen> <rcvlen> <data>[rcvlen] */ | ||
66 | |||
67 | #define CMD_I2C_BITRATE 0x32 | ||
68 | /* out data: <default=0> */ | ||
69 | |||
70 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/umt-010.c b/drivers/media/dvb/dvb-usb/umt-010.c index f9941ea88b3e..f77b48f76582 100644 --- a/drivers/media/dvb/dvb-usb/umt-010.c +++ b/drivers/media/dvb/dvb-usb/umt-010.c | |||
@@ -99,21 +99,21 @@ static struct dvb_usb_device_properties umt_properties = { | |||
99 | .num_adapters = 1, | 99 | .num_adapters = 1, |
100 | .adapter = { | 100 | .adapter = { |
101 | { | 101 | { |
102 | .streaming_ctrl = dibusb2_0_streaming_ctrl, | 102 | .streaming_ctrl = dibusb2_0_streaming_ctrl, |
103 | .frontend_attach = umt_mt352_frontend_attach, | 103 | .frontend_attach = umt_mt352_frontend_attach, |
104 | .tuner_attach = umt_tuner_attach, | 104 | .tuner_attach = umt_tuner_attach, |
105 | 105 | ||
106 | /* parameter for the MPEG2-data transfer */ | 106 | /* parameter for the MPEG2-data transfer */ |
107 | .stream = { | 107 | .stream = { |
108 | .type = USB_BULK, | 108 | .type = USB_BULK, |
109 | .count = 20, | 109 | .count = 20, |
110 | .endpoint = 0x06, | 110 | .endpoint = 0x06, |
111 | .u = { | 111 | .u = { |
112 | .bulk = { | 112 | .bulk = { |
113 | .buffersize = 512, | 113 | .buffersize = 512, |
114 | } | 114 | } |
115 | } | 115 | } |
116 | }, | 116 | }, |
117 | 117 | ||
118 | .size_of_priv = sizeof(struct dibusb_state), | 118 | .size_of_priv = sizeof(struct dibusb_state), |
119 | } | 119 | } |
diff --git a/drivers/media/dvb/dvb-usb/vp702x.c b/drivers/media/dvb/dvb-usb/vp702x.c index 02bd61aaac66..16533b31a82d 100644 --- a/drivers/media/dvb/dvb-usb/vp702x.c +++ b/drivers/media/dvb/dvb-usb/vp702x.c | |||
@@ -275,22 +275,22 @@ static struct dvb_usb_device_properties vp702x_properties = { | |||
275 | .caps = DVB_USB_ADAP_RECEIVES_204_BYTE_TS, | 275 | .caps = DVB_USB_ADAP_RECEIVES_204_BYTE_TS, |
276 | 276 | ||
277 | .streaming_ctrl = vp702x_streaming_ctrl, | 277 | .streaming_ctrl = vp702x_streaming_ctrl, |
278 | .frontend_attach = vp702x_frontend_attach, | 278 | .frontend_attach = vp702x_frontend_attach, |
279 | 279 | ||
280 | /* parameter for the MPEG2-data transfer */ | 280 | /* parameter for the MPEG2-data transfer */ |
281 | .stream = { | 281 | .stream = { |
282 | .type = USB_BULK, | 282 | .type = USB_BULK, |
283 | .count = 10, | 283 | .count = 10, |
284 | .endpoint = 0x02, | 284 | .endpoint = 0x02, |
285 | .u = { | 285 | .u = { |
286 | .bulk = { | 286 | .bulk = { |
287 | .buffersize = 4096, | 287 | .buffersize = 4096, |
288 | } | 288 | } |
289 | } | 289 | } |
290 | }, | 290 | }, |
291 | .size_of_priv = sizeof(struct vp702x_state), | 291 | .size_of_priv = sizeof(struct vp702x_state), |
292 | } | 292 | } |
293 | }, | 293 | }, |
294 | .read_mac_address = vp702x_read_mac_addr, | 294 | .read_mac_address = vp702x_read_mac_addr, |
295 | 295 | ||
296 | .rc_key_map = vp702x_rc_keys, | 296 | .rc_key_map = vp702x_rc_keys, |
diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c index b4cf002703a7..69a46b3607a2 100644 --- a/drivers/media/dvb/dvb-usb/vp7045.c +++ b/drivers/media/dvb/dvb-usb/vp7045.c | |||
@@ -125,7 +125,25 @@ static struct dvb_usb_rc_key vp7045_rc_keys[] = { | |||
125 | { 0x00, 0x00, KEY_TAB }, /* Tab */ | 125 | { 0x00, 0x00, KEY_TAB }, /* Tab */ |
126 | { 0x00, 0x48, KEY_INFO }, /* Preview */ | 126 | { 0x00, 0x48, KEY_INFO }, /* Preview */ |
127 | { 0x00, 0x04, KEY_LIST }, /* RecordList */ | 127 | { 0x00, 0x04, KEY_LIST }, /* RecordList */ |
128 | { 0x00, 0x0f, KEY_TEXT } /* Teletext */ | 128 | { 0x00, 0x0f, KEY_TEXT }, /* Teletext */ |
129 | { 0x00, 0x41, KEY_PREVIOUSSONG }, | ||
130 | { 0x00, 0x42, KEY_NEXTSONG }, | ||
131 | { 0x00, 0x4b, KEY_UP }, | ||
132 | { 0x00, 0x51, KEY_DOWN }, | ||
133 | { 0x00, 0x4e, KEY_LEFT }, | ||
134 | { 0x00, 0x52, KEY_RIGHT }, | ||
135 | { 0x00, 0x4f, KEY_ENTER }, | ||
136 | { 0x00, 0x13, KEY_CANCEL }, | ||
137 | { 0x00, 0x4a, KEY_CLEAR }, | ||
138 | { 0x00, 0x54, KEY_PRINT }, /* Capture */ | ||
139 | { 0x00, 0x43, KEY_SUBTITLE }, /* Subtitle/CC */ | ||
140 | { 0x00, 0x08, KEY_VIDEO }, /* A/V */ | ||
141 | { 0x00, 0x07, KEY_SLEEP }, /* Hibernate */ | ||
142 | { 0x00, 0x45, KEY_ZOOM }, /* Zoom+ */ | ||
143 | { 0x00, 0x18, KEY_RED}, | ||
144 | { 0x00, 0x53, KEY_GREEN}, | ||
145 | { 0x00, 0x5e, KEY_YELLOW}, | ||
146 | { 0x00, 0x5f, KEY_BLUE} | ||
129 | }; | 147 | }; |
130 | 148 | ||
131 | static int vp7045_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | 149 | static int vp7045_rc_query(struct dvb_usb_device *d, u32 *event, int *state) |
@@ -217,18 +235,18 @@ static struct dvb_usb_device_properties vp7045_properties = { | |||
217 | .num_adapters = 1, | 235 | .num_adapters = 1, |
218 | .adapter = { | 236 | .adapter = { |
219 | { | 237 | { |
220 | .frontend_attach = vp7045_frontend_attach, | 238 | .frontend_attach = vp7045_frontend_attach, |
221 | /* parameter for the MPEG2-data transfer */ | 239 | /* parameter for the MPEG2-data transfer */ |
222 | .stream = { | 240 | .stream = { |
223 | .type = USB_BULK, | 241 | .type = USB_BULK, |
224 | .count = 7, | 242 | .count = 7, |
225 | .endpoint = 0x02, | 243 | .endpoint = 0x02, |
226 | .u = { | 244 | .u = { |
227 | .bulk = { | 245 | .bulk = { |
228 | .buffersize = 4096, | 246 | .buffersize = 4096, |
229 | } | 247 | } |
230 | } | 248 | } |
231 | }, | 249 | }, |
232 | } | 250 | } |
233 | }, | 251 | }, |
234 | .power_ctrl = vp7045_power_ctrl, | 252 | .power_ctrl = vp7045_power_ctrl, |
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index aebb8d6f26f8..af314bb1dcac 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig | |||
@@ -172,6 +172,22 @@ config DVB_DIB3000MC | |||
172 | A DVB-T tuner module. Designed for mobile usage. Say Y when you want | 172 | A DVB-T tuner module. Designed for mobile usage. Say Y when you want |
173 | to support this frontend. | 173 | to support this frontend. |
174 | 174 | ||
175 | config DVB_DIB7000M | ||
176 | tristate "DiBcom 7000MA/MB/PA/PB/MC" | ||
177 | depends on DVB_CORE && I2C | ||
178 | default m if DVB_FE_CUSTOMISE | ||
179 | help | ||
180 | A DVB-T tuner module. Designed for mobile usage. Say Y when you want | ||
181 | to support this frontend. | ||
182 | |||
183 | config DVB_DIB7000P | ||
184 | tristate "DiBcom 7000PC" | ||
185 | depends on DVB_CORE && I2C | ||
186 | default m if DVB_FE_CUSTOMISE | ||
187 | help | ||
188 | A DVB-T tuner module. Designed for mobile usage. Say Y when you want | ||
189 | to support this frontend. | ||
190 | |||
175 | comment "DVB-C (cable) frontends" | 191 | comment "DVB-C (cable) frontends" |
176 | depends on DVB_CORE | 192 | depends on DVB_CORE |
177 | 193 | ||
@@ -281,6 +297,14 @@ config DVB_TUNER_MT2060 | |||
281 | help | 297 | help |
282 | A driver for the silicon IF tuner MT2060 from Microtune. | 298 | A driver for the silicon IF tuner MT2060 from Microtune. |
283 | 299 | ||
300 | config DVB_TUNER_LGH06XF | ||
301 | tristate "LG TDVS-H06xF ATSC tuner" | ||
302 | depends on DVB_CORE && I2C | ||
303 | select DVB_PLL | ||
304 | default m if DVB_FE_CUSTOMISE | ||
305 | help | ||
306 | A driver for the LG TDVS-H06xF ATSC tuner family. | ||
307 | |||
284 | comment "Miscellaneous devices" | 308 | comment "Miscellaneous devices" |
285 | depends on DVB_CORE | 309 | depends on DVB_CORE |
286 | 310 | ||
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index dce9cf0c75c0..3fa6e5d32a9c 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile | |||
@@ -13,6 +13,8 @@ obj-$(CONFIG_DVB_TDA8083) += tda8083.o | |||
13 | obj-$(CONFIG_DVB_L64781) += l64781.o | 13 | obj-$(CONFIG_DVB_L64781) += l64781.o |
14 | obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o | 14 | obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o |
15 | obj-$(CONFIG_DVB_DIB3000MC) += dib3000mc.o dibx000_common.o | 15 | obj-$(CONFIG_DVB_DIB3000MC) += dib3000mc.o dibx000_common.o |
16 | obj-$(CONFIG_DVB_DIB7000M) += dib7000m.o dibx000_common.o | ||
17 | obj-$(CONFIG_DVB_DIB7000P) += dib7000p.o dibx000_common.o | ||
16 | obj-$(CONFIG_DVB_MT312) += mt312.o | 18 | obj-$(CONFIG_DVB_MT312) += mt312.o |
17 | obj-$(CONFIG_DVB_VES1820) += ves1820.o | 19 | obj-$(CONFIG_DVB_VES1820) += ves1820.o |
18 | obj-$(CONFIG_DVB_VES1X93) += ves1x93.o | 20 | obj-$(CONFIG_DVB_VES1X93) += ves1x93.o |
@@ -37,3 +39,4 @@ obj-$(CONFIG_DVB_TDA10086) += tda10086.o | |||
37 | obj-$(CONFIG_DVB_TDA826X) += tda826x.o | 39 | obj-$(CONFIG_DVB_TDA826X) += tda826x.o |
38 | obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o | 40 | obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o |
39 | obj-$(CONFIG_DVB_TUA6100) += tua6100.o | 41 | obj-$(CONFIG_DVB_TUA6100) += tua6100.o |
42 | obj-$(CONFIG_DVB_TUNER_LGH06XF) += lgh06xf.o | ||
diff --git a/drivers/media/dvb/frontends/dib3000mc.c b/drivers/media/dvb/frontends/dib3000mc.c index 3561a777568c..5da66178006c 100644 --- a/drivers/media/dvb/frontends/dib3000mc.c +++ b/drivers/media/dvb/frontends/dib3000mc.c | |||
@@ -511,16 +511,11 @@ static int dib3000mc_autosearch_start(struct dvb_frontend *demod, struct dibx000 | |||
511 | 511 | ||
512 | 512 | ||
513 | /* a channel for autosearch */ | 513 | /* a channel for autosearch */ |
514 | reg = 0; | ||
515 | if (chan->nfft == -1 && chan->guard == -1) reg = 7; | ||
516 | if (chan->nfft == -1 && chan->guard != -1) reg = 2; | ||
517 | if (chan->nfft != -1 && chan->guard == -1) reg = 3; | ||
518 | |||
519 | fchan.nfft = 1; fchan.guard = 0; fchan.nqam = 2; | 514 | fchan.nfft = 1; fchan.guard = 0; fchan.nqam = 2; |
520 | fchan.vit_alpha = 1; fchan.vit_code_rate_hp = 2; fchan.vit_code_rate_lp = 2; | 515 | fchan.vit_alpha = 1; fchan.vit_code_rate_hp = 2; fchan.vit_code_rate_lp = 2; |
521 | fchan.vit_hrch = 0; fchan.vit_select_hp = 1; | 516 | fchan.vit_hrch = 0; fchan.vit_select_hp = 1; |
522 | 517 | ||
523 | dib3000mc_set_channel_cfg(state, &fchan, reg); | 518 | dib3000mc_set_channel_cfg(state, &fchan, 7); |
524 | 519 | ||
525 | reg = dib3000mc_read_word(state, 0); | 520 | reg = dib3000mc_read_word(state, 0); |
526 | dib3000mc_write_word(state, 0, reg | (1 << 8)); | 521 | dib3000mc_write_word(state, 0, reg | (1 << 8)); |
diff --git a/drivers/media/dvb/frontends/dib7000m.c b/drivers/media/dvb/frontends/dib7000m.c new file mode 100644 index 000000000000..f5d40aa3d27f --- /dev/null +++ b/drivers/media/dvb/frontends/dib7000m.c | |||
@@ -0,0 +1,1191 @@ | |||
1 | /* | ||
2 | * Linux-DVB Driver for DiBcom's DiB7000M and | ||
3 | * first generation DiB7000P-demodulator-family. | ||
4 | * | ||
5 | * Copyright (C) 2005-6 DiBcom (http://www.dibcom.fr/) | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License as | ||
9 | * published by the Free Software Foundation, version 2. | ||
10 | */ | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/i2c.h> | ||
13 | |||
14 | #include "dvb_frontend.h" | ||
15 | |||
16 | #include "dib7000m.h" | ||
17 | |||
18 | static int debug; | ||
19 | module_param(debug, int, 0644); | ||
20 | MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); | ||
21 | |||
22 | #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000M:"); printk(args); } } while (0) | ||
23 | |||
24 | struct dib7000m_state { | ||
25 | struct dvb_frontend demod; | ||
26 | struct dib7000m_config cfg; | ||
27 | |||
28 | u8 i2c_addr; | ||
29 | struct i2c_adapter *i2c_adap; | ||
30 | |||
31 | struct dibx000_i2c_master i2c_master; | ||
32 | |||
33 | /* offset is 1 in case of the 7000MC */ | ||
34 | u8 reg_offs; | ||
35 | |||
36 | u16 wbd_ref; | ||
37 | |||
38 | u8 current_band; | ||
39 | fe_bandwidth_t current_bandwidth; | ||
40 | struct dibx000_agc_config *current_agc; | ||
41 | u32 timf; | ||
42 | |||
43 | u16 revision; | ||
44 | }; | ||
45 | |||
46 | enum dib7000m_power_mode { | ||
47 | DIB7000M_POWER_ALL = 0, | ||
48 | |||
49 | DIB7000M_POWER_NO, | ||
50 | DIB7000M_POWER_INTERF_ANALOG_AGC, | ||
51 | DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD, | ||
52 | DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD, | ||
53 | DIB7000M_POWER_INTERFACE_ONLY, | ||
54 | }; | ||
55 | |||
56 | static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg) | ||
57 | { | ||
58 | u8 wb[2] = { (reg >> 8) | 0x80, reg & 0xff }; | ||
59 | u8 rb[2]; | ||
60 | struct i2c_msg msg[2] = { | ||
61 | { .addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2 }, | ||
62 | { .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 }, | ||
63 | }; | ||
64 | |||
65 | if (i2c_transfer(state->i2c_adap, msg, 2) != 2) | ||
66 | dprintk("i2c read error on %d\n",reg); | ||
67 | |||
68 | return (rb[0] << 8) | rb[1]; | ||
69 | } | ||
70 | |||
71 | static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val) | ||
72 | { | ||
73 | u8 b[4] = { | ||
74 | (reg >> 8) & 0xff, reg & 0xff, | ||
75 | (val >> 8) & 0xff, val & 0xff, | ||
76 | }; | ||
77 | struct i2c_msg msg = { | ||
78 | .addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4 | ||
79 | }; | ||
80 | return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; | ||
81 | } | ||
82 | static int dib7000m_set_output_mode(struct dib7000m_state *state, int mode) | ||
83 | { | ||
84 | int ret = 0; | ||
85 | u16 outreg, fifo_threshold, smo_mode, | ||
86 | sram = 0x0005; /* by default SRAM output is disabled */ | ||
87 | |||
88 | outreg = 0; | ||
89 | fifo_threshold = 1792; | ||
90 | smo_mode = (dib7000m_read_word(state, 294 + state->reg_offs) & 0x0010) | (1 << 1); | ||
91 | |||
92 | dprintk("-I- Setting output mode for demod %p to %d\n", | ||
93 | &state->demod, mode); | ||
94 | |||
95 | switch (mode) { | ||
96 | case OUTMODE_MPEG2_PAR_GATED_CLK: // STBs with parallel gated clock | ||
97 | outreg = (1 << 10); /* 0x0400 */ | ||
98 | break; | ||
99 | case OUTMODE_MPEG2_PAR_CONT_CLK: // STBs with parallel continues clock | ||
100 | outreg = (1 << 10) | (1 << 6); /* 0x0440 */ | ||
101 | break; | ||
102 | case OUTMODE_MPEG2_SERIAL: // STBs with serial input | ||
103 | outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0482 */ | ||
104 | break; | ||
105 | case OUTMODE_DIVERSITY: | ||
106 | if (state->cfg.hostbus_diversity) | ||
107 | outreg = (1 << 10) | (4 << 6); /* 0x0500 */ | ||
108 | else | ||
109 | sram |= 0x0c00; | ||
110 | break; | ||
111 | case OUTMODE_MPEG2_FIFO: // e.g. USB feeding | ||
112 | smo_mode |= (3 << 1); | ||
113 | fifo_threshold = 512; | ||
114 | outreg = (1 << 10) | (5 << 6); | ||
115 | break; | ||
116 | case OUTMODE_HIGH_Z: // disable | ||
117 | outreg = 0; | ||
118 | break; | ||
119 | default: | ||
120 | dprintk("Unhandled output_mode passed to be set for demod %p\n",&state->demod); | ||
121 | break; | ||
122 | } | ||
123 | |||
124 | if (state->cfg.output_mpeg2_in_188_bytes) | ||
125 | smo_mode |= (1 << 5) ; | ||
126 | |||
127 | ret |= dib7000m_write_word(state, 294 + state->reg_offs, smo_mode); | ||
128 | ret |= dib7000m_write_word(state, 295 + state->reg_offs, fifo_threshold); /* synchronous fread */ | ||
129 | ret |= dib7000m_write_word(state, 1795, outreg); | ||
130 | ret |= dib7000m_write_word(state, 1805, sram); | ||
131 | |||
132 | return ret; | ||
133 | } | ||
134 | |||
135 | static int dib7000m_set_power_mode(struct dib7000m_state *state, enum dib7000m_power_mode mode) | ||
136 | { | ||
137 | /* by default everything is going to be powered off */ | ||
138 | u16 reg_903 = 0xffff, reg_904 = 0xffff, reg_905 = 0xffff, reg_906 = 0x3fff; | ||
139 | |||
140 | /* now, depending on the requested mode, we power on */ | ||
141 | switch (mode) { | ||
142 | /* power up everything in the demod */ | ||
143 | case DIB7000M_POWER_ALL: | ||
144 | reg_903 = 0x0000; reg_904 = 0x0000; reg_905 = 0x0000; reg_906 = 0x0000; | ||
145 | break; | ||
146 | |||
147 | /* just leave power on the control-interfaces: GPIO and (I2C or SDIO or SRAM) */ | ||
148 | case DIB7000M_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C or SRAM */ | ||
149 | reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 2)); | ||
150 | break; | ||
151 | |||
152 | case DIB7000M_POWER_INTERF_ANALOG_AGC: | ||
153 | reg_903 &= ~((1 << 15) | (1 << 14) | (1 << 11) | (1 << 10)); | ||
154 | reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 4) | (1 << 2)); | ||
155 | reg_906 &= ~((1 << 0)); | ||
156 | break; | ||
157 | |||
158 | case DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD: | ||
159 | reg_903 = 0x0000; reg_904 = 0x801f; reg_905 = 0x0000; reg_906 = 0x0000; | ||
160 | break; | ||
161 | |||
162 | case DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD: | ||
163 | reg_903 = 0x0000; reg_904 = 0x8000; reg_905 = 0x010b; reg_906 = 0x0000; | ||
164 | break; | ||
165 | case DIB7000M_POWER_NO: | ||
166 | break; | ||
167 | } | ||
168 | |||
169 | /* always power down unused parts */ | ||
170 | if (!state->cfg.mobile_mode) | ||
171 | reg_904 |= (1 << 7) | (1 << 6) | (1 << 4) | (1 << 2) | (1 << 1); | ||
172 | |||
173 | /* P_sdio_select_clk = 0 on MC */ | ||
174 | if (state->revision != 0x4000) | ||
175 | reg_906 <<= 1; | ||
176 | |||
177 | dib7000m_write_word(state, 903, reg_903); | ||
178 | dib7000m_write_word(state, 904, reg_904); | ||
179 | dib7000m_write_word(state, 905, reg_905); | ||
180 | dib7000m_write_word(state, 906, reg_906); | ||
181 | |||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | static int dib7000m_set_adc_state(struct dib7000m_state *state, enum dibx000_adc_states no) | ||
186 | { | ||
187 | int ret = 0; | ||
188 | u16 reg_913 = dib7000m_read_word(state, 913), | ||
189 | reg_914 = dib7000m_read_word(state, 914); | ||
190 | |||
191 | switch (no) { | ||
192 | case DIBX000_SLOW_ADC_ON: | ||
193 | reg_914 |= (1 << 1) | (1 << 0); | ||
194 | ret |= dib7000m_write_word(state, 914, reg_914); | ||
195 | reg_914 &= ~(1 << 1); | ||
196 | break; | ||
197 | |||
198 | case DIBX000_SLOW_ADC_OFF: | ||
199 | reg_914 |= (1 << 1) | (1 << 0); | ||
200 | break; | ||
201 | |||
202 | case DIBX000_ADC_ON: | ||
203 | if (state->revision == 0x4000) { // workaround for PA/MA | ||
204 | // power-up ADC | ||
205 | dib7000m_write_word(state, 913, 0); | ||
206 | dib7000m_write_word(state, 914, reg_914 & 0x3); | ||
207 | // power-down bandgag | ||
208 | dib7000m_write_word(state, 913, (1 << 15)); | ||
209 | dib7000m_write_word(state, 914, reg_914 & 0x3); | ||
210 | } | ||
211 | |||
212 | reg_913 &= 0x0fff; | ||
213 | reg_914 &= 0x0003; | ||
214 | break; | ||
215 | |||
216 | case DIBX000_ADC_OFF: // leave the VBG voltage on | ||
217 | reg_913 |= (1 << 14) | (1 << 13) | (1 << 12); | ||
218 | reg_914 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2); | ||
219 | break; | ||
220 | |||
221 | case DIBX000_VBG_ENABLE: | ||
222 | reg_913 &= ~(1 << 15); | ||
223 | break; | ||
224 | |||
225 | case DIBX000_VBG_DISABLE: | ||
226 | reg_913 |= (1 << 15); | ||
227 | break; | ||
228 | |||
229 | default: | ||
230 | break; | ||
231 | } | ||
232 | |||
233 | // dprintk("-D- 913: %x, 914: %x\n", reg_913, reg_914); | ||
234 | |||
235 | ret |= dib7000m_write_word(state, 913, reg_913); | ||
236 | ret |= dib7000m_write_word(state, 914, reg_914); | ||
237 | |||
238 | return ret; | ||
239 | } | ||
240 | |||
241 | static int dib7000m_set_bandwidth(struct dvb_frontend *demod, u8 bw_idx) | ||
242 | { | ||
243 | struct dib7000m_state *state = demod->demodulator_priv; | ||
244 | u32 timf; | ||
245 | |||
246 | // store the current bandwidth for later use | ||
247 | state->current_bandwidth = bw_idx; | ||
248 | |||
249 | if (state->timf == 0) { | ||
250 | dprintk("-D- Using default timf\n"); | ||
251 | timf = state->cfg.bw->timf; | ||
252 | } else { | ||
253 | dprintk("-D- Using updated timf\n"); | ||
254 | timf = state->timf; | ||
255 | } | ||
256 | |||
257 | timf = timf * (BW_INDEX_TO_KHZ(bw_idx) / 100) / 80; | ||
258 | |||
259 | dib7000m_write_word(state, 23, (timf >> 16) & 0xffff); | ||
260 | dib7000m_write_word(state, 24, (timf ) & 0xffff); | ||
261 | |||
262 | return 0; | ||
263 | } | ||
264 | |||
265 | static int dib7000m_sad_calib(struct dib7000m_state *state) | ||
266 | { | ||
267 | |||
268 | /* internal */ | ||
269 | // dib7000m_write_word(state, 928, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is writting in set_bandwidth | ||
270 | dib7000m_write_word(state, 929, (0 << 1) | (0 << 0)); | ||
271 | dib7000m_write_word(state, 930, 776); // 0.625*3.3 / 4096 | ||
272 | |||
273 | /* do the calibration */ | ||
274 | dib7000m_write_word(state, 929, (1 << 0)); | ||
275 | dib7000m_write_word(state, 929, (0 << 0)); | ||
276 | |||
277 | msleep(1); | ||
278 | |||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | static void dib7000m_reset_pll_common(struct dib7000m_state *state, const struct dibx000_bandwidth_config *bw) | ||
283 | { | ||
284 | dib7000m_write_word(state, 18, ((bw->internal*1000) >> 16) & 0xffff); | ||
285 | dib7000m_write_word(state, 19, (bw->internal*1000) & 0xffff); | ||
286 | dib7000m_write_word(state, 21, (bw->ifreq >> 16) & 0xffff); | ||
287 | dib7000m_write_word(state, 22, bw->ifreq & 0xffff); | ||
288 | |||
289 | dib7000m_write_word(state, 928, bw->sad_cfg); | ||
290 | } | ||
291 | |||
292 | static void dib7000m_reset_pll(struct dib7000m_state *state) | ||
293 | { | ||
294 | const struct dibx000_bandwidth_config *bw = state->cfg.bw; | ||
295 | u16 reg_907,reg_910; | ||
296 | |||
297 | /* default */ | ||
298 | reg_907 = (bw->pll_bypass << 15) | (bw->modulo << 7) | | ||
299 | (bw->ADClkSrc << 6) | (bw->IO_CLK_en_core << 5) | (bw->bypclk_div << 2) | | ||
300 | (bw->enable_refdiv << 1) | (0 << 0); | ||
301 | reg_910 = (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset; | ||
302 | |||
303 | // for this oscillator frequency should be 30 MHz for the Master (default values in the board_parameters give that value) | ||
304 | // this is only working only for 30 MHz crystals | ||
305 | if (!state->cfg.quartz_direct) { | ||
306 | reg_910 |= (1 << 5); // forcing the predivider to 1 | ||
307 | |||
308 | // if the previous front-end is baseband, its output frequency is 15 MHz (prev freq divided by 2) | ||
309 | if(state->cfg.input_clk_is_div_2) | ||
310 | reg_907 |= (16 << 9); | ||
311 | else // otherwise the previous front-end puts out its input (default 30MHz) - no extra division necessary | ||
312 | reg_907 |= (8 << 9); | ||
313 | } else { | ||
314 | reg_907 |= (bw->pll_ratio & 0x3f) << 9; | ||
315 | reg_910 |= (bw->pll_prediv << 5); | ||
316 | } | ||
317 | |||
318 | dib7000m_write_word(state, 910, reg_910); // pll cfg | ||
319 | dib7000m_write_word(state, 907, reg_907); // clk cfg0 | ||
320 | dib7000m_write_word(state, 908, 0x0006); // clk_cfg1 | ||
321 | |||
322 | dib7000m_reset_pll_common(state, bw); | ||
323 | } | ||
324 | |||
325 | static void dib7000mc_reset_pll(struct dib7000m_state *state) | ||
326 | { | ||
327 | const struct dibx000_bandwidth_config *bw = state->cfg.bw; | ||
328 | |||
329 | // clk_cfg0 | ||
330 | dib7000m_write_word(state, 907, (bw->pll_prediv << 8) | (bw->pll_ratio << 0)); | ||
331 | |||
332 | // clk_cfg1 | ||
333 | //dib7000m_write_word(state, 908, (1 << 14) | (3 << 12) |(0 << 11) | | ||
334 | dib7000m_write_word(state, 908, (0 << 14) | (3 << 12) |(0 << 11) | | ||
335 | (bw->IO_CLK_en_core << 10) | (bw->bypclk_div << 5) | (bw->enable_refdiv << 4) | | ||
336 | (bw->pll_bypass << 3) | (bw->pll_range << 1) | (bw->pll_reset << 0)); | ||
337 | |||
338 | // smpl_cfg | ||
339 | dib7000m_write_word(state, 910, (1 << 12) | (2 << 10) | (bw->modulo << 8) | (bw->ADClkSrc << 7)); | ||
340 | |||
341 | dib7000m_reset_pll_common(state, bw); | ||
342 | } | ||
343 | |||
344 | static int dib7000m_reset_gpio(struct dib7000m_state *st) | ||
345 | { | ||
346 | /* reset the GPIOs */ | ||
347 | dprintk("-D- gpio dir: %x: gpio val: %x, gpio pwm pos: %x\n", | ||
348 | st->cfg.gpio_dir, st->cfg.gpio_val,st->cfg.gpio_pwm_pos); | ||
349 | |||
350 | dib7000m_write_word(st, 773, st->cfg.gpio_dir); | ||
351 | dib7000m_write_word(st, 774, st->cfg.gpio_val); | ||
352 | |||
353 | /* TODO 782 is P_gpio_od */ | ||
354 | |||
355 | dib7000m_write_word(st, 775, st->cfg.gpio_pwm_pos); | ||
356 | |||
357 | dib7000m_write_word(st, 780, st->cfg.pwm_freq_div); | ||
358 | return 0; | ||
359 | } | ||
360 | |||
361 | static int dib7000m_demod_reset(struct dib7000m_state *state) | ||
362 | { | ||
363 | dib7000m_set_power_mode(state, DIB7000M_POWER_ALL); | ||
364 | |||
365 | /* always leave the VBG voltage on - it consumes almost nothing but takes a long time to start */ | ||
366 | dib7000m_set_adc_state(state, DIBX000_VBG_ENABLE); | ||
367 | |||
368 | /* restart all parts */ | ||
369 | dib7000m_write_word(state, 898, 0xffff); | ||
370 | dib7000m_write_word(state, 899, 0xffff); | ||
371 | dib7000m_write_word(state, 900, 0xff0f); | ||
372 | dib7000m_write_word(state, 901, 0xfffc); | ||
373 | |||
374 | dib7000m_write_word(state, 898, 0); | ||
375 | dib7000m_write_word(state, 899, 0); | ||
376 | dib7000m_write_word(state, 900, 0); | ||
377 | dib7000m_write_word(state, 901, 0); | ||
378 | |||
379 | if (state->revision == 0x4000) | ||
380 | dib7000m_reset_pll(state); | ||
381 | else | ||
382 | dib7000mc_reset_pll(state); | ||
383 | |||
384 | if (dib7000m_reset_gpio(state) != 0) | ||
385 | dprintk("-E- GPIO reset was not successful.\n"); | ||
386 | |||
387 | if (dib7000m_set_output_mode(state, OUTMODE_HIGH_Z) != 0) | ||
388 | dprintk("-E- OUTPUT_MODE could not be resetted.\n"); | ||
389 | |||
390 | /* unforce divstr regardless whether i2c enumeration was done or not */ | ||
391 | dib7000m_write_word(state, 1794, dib7000m_read_word(state, 1794) & ~(1 << 1) ); | ||
392 | |||
393 | dib7000m_set_bandwidth(&state->demod, BANDWIDTH_8_MHZ); | ||
394 | |||
395 | dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON); | ||
396 | dib7000m_sad_calib(state); | ||
397 | dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_OFF); | ||
398 | |||
399 | dib7000m_set_power_mode(state, DIB7000M_POWER_INTERFACE_ONLY); | ||
400 | |||
401 | return 0; | ||
402 | } | ||
403 | |||
404 | static void dib7000m_restart_agc(struct dib7000m_state *state) | ||
405 | { | ||
406 | // P_restart_iqc & P_restart_agc | ||
407 | dib7000m_write_word(state, 898, 0x0c00); | ||
408 | dib7000m_write_word(state, 898, 0x0000); | ||
409 | } | ||
410 | |||
411 | static int dib7000m_agc_soft_split(struct dib7000m_state *state) | ||
412 | { | ||
413 | u16 agc,split_offset; | ||
414 | |||
415 | if(!state->current_agc || !state->current_agc->perform_agc_softsplit || state->current_agc->split.max == 0) | ||
416 | return 0; | ||
417 | |||
418 | // n_agc_global | ||
419 | agc = dib7000m_read_word(state, 390); | ||
420 | |||
421 | if (agc > state->current_agc->split.min_thres) | ||
422 | split_offset = state->current_agc->split.min; | ||
423 | else if (agc < state->current_agc->split.max_thres) | ||
424 | split_offset = state->current_agc->split.max; | ||
425 | else | ||
426 | split_offset = state->current_agc->split.max * | ||
427 | (agc - state->current_agc->split.min_thres) / | ||
428 | (state->current_agc->split.max_thres - state->current_agc->split.min_thres); | ||
429 | |||
430 | dprintk("AGC split_offset: %d\n",split_offset); | ||
431 | |||
432 | // P_agc_force_split and P_agc_split_offset | ||
433 | return dib7000m_write_word(state, 103, (dib7000m_read_word(state, 103) & 0xff00) | split_offset); | ||
434 | } | ||
435 | |||
436 | static int dib7000m_update_lna(struct dib7000m_state *state) | ||
437 | { | ||
438 | int i; | ||
439 | u16 dyn_gain; | ||
440 | |||
441 | // when there is no LNA to program return immediatly | ||
442 | if (state->cfg.update_lna == NULL) | ||
443 | return 0; | ||
444 | |||
445 | msleep(60); | ||
446 | for (i = 0; i < 20; i++) { | ||
447 | // read dyn_gain here (because it is demod-dependent and not tuner) | ||
448 | dyn_gain = dib7000m_read_word(state, 390); | ||
449 | |||
450 | dprintk("agc global: %d\n", dyn_gain); | ||
451 | |||
452 | if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed | ||
453 | dib7000m_restart_agc(state); | ||
454 | msleep(60); | ||
455 | } else | ||
456 | break; | ||
457 | } | ||
458 | return 0; | ||
459 | } | ||
460 | |||
461 | static void dib7000m_set_agc_config(struct dib7000m_state *state, u8 band) | ||
462 | { | ||
463 | struct dibx000_agc_config *agc = NULL; | ||
464 | int i; | ||
465 | if (state->current_band == band) | ||
466 | return; | ||
467 | state->current_band = band; | ||
468 | |||
469 | for (i = 0; i < state->cfg.agc_config_count; i++) | ||
470 | if (state->cfg.agc[i].band_caps & band) { | ||
471 | agc = &state->cfg.agc[i]; | ||
472 | break; | ||
473 | } | ||
474 | |||
475 | if (agc == NULL) { | ||
476 | dprintk("-E- No valid AGC configuration found for band 0x%02x\n",band); | ||
477 | return; | ||
478 | } | ||
479 | |||
480 | state->current_agc = agc; | ||
481 | |||
482 | /* AGC */ | ||
483 | dib7000m_write_word(state, 72 , agc->setup); | ||
484 | dib7000m_write_word(state, 73 , agc->inv_gain); | ||
485 | dib7000m_write_word(state, 74 , agc->time_stabiliz); | ||
486 | dib7000m_write_word(state, 97 , (agc->alpha_level << 12) | agc->thlock); | ||
487 | |||
488 | // Demod AGC loop configuration | ||
489 | dib7000m_write_word(state, 98, (agc->alpha_mant << 5) | agc->alpha_exp); | ||
490 | dib7000m_write_word(state, 99, (agc->beta_mant << 6) | agc->beta_exp); | ||
491 | |||
492 | dprintk("-D- WBD: ref: %d, sel: %d, active: %d, alpha: %d\n", | ||
493 | state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel); | ||
494 | |||
495 | /* AGC continued */ | ||
496 | if (state->wbd_ref != 0) | ||
497 | dib7000m_write_word(state, 102, state->wbd_ref); | ||
498 | else // use default | ||
499 | dib7000m_write_word(state, 102, agc->wbd_ref); | ||
500 | |||
501 | dib7000m_write_word(state, 103, (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8) ); | ||
502 | dib7000m_write_word(state, 104, agc->agc1_max); | ||
503 | dib7000m_write_word(state, 105, agc->agc1_min); | ||
504 | dib7000m_write_word(state, 106, agc->agc2_max); | ||
505 | dib7000m_write_word(state, 107, agc->agc2_min); | ||
506 | dib7000m_write_word(state, 108, (agc->agc1_pt1 << 8) | agc->agc1_pt2 ); | ||
507 | dib7000m_write_word(state, 109, (agc->agc1_slope1 << 8) | agc->agc1_slope2); | ||
508 | dib7000m_write_word(state, 110, (agc->agc2_pt1 << 8) | agc->agc2_pt2); | ||
509 | dib7000m_write_word(state, 111, (agc->agc2_slope1 << 8) | agc->agc2_slope2); | ||
510 | |||
511 | if (state->revision > 0x4000) { // settings for the MC | ||
512 | dib7000m_write_word(state, 71, agc->agc1_pt3); | ||
513 | // dprintk("-D- 929: %x %d %d\n", | ||
514 | // (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2), agc->wbd_inv, agc->wbd_sel); | ||
515 | dib7000m_write_word(state, 929, (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2)); | ||
516 | } else { | ||
517 | // wrong default values | ||
518 | u16 b[9] = { 676, 696, 717, 737, 758, 778, 799, 819, 840 }; | ||
519 | for (i = 0; i < 9; i++) | ||
520 | dib7000m_write_word(state, 88 + i, b[i]); | ||
521 | } | ||
522 | } | ||
523 | |||
524 | static void dib7000m_update_timf_freq(struct dib7000m_state *state) | ||
525 | { | ||
526 | u32 timf = (dib7000m_read_word(state, 436) << 16) | dib7000m_read_word(state, 437); | ||
527 | state->timf = timf * 80 / (BW_INDEX_TO_KHZ(state->current_bandwidth) / 100); | ||
528 | dib7000m_write_word(state, 23, (u16) (timf >> 16)); | ||
529 | dib7000m_write_word(state, 24, (u16) (timf & 0xffff)); | ||
530 | dprintk("-D- Updated timf_frequency: %d (default: %d)\n",state->timf, state->cfg.bw->timf); | ||
531 | } | ||
532 | |||
533 | static void dib7000m_set_channel(struct dib7000m_state *state, struct dibx000_ofdm_channel *ch, u8 seq) | ||
534 | { | ||
535 | u16 value, est[4]; | ||
536 | |||
537 | dib7000m_set_agc_config(state, BAND_OF_FREQUENCY(ch->RF_kHz)); | ||
538 | |||
539 | /* nfft, guard, qam, alpha */ | ||
540 | dib7000m_write_word(state, 0, (ch->nfft << 7) | (ch->guard << 5) | (ch->nqam << 3) | (ch->vit_alpha)); | ||
541 | dib7000m_write_word(state, 5, (seq << 4)); | ||
542 | |||
543 | /* P_dintl_native, P_dintlv_inv, P_vit_hrch, P_vit_code_rate, P_vit_select_hp */ | ||
544 | value = (ch->intlv_native << 6) | (ch->vit_hrch << 4) | (ch->vit_select_hp & 0x1); | ||
545 | if (ch->vit_hrch == 0 || ch->vit_select_hp == 1) | ||
546 | value |= (ch->vit_code_rate_hp << 1); | ||
547 | else | ||
548 | value |= (ch->vit_code_rate_lp << 1); | ||
549 | dib7000m_write_word(state, 267 + state->reg_offs, value); | ||
550 | |||
551 | /* offset loop parameters */ | ||
552 | |||
553 | /* P_timf_alpha = 6, P_corm_alpha=6, P_corm_thres=0x80 */ | ||
554 | dib7000m_write_word(state, 26, (6 << 12) | (6 << 8) | 0x80); | ||
555 | |||
556 | /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=1, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */ | ||
557 | dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (1 << 9) | (3 << 5) | (1 << 4) | (0x3)); | ||
558 | |||
559 | /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max=3 */ | ||
560 | dib7000m_write_word(state, 32, (0 << 4) | 0x3); | ||
561 | |||
562 | /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step=5 */ | ||
563 | dib7000m_write_word(state, 33, (0 << 4) | 0x5); | ||
564 | |||
565 | /* P_dvsy_sync_wait */ | ||
566 | switch (ch->nfft) { | ||
567 | case 1: value = 256; break; | ||
568 | case 2: value = 128; break; | ||
569 | case 0: | ||
570 | default: value = 64; break; | ||
571 | } | ||
572 | value *= ((1 << (ch->guard)) * 3 / 2); // add 50% SFN margin | ||
573 | value <<= 4; | ||
574 | |||
575 | /* deactive the possibility of diversity reception if extended interleave - not for 7000MC */ | ||
576 | /* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */ | ||
577 | if (ch->intlv_native || state->revision > 0x4000) | ||
578 | value |= (1 << 2) | (2 << 0); | ||
579 | else | ||
580 | value |= 0; | ||
581 | dib7000m_write_word(state, 266 + state->reg_offs, value); | ||
582 | |||
583 | /* channel estimation fine configuration */ | ||
584 | switch (ch->nqam) { | ||
585 | case 2: | ||
586 | est[0] = 0x0148; /* P_adp_regul_cnt 0.04 */ | ||
587 | est[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */ | ||
588 | est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ | ||
589 | est[3] = 0xfff8; /* P_adp_noise_ext -0.001 */ | ||
590 | break; | ||
591 | case 1: | ||
592 | est[0] = 0x023d; /* P_adp_regul_cnt 0.07 */ | ||
593 | est[1] = 0xffdf; /* P_adp_noise_cnt -0.004 */ | ||
594 | est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ | ||
595 | est[3] = 0xfff0; /* P_adp_noise_ext -0.002 */ | ||
596 | break; | ||
597 | default: | ||
598 | est[0] = 0x099a; /* P_adp_regul_cnt 0.3 */ | ||
599 | est[1] = 0xffae; /* P_adp_noise_cnt -0.01 */ | ||
600 | est[2] = 0x0333; /* P_adp_regul_ext 0.1 */ | ||
601 | est[3] = 0xfff8; /* P_adp_noise_ext -0.002 */ | ||
602 | break; | ||
603 | } | ||
604 | for (value = 0; value < 4; value++) | ||
605 | dib7000m_write_word(state, 214 + value + state->reg_offs, est[value]); | ||
606 | |||
607 | // set power-up level: interf+analog+AGC | ||
608 | dib7000m_set_power_mode(state, DIB7000M_POWER_INTERF_ANALOG_AGC); | ||
609 | dib7000m_set_adc_state(state, DIBX000_ADC_ON); | ||
610 | |||
611 | msleep(7); | ||
612 | |||
613 | //AGC initialization | ||
614 | if (state->cfg.agc_control) | ||
615 | state->cfg.agc_control(&state->demod, 1); | ||
616 | |||
617 | dib7000m_restart_agc(state); | ||
618 | |||
619 | // wait AGC rough lock time | ||
620 | msleep(5); | ||
621 | |||
622 | dib7000m_update_lna(state); | ||
623 | dib7000m_agc_soft_split(state); | ||
624 | |||
625 | // wait AGC accurate lock time | ||
626 | msleep(7); | ||
627 | |||
628 | if (state->cfg.agc_control) | ||
629 | state->cfg.agc_control(&state->demod, 0); | ||
630 | |||
631 | // set power-up level: autosearch | ||
632 | dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD); | ||
633 | } | ||
634 | |||
635 | static int dib7000m_autosearch_start(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch) | ||
636 | { | ||
637 | struct dib7000m_state *state = demod->demodulator_priv; | ||
638 | struct dibx000_ofdm_channel auto_ch; | ||
639 | int ret = 0; | ||
640 | u32 value; | ||
641 | |||
642 | INIT_OFDM_CHANNEL(&auto_ch); | ||
643 | auto_ch.RF_kHz = ch->RF_kHz; | ||
644 | auto_ch.Bw = ch->Bw; | ||
645 | auto_ch.nqam = 2; | ||
646 | auto_ch.guard = 0; | ||
647 | auto_ch.nfft = 1; | ||
648 | auto_ch.vit_alpha = 1; | ||
649 | auto_ch.vit_select_hp = 1; | ||
650 | auto_ch.vit_code_rate_hp = 2; | ||
651 | auto_ch.vit_code_rate_lp = 3; | ||
652 | auto_ch.vit_hrch = 0; | ||
653 | auto_ch.intlv_native = 1; | ||
654 | |||
655 | dib7000m_set_channel(state, &auto_ch, 7); | ||
656 | |||
657 | // always use the setting for 8MHz here lock_time for 7,6 MHz are longer | ||
658 | value = 30 * state->cfg.bw->internal; | ||
659 | ret |= dib7000m_write_word(state, 6, (u16) ((value >> 16) & 0xffff)); // lock0 wait time | ||
660 | ret |= dib7000m_write_word(state, 7, (u16) (value & 0xffff)); // lock0 wait time | ||
661 | value = 100 * state->cfg.bw->internal; | ||
662 | ret |= dib7000m_write_word(state, 8, (u16) ((value >> 16) & 0xffff)); // lock1 wait time | ||
663 | ret |= dib7000m_write_word(state, 9, (u16) (value & 0xffff)); // lock1 wait time | ||
664 | value = 500 * state->cfg.bw->internal; | ||
665 | ret |= dib7000m_write_word(state, 10, (u16) ((value >> 16) & 0xffff)); // lock2 wait time | ||
666 | ret |= dib7000m_write_word(state, 11, (u16) (value & 0xffff)); // lock2 wait time | ||
667 | |||
668 | // start search | ||
669 | value = dib7000m_read_word(state, 0); | ||
670 | ret |= dib7000m_write_word(state, 0, value | (1 << 9)); | ||
671 | |||
672 | /* clear n_irq_pending */ | ||
673 | if (state->revision == 0x4000) | ||
674 | dib7000m_write_word(state, 1793, 0); | ||
675 | else | ||
676 | dib7000m_read_word(state, 537); | ||
677 | |||
678 | ret |= dib7000m_write_word(state, 0, (u16) value); | ||
679 | |||
680 | return ret; | ||
681 | } | ||
682 | |||
683 | static int dib7000m_autosearch_irq(struct dib7000m_state *state, u16 reg) | ||
684 | { | ||
685 | u16 irq_pending = dib7000m_read_word(state, reg); | ||
686 | |||
687 | if (irq_pending & 0x1) { // failed | ||
688 | dprintk("#\n"); | ||
689 | return 1; | ||
690 | } | ||
691 | |||
692 | if (irq_pending & 0x2) { // succeeded | ||
693 | dprintk("!\n"); | ||
694 | return 2; | ||
695 | } | ||
696 | return 0; // still pending | ||
697 | } | ||
698 | |||
699 | static int dib7000m_autosearch_is_irq(struct dvb_frontend *demod) | ||
700 | { | ||
701 | struct dib7000m_state *state = demod->demodulator_priv; | ||
702 | if (state->revision == 0x4000) | ||
703 | return dib7000m_autosearch_irq(state, 1793); | ||
704 | else | ||
705 | return dib7000m_autosearch_irq(state, 537); | ||
706 | } | ||
707 | |||
708 | static int dib7000m_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch) | ||
709 | { | ||
710 | struct dib7000m_state *state = demod->demodulator_priv; | ||
711 | int ret = 0; | ||
712 | u16 value; | ||
713 | |||
714 | // we are already tuned - just resuming from suspend | ||
715 | if (ch != NULL) | ||
716 | dib7000m_set_channel(state, ch, 0); | ||
717 | else | ||
718 | return -EINVAL; | ||
719 | |||
720 | // restart demod | ||
721 | ret |= dib7000m_write_word(state, 898, 0x4000); | ||
722 | ret |= dib7000m_write_word(state, 898, 0x0000); | ||
723 | msleep(45); | ||
724 | |||
725 | ret |= dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD); | ||
726 | /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */ | ||
727 | ret |= dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3)); | ||
728 | |||
729 | // never achieved a lock with that bandwidth so far - wait for timfreq to update | ||
730 | if (state->timf == 0) | ||
731 | msleep(200); | ||
732 | |||
733 | //dump_reg(state); | ||
734 | /* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */ | ||
735 | value = (6 << 8) | 0x80; | ||
736 | switch (ch->nfft) { | ||
737 | case 0: value |= (7 << 12); break; | ||
738 | case 1: value |= (9 << 12); break; | ||
739 | case 2: value |= (8 << 12); break; | ||
740 | } | ||
741 | ret |= dib7000m_write_word(state, 26, value); | ||
742 | |||
743 | /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */ | ||
744 | value = (0 << 4); | ||
745 | switch (ch->nfft) { | ||
746 | case 0: value |= 0x6; break; | ||
747 | case 1: value |= 0x8; break; | ||
748 | case 2: value |= 0x7; break; | ||
749 | } | ||
750 | ret |= dib7000m_write_word(state, 32, value); | ||
751 | |||
752 | /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */ | ||
753 | value = (0 << 4); | ||
754 | switch (ch->nfft) { | ||
755 | case 0: value |= 0x6; break; | ||
756 | case 1: value |= 0x8; break; | ||
757 | case 2: value |= 0x7; break; | ||
758 | } | ||
759 | ret |= dib7000m_write_word(state, 33, value); | ||
760 | |||
761 | // we achieved a lock - it's time to update the osc freq | ||
762 | if ((dib7000m_read_word(state, 535) >> 6) & 0x1) | ||
763 | dib7000m_update_timf_freq(state); | ||
764 | |||
765 | return ret; | ||
766 | } | ||
767 | |||
768 | static int dib7000m_init(struct dvb_frontend *demod) | ||
769 | { | ||
770 | struct dib7000m_state *state = demod->demodulator_priv; | ||
771 | int ret = 0; | ||
772 | u8 o = state->reg_offs; | ||
773 | |||
774 | dib7000m_set_power_mode(state, DIB7000M_POWER_ALL); | ||
775 | |||
776 | if (dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0) | ||
777 | dprintk("-E- could not start Slow ADC\n"); | ||
778 | |||
779 | if (state->cfg.dvbt_mode) | ||
780 | dib7000m_write_word(state, 1796, 0x0); // select DVB-T output | ||
781 | |||
782 | if (state->cfg.mobile_mode) | ||
783 | ret |= dib7000m_write_word(state, 261 + o, 2); | ||
784 | else | ||
785 | ret |= dib7000m_write_word(state, 224 + o, 1); | ||
786 | |||
787 | ret |= dib7000m_write_word(state, 173 + o, 0); | ||
788 | ret |= dib7000m_write_word(state, 174 + o, 0); | ||
789 | ret |= dib7000m_write_word(state, 175 + o, 0); | ||
790 | ret |= dib7000m_write_word(state, 176 + o, 0); | ||
791 | ret |= dib7000m_write_word(state, 177 + o, 0); | ||
792 | ret |= dib7000m_write_word(state, 178 + o, 0); | ||
793 | ret |= dib7000m_write_word(state, 179 + o, 0); | ||
794 | ret |= dib7000m_write_word(state, 180 + o, 0); | ||
795 | |||
796 | // P_corm_thres Lock algorithms configuration | ||
797 | ret |= dib7000m_write_word(state, 26, 0x6680); | ||
798 | |||
799 | // P_palf_alpha_regul, P_palf_filter_freeze, P_palf_filter_on | ||
800 | ret |= dib7000m_write_word(state, 170 + o, 0x0410); | ||
801 | // P_fft_nb_to_cut | ||
802 | ret |= dib7000m_write_word(state, 182 + o, 8192); | ||
803 | // P_pha3_thres | ||
804 | ret |= dib7000m_write_word(state, 195 + o, 0x0ccd); | ||
805 | // P_cti_use_cpe, P_cti_use_prog | ||
806 | ret |= dib7000m_write_word(state, 196 + o, 0); | ||
807 | // P_cspu_regul, P_cspu_win_cut | ||
808 | ret |= dib7000m_write_word(state, 205 + o, 0x200f); | ||
809 | // P_adp_regul_cnt | ||
810 | ret |= dib7000m_write_word(state, 214 + o, 0x023d); | ||
811 | // P_adp_noise_cnt | ||
812 | ret |= dib7000m_write_word(state, 215 + o, 0x00a4); | ||
813 | // P_adp_regul_ext | ||
814 | ret |= dib7000m_write_word(state, 216 + o, 0x00a4); | ||
815 | // P_adp_noise_ext | ||
816 | ret |= dib7000m_write_word(state, 217 + o, 0x7ff0); | ||
817 | // P_adp_fil | ||
818 | ret |= dib7000m_write_word(state, 218 + o, 0x3ccc); | ||
819 | |||
820 | // P_2d_byp_ti_num | ||
821 | ret |= dib7000m_write_word(state, 226 + o, 0); | ||
822 | |||
823 | // P_fec_* | ||
824 | ret |= dib7000m_write_word(state, 281 + o, 0x0010); | ||
825 | // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard | ||
826 | ret |= dib7000m_write_word(state, 294 + o,0x0062); | ||
827 | |||
828 | // P_iqc_alpha_pha, P_iqc_alpha_amp, P_iqc_dcc_alpha, ... | ||
829 | if(state->cfg.tuner_is_baseband) | ||
830 | ret |= dib7000m_write_word(state, 36, 0x0755); | ||
831 | else | ||
832 | ret |= dib7000m_write_word(state, 36, 0x1f55); | ||
833 | |||
834 | // auto search configuration | ||
835 | ret |= dib7000m_write_word(state, 2, 0x0004); | ||
836 | ret |= dib7000m_write_word(state, 3, 0x1000); | ||
837 | ret |= dib7000m_write_word(state, 4, 0x0814); | ||
838 | ret |= dib7000m_write_word(state, 6, 0x001b); | ||
839 | ret |= dib7000m_write_word(state, 7, 0x7740); | ||
840 | ret |= dib7000m_write_word(state, 8, 0x005b); | ||
841 | ret |= dib7000m_write_word(state, 9, 0x8d80); | ||
842 | ret |= dib7000m_write_word(state, 10, 0x01c9); | ||
843 | ret |= dib7000m_write_word(state, 11, 0xc380); | ||
844 | ret |= dib7000m_write_word(state, 12, 0x0000); | ||
845 | ret |= dib7000m_write_word(state, 13, 0x0080); | ||
846 | ret |= dib7000m_write_word(state, 14, 0x0000); | ||
847 | ret |= dib7000m_write_word(state, 15, 0x0090); | ||
848 | ret |= dib7000m_write_word(state, 16, 0x0001); | ||
849 | ret |= dib7000m_write_word(state, 17, 0xd4c0); | ||
850 | ret |= dib7000m_write_word(state, 263 + o,0x0001); | ||
851 | |||
852 | // P_divclksel=3 P_divbitsel=1 | ||
853 | if (state->revision == 0x4000) | ||
854 | dib7000m_write_word(state, 909, (3 << 10) | (1 << 6)); | ||
855 | else | ||
856 | dib7000m_write_word(state, 909, (3 << 4) | 1); | ||
857 | |||
858 | // Tuner IO bank: max drive (14mA) | ||
859 | ret |= dib7000m_write_word(state, 912 ,0x2c8a); | ||
860 | |||
861 | ret |= dib7000m_write_word(state, 1817, 1); | ||
862 | |||
863 | return ret; | ||
864 | } | ||
865 | |||
866 | static int dib7000m_sleep(struct dvb_frontend *demod) | ||
867 | { | ||
868 | struct dib7000m_state *st = demod->demodulator_priv; | ||
869 | dib7000m_set_output_mode(st, OUTMODE_HIGH_Z); | ||
870 | return dib7000m_set_power_mode(st, DIB7000M_POWER_INTERFACE_ONLY) | | ||
871 | dib7000m_set_adc_state(st, DIBX000_SLOW_ADC_OFF) | | ||
872 | dib7000m_set_adc_state(st, DIBX000_ADC_OFF); | ||
873 | } | ||
874 | |||
875 | static int dib7000m_identify(struct dib7000m_state *state) | ||
876 | { | ||
877 | u16 value; | ||
878 | if ((value = dib7000m_read_word(state, 896)) != 0x01b3) { | ||
879 | dprintk("-E- DiB7000M: wrong Vendor ID (read=0x%x)\n",value); | ||
880 | return -EREMOTEIO; | ||
881 | } | ||
882 | |||
883 | state->revision = dib7000m_read_word(state, 897); | ||
884 | if (state->revision != 0x4000 && | ||
885 | state->revision != 0x4001 && | ||
886 | state->revision != 0x4002) { | ||
887 | dprintk("-E- DiB7000M: wrong Device ID (%x)\n",value); | ||
888 | return -EREMOTEIO; | ||
889 | } | ||
890 | |||
891 | /* protect this driver to be used with 7000PC */ | ||
892 | if (state->revision == 0x4000 && dib7000m_read_word(state, 769) == 0x4000) { | ||
893 | dprintk("-E- DiB7000M: this driver does not work with DiB7000PC\n"); | ||
894 | return -EREMOTEIO; | ||
895 | } | ||
896 | |||
897 | switch (state->revision) { | ||
898 | case 0x4000: dprintk("-I- found DiB7000MA/PA/MB/PB\n"); break; | ||
899 | case 0x4001: state->reg_offs = 1; dprintk("-I- found DiB7000HC\n"); break; | ||
900 | case 0x4002: state->reg_offs = 1; dprintk("-I- found DiB7000MC\n"); break; | ||
901 | } | ||
902 | |||
903 | return 0; | ||
904 | } | ||
905 | |||
906 | |||
907 | static int dib7000m_get_frontend(struct dvb_frontend* fe, | ||
908 | struct dvb_frontend_parameters *fep) | ||
909 | { | ||
910 | struct dib7000m_state *state = fe->demodulator_priv; | ||
911 | u16 tps = dib7000m_read_word(state,480); | ||
912 | |||
913 | fep->inversion = INVERSION_AUTO; | ||
914 | |||
915 | fep->u.ofdm.bandwidth = state->current_bandwidth; | ||
916 | |||
917 | switch ((tps >> 8) & 0x3) { | ||
918 | case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break; | ||
919 | case 1: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; break; | ||
920 | /* case 2: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_4K; break; */ | ||
921 | } | ||
922 | |||
923 | switch (tps & 0x3) { | ||
924 | case 0: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break; | ||
925 | case 1: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; break; | ||
926 | case 2: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; break; | ||
927 | case 3: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; break; | ||
928 | } | ||
929 | |||
930 | switch ((tps >> 14) & 0x3) { | ||
931 | case 0: fep->u.ofdm.constellation = QPSK; break; | ||
932 | case 1: fep->u.ofdm.constellation = QAM_16; break; | ||
933 | case 2: | ||
934 | default: fep->u.ofdm.constellation = QAM_64; break; | ||
935 | } | ||
936 | |||
937 | /* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */ | ||
938 | /* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */ | ||
939 | |||
940 | fep->u.ofdm.hierarchy_information = HIERARCHY_NONE; | ||
941 | switch ((tps >> 5) & 0x7) { | ||
942 | case 1: fep->u.ofdm.code_rate_HP = FEC_1_2; break; | ||
943 | case 2: fep->u.ofdm.code_rate_HP = FEC_2_3; break; | ||
944 | case 3: fep->u.ofdm.code_rate_HP = FEC_3_4; break; | ||
945 | case 5: fep->u.ofdm.code_rate_HP = FEC_5_6; break; | ||
946 | case 7: | ||
947 | default: fep->u.ofdm.code_rate_HP = FEC_7_8; break; | ||
948 | |||
949 | } | ||
950 | |||
951 | switch ((tps >> 2) & 0x7) { | ||
952 | case 1: fep->u.ofdm.code_rate_LP = FEC_1_2; break; | ||
953 | case 2: fep->u.ofdm.code_rate_LP = FEC_2_3; break; | ||
954 | case 3: fep->u.ofdm.code_rate_LP = FEC_3_4; break; | ||
955 | case 5: fep->u.ofdm.code_rate_LP = FEC_5_6; break; | ||
956 | case 7: | ||
957 | default: fep->u.ofdm.code_rate_LP = FEC_7_8; break; | ||
958 | } | ||
959 | |||
960 | /* native interleaver: (dib7000m_read_word(state, 481) >> 5) & 0x1 */ | ||
961 | |||
962 | return 0; | ||
963 | } | ||
964 | |||
965 | static int dib7000m_set_frontend(struct dvb_frontend* fe, | ||
966 | struct dvb_frontend_parameters *fep) | ||
967 | { | ||
968 | struct dib7000m_state *state = fe->demodulator_priv; | ||
969 | struct dibx000_ofdm_channel ch; | ||
970 | |||
971 | INIT_OFDM_CHANNEL(&ch); | ||
972 | FEP2DIB(fep,&ch); | ||
973 | |||
974 | state->current_bandwidth = fep->u.ofdm.bandwidth; | ||
975 | dib7000m_set_bandwidth(fe, fep->u.ofdm.bandwidth); | ||
976 | |||
977 | if (fe->ops.tuner_ops.set_params) | ||
978 | fe->ops.tuner_ops.set_params(fe, fep); | ||
979 | |||
980 | if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO || | ||
981 | fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO || | ||
982 | fep->u.ofdm.constellation == QAM_AUTO || | ||
983 | fep->u.ofdm.code_rate_HP == FEC_AUTO) { | ||
984 | int i = 800, found; | ||
985 | |||
986 | dib7000m_autosearch_start(fe, &ch); | ||
987 | do { | ||
988 | msleep(1); | ||
989 | found = dib7000m_autosearch_is_irq(fe); | ||
990 | } while (found == 0 && i--); | ||
991 | |||
992 | dprintk("autosearch returns: %d\n",found); | ||
993 | if (found == 0 || found == 1) | ||
994 | return 0; // no channel found | ||
995 | |||
996 | dib7000m_get_frontend(fe, fep); | ||
997 | FEP2DIB(fep, &ch); | ||
998 | } | ||
999 | |||
1000 | /* make this a config parameter */ | ||
1001 | dib7000m_set_output_mode(state, OUTMODE_MPEG2_FIFO); | ||
1002 | |||
1003 | return dib7000m_tune(fe, &ch); | ||
1004 | } | ||
1005 | |||
1006 | static int dib7000m_read_status(struct dvb_frontend *fe, fe_status_t *stat) | ||
1007 | { | ||
1008 | struct dib7000m_state *state = fe->demodulator_priv; | ||
1009 | u16 lock = dib7000m_read_word(state, 535); | ||
1010 | |||
1011 | *stat = 0; | ||
1012 | |||
1013 | if (lock & 0x8000) | ||
1014 | *stat |= FE_HAS_SIGNAL; | ||
1015 | if (lock & 0x3000) | ||
1016 | *stat |= FE_HAS_CARRIER; | ||
1017 | if (lock & 0x0100) | ||
1018 | *stat |= FE_HAS_VITERBI; | ||
1019 | if (lock & 0x0010) | ||
1020 | *stat |= FE_HAS_SYNC; | ||
1021 | if (lock & 0x0008) | ||
1022 | *stat |= FE_HAS_LOCK; | ||
1023 | |||
1024 | return 0; | ||
1025 | } | ||
1026 | |||
1027 | static int dib7000m_read_ber(struct dvb_frontend *fe, u32 *ber) | ||
1028 | { | ||
1029 | struct dib7000m_state *state = fe->demodulator_priv; | ||
1030 | *ber = (dib7000m_read_word(state, 526) << 16) | dib7000m_read_word(state, 527); | ||
1031 | return 0; | ||
1032 | } | ||
1033 | |||
1034 | static int dib7000m_read_unc_blocks(struct dvb_frontend *fe, u32 *unc) | ||
1035 | { | ||
1036 | struct dib7000m_state *state = fe->demodulator_priv; | ||
1037 | *unc = dib7000m_read_word(state, 534); | ||
1038 | return 0; | ||
1039 | } | ||
1040 | |||
1041 | static int dib7000m_read_signal_strength(struct dvb_frontend *fe, u16 *strength) | ||
1042 | { | ||
1043 | struct dib7000m_state *state = fe->demodulator_priv; | ||
1044 | u16 val = dib7000m_read_word(state, 390); | ||
1045 | *strength = 65535 - val; | ||
1046 | return 0; | ||
1047 | } | ||
1048 | |||
1049 | static int dib7000m_read_snr(struct dvb_frontend* fe, u16 *snr) | ||
1050 | { | ||
1051 | *snr = 0x0000; | ||
1052 | return 0; | ||
1053 | } | ||
1054 | |||
1055 | static int dib7000m_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) | ||
1056 | { | ||
1057 | tune->min_delay_ms = 1000; | ||
1058 | return 0; | ||
1059 | } | ||
1060 | |||
1061 | static void dib7000m_release(struct dvb_frontend *demod) | ||
1062 | { | ||
1063 | struct dib7000m_state *st = demod->demodulator_priv; | ||
1064 | dibx000_exit_i2c_master(&st->i2c_master); | ||
1065 | kfree(st); | ||
1066 | } | ||
1067 | |||
1068 | struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating) | ||
1069 | { | ||
1070 | struct dib7000m_state *st = demod->demodulator_priv; | ||
1071 | return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating); | ||
1072 | } | ||
1073 | EXPORT_SYMBOL(dib7000m_get_i2c_master); | ||
1074 | |||
1075 | int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000m_config cfg[]) | ||
1076 | { | ||
1077 | struct dib7000m_state st = { .i2c_adap = i2c }; | ||
1078 | int k = 0; | ||
1079 | u8 new_addr = 0; | ||
1080 | |||
1081 | for (k = no_of_demods-1; k >= 0; k--) { | ||
1082 | st.cfg = cfg[k]; | ||
1083 | |||
1084 | /* designated i2c address */ | ||
1085 | new_addr = (0x40 + k) << 1; | ||
1086 | st.i2c_addr = new_addr; | ||
1087 | if (dib7000m_identify(&st) != 0) { | ||
1088 | st.i2c_addr = default_addr; | ||
1089 | if (dib7000m_identify(&st) != 0) { | ||
1090 | dprintk("DiB7000M #%d: not identified\n", k); | ||
1091 | return -EIO; | ||
1092 | } | ||
1093 | } | ||
1094 | |||
1095 | /* start diversity to pull_down div_str - just for i2c-enumeration */ | ||
1096 | dib7000m_set_output_mode(&st, OUTMODE_DIVERSITY); | ||
1097 | |||
1098 | dib7000m_write_word(&st, 1796, 0x0); // select DVB-T output | ||
1099 | |||
1100 | /* set new i2c address and force divstart */ | ||
1101 | dib7000m_write_word(&st, 1794, (new_addr << 2) | 0x2); | ||
1102 | |||
1103 | dprintk("IC %d initialized (to i2c_address 0x%x)\n", k, new_addr); | ||
1104 | } | ||
1105 | |||
1106 | for (k = 0; k < no_of_demods; k++) { | ||
1107 | st.cfg = cfg[k]; | ||
1108 | st.i2c_addr = (0x40 + k) << 1; | ||
1109 | |||
1110 | // unforce divstr | ||
1111 | dib7000m_write_word(&st,1794, st.i2c_addr << 2); | ||
1112 | |||
1113 | /* deactivate div - it was just for i2c-enumeration */ | ||
1114 | dib7000m_set_output_mode(&st, OUTMODE_HIGH_Z); | ||
1115 | } | ||
1116 | |||
1117 | return 0; | ||
1118 | } | ||
1119 | EXPORT_SYMBOL(dib7000m_i2c_enumeration); | ||
1120 | |||
1121 | static struct dvb_frontend_ops dib7000m_ops; | ||
1122 | struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000m_config *cfg) | ||
1123 | { | ||
1124 | struct dvb_frontend *demod; | ||
1125 | struct dib7000m_state *st; | ||
1126 | st = kzalloc(sizeof(struct dib7000m_state), GFP_KERNEL); | ||
1127 | if (st == NULL) | ||
1128 | return NULL; | ||
1129 | |||
1130 | memcpy(&st->cfg, cfg, sizeof(struct dib7000m_config)); | ||
1131 | st->i2c_adap = i2c_adap; | ||
1132 | st->i2c_addr = i2c_addr; | ||
1133 | |||
1134 | demod = &st->demod; | ||
1135 | demod->demodulator_priv = st; | ||
1136 | memcpy(&st->demod.ops, &dib7000m_ops, sizeof(struct dvb_frontend_ops)); | ||
1137 | |||
1138 | if (dib7000m_identify(st) != 0) | ||
1139 | goto error; | ||
1140 | |||
1141 | if (st->revision == 0x4000) | ||
1142 | dibx000_init_i2c_master(&st->i2c_master, DIB7000, st->i2c_adap, st->i2c_addr); | ||
1143 | else | ||
1144 | dibx000_init_i2c_master(&st->i2c_master, DIB7000MC, st->i2c_adap, st->i2c_addr); | ||
1145 | |||
1146 | dib7000m_demod_reset(st); | ||
1147 | |||
1148 | return demod; | ||
1149 | |||
1150 | error: | ||
1151 | kfree(st); | ||
1152 | return NULL; | ||
1153 | } | ||
1154 | EXPORT_SYMBOL(dib7000m_attach); | ||
1155 | |||
1156 | static struct dvb_frontend_ops dib7000m_ops = { | ||
1157 | .info = { | ||
1158 | .name = "DiBcom 7000MA/MB/PA/PB/MC", | ||
1159 | .type = FE_OFDM, | ||
1160 | .frequency_min = 44250000, | ||
1161 | .frequency_max = 867250000, | ||
1162 | .frequency_stepsize = 62500, | ||
1163 | .caps = FE_CAN_INVERSION_AUTO | | ||
1164 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||
1165 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | | ||
1166 | FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | | ||
1167 | FE_CAN_TRANSMISSION_MODE_AUTO | | ||
1168 | FE_CAN_GUARD_INTERVAL_AUTO | | ||
1169 | FE_CAN_RECOVER | | ||
1170 | FE_CAN_HIERARCHY_AUTO, | ||
1171 | }, | ||
1172 | |||
1173 | .release = dib7000m_release, | ||
1174 | |||
1175 | .init = dib7000m_init, | ||
1176 | .sleep = dib7000m_sleep, | ||
1177 | |||
1178 | .set_frontend = dib7000m_set_frontend, | ||
1179 | .get_tune_settings = dib7000m_fe_get_tune_settings, | ||
1180 | .get_frontend = dib7000m_get_frontend, | ||
1181 | |||
1182 | .read_status = dib7000m_read_status, | ||
1183 | .read_ber = dib7000m_read_ber, | ||
1184 | .read_signal_strength = dib7000m_read_signal_strength, | ||
1185 | .read_snr = dib7000m_read_snr, | ||
1186 | .read_ucblocks = dib7000m_read_unc_blocks, | ||
1187 | }; | ||
1188 | |||
1189 | MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>"); | ||
1190 | MODULE_DESCRIPTION("Driver for the DiBcom 7000MA/MB/PA/PB/MC COFDM demodulator"); | ||
1191 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/frontends/dib7000m.h b/drivers/media/dvb/frontends/dib7000m.h new file mode 100644 index 000000000000..597e9cc2da62 --- /dev/null +++ b/drivers/media/dvb/frontends/dib7000m.h | |||
@@ -0,0 +1,51 @@ | |||
1 | #ifndef DIB7000M_H | ||
2 | #define DIB7000M_H | ||
3 | |||
4 | #include "dibx000_common.h" | ||
5 | |||
6 | struct dib7000m_config { | ||
7 | u8 dvbt_mode; | ||
8 | u8 output_mpeg2_in_188_bytes; | ||
9 | u8 hostbus_diversity; | ||
10 | u8 tuner_is_baseband; | ||
11 | u8 mobile_mode; | ||
12 | int (*update_lna) (struct dvb_frontend *, u16 agc_global); | ||
13 | |||
14 | u8 agc_config_count; | ||
15 | struct dibx000_agc_config *agc; | ||
16 | |||
17 | struct dibx000_bandwidth_config *bw; | ||
18 | |||
19 | #define DIB7000M_GPIO_DEFAULT_DIRECTIONS 0xffff | ||
20 | u16 gpio_dir; | ||
21 | #define DIB7000M_GPIO_DEFAULT_VALUES 0x0000 | ||
22 | u16 gpio_val; | ||
23 | #define DIB7000M_GPIO_PWM_POS0(v) ((v & 0xf) << 12) | ||
24 | #define DIB7000M_GPIO_PWM_POS1(v) ((v & 0xf) << 8 ) | ||
25 | #define DIB7000M_GPIO_PWM_POS2(v) ((v & 0xf) << 4 ) | ||
26 | #define DIB7000M_GPIO_PWM_POS3(v) (v & 0xf) | ||
27 | #define DIB7000M_GPIO_DEFAULT_PWM_POS 0xffff | ||
28 | u16 gpio_pwm_pos; | ||
29 | |||
30 | u16 pwm_freq_div; | ||
31 | |||
32 | u8 quartz_direct; | ||
33 | |||
34 | u8 input_clk_is_div_2; | ||
35 | |||
36 | int (*agc_control) (struct dvb_frontend *, u8 before); | ||
37 | }; | ||
38 | |||
39 | #define DEFAULT_DIB7000M_I2C_ADDRESS 18 | ||
40 | |||
41 | extern struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000m_config *cfg); | ||
42 | extern struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int); | ||
43 | |||
44 | /* TODO | ||
45 | extern INT dib7000m_set_gpio(struct dibDemod *demod, UCHAR num, UCHAR dir, UCHAR val); | ||
46 | extern INT dib7000m_enable_vbg_voltage(struct dibDemod *demod); | ||
47 | extern void dib7000m_set_hostbus_diversity(struct dibDemod *demod, UCHAR onoff); | ||
48 | extern USHORT dib7000m_get_current_agc_global(struct dibDemod *demod); | ||
49 | */ | ||
50 | |||
51 | #endif | ||
diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c new file mode 100644 index 000000000000..0349a4b5da3f --- /dev/null +++ b/drivers/media/dvb/frontends/dib7000p.c | |||
@@ -0,0 +1,1019 @@ | |||
1 | /* | ||
2 | * Linux-DVB Driver for DiBcom's second generation DiB7000P (PC). | ||
3 | * | ||
4 | * Copyright (C) 2005-6 DiBcom (http://www.dibcom.fr/) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation, version 2. | ||
9 | */ | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/i2c.h> | ||
12 | |||
13 | #include "dvb_frontend.h" | ||
14 | |||
15 | #include "dib7000p.h" | ||
16 | |||
17 | static int debug; | ||
18 | module_param(debug, int, 0644); | ||
19 | MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); | ||
20 | |||
21 | #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000P:"); printk(args); } } while (0) | ||
22 | |||
23 | struct dib7000p_state { | ||
24 | struct dvb_frontend demod; | ||
25 | struct dib7000p_config cfg; | ||
26 | |||
27 | u8 i2c_addr; | ||
28 | struct i2c_adapter *i2c_adap; | ||
29 | |||
30 | struct dibx000_i2c_master i2c_master; | ||
31 | |||
32 | u16 wbd_ref; | ||
33 | |||
34 | u8 current_band; | ||
35 | fe_bandwidth_t current_bandwidth; | ||
36 | struct dibx000_agc_config *current_agc; | ||
37 | u32 timf; | ||
38 | |||
39 | u16 gpio_dir; | ||
40 | u16 gpio_val; | ||
41 | }; | ||
42 | |||
43 | enum dib7000p_power_mode { | ||
44 | DIB7000P_POWER_ALL = 0, | ||
45 | DIB7000P_POWER_INTERFACE_ONLY, | ||
46 | }; | ||
47 | |||
48 | static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg) | ||
49 | { | ||
50 | u8 wb[2] = { reg >> 8, reg & 0xff }; | ||
51 | u8 rb[2]; | ||
52 | struct i2c_msg msg[2] = { | ||
53 | { .addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2 }, | ||
54 | { .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 }, | ||
55 | }; | ||
56 | |||
57 | if (i2c_transfer(state->i2c_adap, msg, 2) != 2) | ||
58 | dprintk("i2c read error on %d\n",reg); | ||
59 | |||
60 | return (rb[0] << 8) | rb[1]; | ||
61 | } | ||
62 | |||
63 | static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val) | ||
64 | { | ||
65 | u8 b[4] = { | ||
66 | (reg >> 8) & 0xff, reg & 0xff, | ||
67 | (val >> 8) & 0xff, val & 0xff, | ||
68 | }; | ||
69 | struct i2c_msg msg = { | ||
70 | .addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4 | ||
71 | }; | ||
72 | return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; | ||
73 | } | ||
74 | static int dib7000p_set_output_mode(struct dib7000p_state *state, int mode) | ||
75 | { | ||
76 | int ret = 0; | ||
77 | u16 outreg, fifo_threshold, smo_mode; | ||
78 | |||
79 | outreg = 0; | ||
80 | fifo_threshold = 1792; | ||
81 | smo_mode = (dib7000p_read_word(state, 235) & 0x0010) | (1 << 1); | ||
82 | |||
83 | dprintk("-I- Setting output mode for demod %p to %d\n", | ||
84 | &state->demod, mode); | ||
85 | |||
86 | switch (mode) { | ||
87 | case OUTMODE_MPEG2_PAR_GATED_CLK: // STBs with parallel gated clock | ||
88 | outreg = (1 << 10); /* 0x0400 */ | ||
89 | break; | ||
90 | case OUTMODE_MPEG2_PAR_CONT_CLK: // STBs with parallel continues clock | ||
91 | outreg = (1 << 10) | (1 << 6); /* 0x0440 */ | ||
92 | break; | ||
93 | case OUTMODE_MPEG2_SERIAL: // STBs with serial input | ||
94 | outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0480 */ | ||
95 | break; | ||
96 | case OUTMODE_DIVERSITY: | ||
97 | if (state->cfg.hostbus_diversity) | ||
98 | outreg = (1 << 10) | (4 << 6); /* 0x0500 */ | ||
99 | else | ||
100 | outreg = (1 << 11); | ||
101 | break; | ||
102 | case OUTMODE_MPEG2_FIFO: // e.g. USB feeding | ||
103 | smo_mode |= (3 << 1); | ||
104 | fifo_threshold = 512; | ||
105 | outreg = (1 << 10) | (5 << 6); | ||
106 | break; | ||
107 | case OUTMODE_HIGH_Z: // disable | ||
108 | outreg = 0; | ||
109 | break; | ||
110 | default: | ||
111 | dprintk("Unhandled output_mode passed to be set for demod %p\n",&state->demod); | ||
112 | break; | ||
113 | } | ||
114 | |||
115 | if (state->cfg.output_mpeg2_in_188_bytes) | ||
116 | smo_mode |= (1 << 5) ; | ||
117 | |||
118 | ret |= dib7000p_write_word(state, 235, smo_mode); | ||
119 | ret |= dib7000p_write_word(state, 236, fifo_threshold); /* synchronous fread */ | ||
120 | ret |= dib7000p_write_word(state, 1286, outreg); /* P_Div_active */ | ||
121 | |||
122 | return ret; | ||
123 | } | ||
124 | |||
125 | static int dib7000p_set_power_mode(struct dib7000p_state *state, enum dib7000p_power_mode mode) | ||
126 | { | ||
127 | /* by default everything is powered off */ | ||
128 | u16 reg_774 = 0xffff, reg_775 = 0xffff, reg_776 = 0x0007, reg_899 = 0x0003, | ||
129 | reg_1280 = (0xfe00) | (dib7000p_read_word(state, 1280) & 0x01ff); | ||
130 | |||
131 | /* now, depending on the requested mode, we power on */ | ||
132 | switch (mode) { | ||
133 | /* power up everything in the demod */ | ||
134 | case DIB7000P_POWER_ALL: | ||
135 | reg_774 = 0x0000; reg_775 = 0x0000; reg_776 = 0x0; reg_899 = 0x0; reg_1280 &= 0x01ff; | ||
136 | break; | ||
137 | /* just leave power on the control-interfaces: GPIO and (I2C or SDIO) */ | ||
138 | case DIB7000P_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C */ | ||
139 | reg_1280 &= ~((1 << 14) | (1 << 13) | (1 << 12) | (1 << 10)); | ||
140 | break; | ||
141 | /* TODO following stuff is just converted from the dib7000-driver - check when is used what */ | ||
142 | } | ||
143 | |||
144 | dib7000p_write_word(state, 774, reg_774); | ||
145 | dib7000p_write_word(state, 775, reg_775); | ||
146 | dib7000p_write_word(state, 776, reg_776); | ||
147 | dib7000p_write_word(state, 899, reg_899); | ||
148 | dib7000p_write_word(state, 1280, reg_1280); | ||
149 | |||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static void dib7000p_set_adc_state(struct dib7000p_state *state, enum dibx000_adc_states no) | ||
154 | { | ||
155 | u16 reg_908 = dib7000p_read_word(state, 908), | ||
156 | reg_909 = dib7000p_read_word(state, 909); | ||
157 | |||
158 | switch (no) { | ||
159 | case DIBX000_SLOW_ADC_ON: | ||
160 | reg_909 |= (1 << 1) | (1 << 0); | ||
161 | dib7000p_write_word(state, 909, reg_909); | ||
162 | reg_909 &= ~(1 << 1); | ||
163 | break; | ||
164 | |||
165 | case DIBX000_SLOW_ADC_OFF: | ||
166 | reg_909 |= (1 << 1) | (1 << 0); | ||
167 | break; | ||
168 | |||
169 | case DIBX000_ADC_ON: | ||
170 | reg_908 &= 0x0fff; | ||
171 | reg_909 &= 0x0003; | ||
172 | break; | ||
173 | |||
174 | case DIBX000_ADC_OFF: // leave the VBG voltage on | ||
175 | reg_908 |= (1 << 14) | (1 << 13) | (1 << 12); | ||
176 | reg_909 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2); | ||
177 | break; | ||
178 | |||
179 | case DIBX000_VBG_ENABLE: | ||
180 | reg_908 &= ~(1 << 15); | ||
181 | break; | ||
182 | |||
183 | case DIBX000_VBG_DISABLE: | ||
184 | reg_908 |= (1 << 15); | ||
185 | break; | ||
186 | |||
187 | default: | ||
188 | break; | ||
189 | } | ||
190 | |||
191 | // dprintk("908: %x, 909: %x\n", reg_908, reg_909); | ||
192 | |||
193 | dib7000p_write_word(state, 908, reg_908); | ||
194 | dib7000p_write_word(state, 909, reg_909); | ||
195 | } | ||
196 | |||
197 | static int dib7000p_set_bandwidth(struct dvb_frontend *demod, u8 BW_Idx) | ||
198 | { | ||
199 | struct dib7000p_state *state = demod->demodulator_priv; | ||
200 | u32 timf; | ||
201 | |||
202 | // store the current bandwidth for later use | ||
203 | state->current_bandwidth = BW_Idx; | ||
204 | |||
205 | if (state->timf == 0) { | ||
206 | dprintk("-D- Using default timf\n"); | ||
207 | timf = state->cfg.bw->timf; | ||
208 | } else { | ||
209 | dprintk("-D- Using updated timf\n"); | ||
210 | timf = state->timf; | ||
211 | } | ||
212 | |||
213 | timf = timf * (BW_INDEX_TO_KHZ(BW_Idx) / 100) / 80; | ||
214 | |||
215 | dprintk("timf: %d\n",timf); | ||
216 | |||
217 | dib7000p_write_word(state, 23, (timf >> 16) & 0xffff); | ||
218 | dib7000p_write_word(state, 24, (timf ) & 0xffff); | ||
219 | |||
220 | return 0; | ||
221 | } | ||
222 | |||
223 | static int dib7000p_sad_calib(struct dib7000p_state *state) | ||
224 | { | ||
225 | /* internal */ | ||
226 | // dib7000p_write_word(state, 72, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is writting in set_bandwidth | ||
227 | dib7000p_write_word(state, 73, (0 << 1) | (0 << 0)); | ||
228 | dib7000p_write_word(state, 74, 776); // 0.625*3.3 / 4096 | ||
229 | |||
230 | /* do the calibration */ | ||
231 | dib7000p_write_word(state, 73, (1 << 0)); | ||
232 | dib7000p_write_word(state, 73, (0 << 0)); | ||
233 | |||
234 | msleep(1); | ||
235 | |||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | static void dib7000p_reset_pll(struct dib7000p_state *state) | ||
240 | { | ||
241 | struct dibx000_bandwidth_config *bw = &state->cfg.bw[0]; | ||
242 | |||
243 | dib7000p_write_word(state, 903, (bw->pll_prediv << 5) | (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset); | ||
244 | dib7000p_write_word(state, 900, ((bw->pll_ratio & 0x3f) << 9) | (bw->pll_bypass << 15) | (bw->modulo << 7) | (bw->ADClkSrc << 6) | | ||
245 | (bw->IO_CLK_en_core << 5) | (bw->bypclk_div << 2) | (bw->enable_refdiv << 1) | (0 << 0)); | ||
246 | |||
247 | dib7000p_write_word(state, 18, ((bw->internal*1000) >> 16) & 0xffff); | ||
248 | dib7000p_write_word(state, 19, (bw->internal*1000 ) & 0xffff); | ||
249 | dib7000p_write_word(state, 21, (bw->ifreq >> 16) & 0xffff); | ||
250 | dib7000p_write_word(state, 22, (bw->ifreq ) & 0xffff); | ||
251 | |||
252 | dib7000p_write_word(state, 72, bw->sad_cfg); | ||
253 | } | ||
254 | |||
255 | static int dib7000p_reset_gpio(struct dib7000p_state *st) | ||
256 | { | ||
257 | /* reset the GPIOs */ | ||
258 | dprintk("-D- gpio dir: %x: gpio val: %x, gpio pwm pos: %x\n",st->gpio_dir, st->gpio_val,st->cfg.gpio_pwm_pos); | ||
259 | |||
260 | dib7000p_write_word(st, 1029, st->gpio_dir); | ||
261 | dib7000p_write_word(st, 1030, st->gpio_val); | ||
262 | |||
263 | /* TODO 1031 is P_gpio_od */ | ||
264 | |||
265 | dib7000p_write_word(st, 1032, st->cfg.gpio_pwm_pos); | ||
266 | |||
267 | dib7000p_write_word(st, 1037, st->cfg.pwm_freq_div); | ||
268 | return 0; | ||
269 | } | ||
270 | |||
271 | static int dib7000p_demod_reset(struct dib7000p_state *state) | ||
272 | { | ||
273 | dib7000p_set_power_mode(state, DIB7000P_POWER_ALL); | ||
274 | |||
275 | dib7000p_set_adc_state(state, DIBX000_VBG_ENABLE); | ||
276 | |||
277 | /* restart all parts */ | ||
278 | dib7000p_write_word(state, 770, 0xffff); | ||
279 | dib7000p_write_word(state, 771, 0xffff); | ||
280 | dib7000p_write_word(state, 772, 0x001f); | ||
281 | dib7000p_write_word(state, 898, 0x0003); | ||
282 | /* except i2c, sdio, gpio - control interfaces */ | ||
283 | dib7000p_write_word(state, 1280, 0x01fc - ((1 << 7) | (1 << 6) | (1 << 5)) ); | ||
284 | |||
285 | dib7000p_write_word(state, 770, 0); | ||
286 | dib7000p_write_word(state, 771, 0); | ||
287 | dib7000p_write_word(state, 772, 0); | ||
288 | dib7000p_write_word(state, 898, 0); | ||
289 | dib7000p_write_word(state, 1280, 0); | ||
290 | |||
291 | /* default */ | ||
292 | dib7000p_reset_pll(state); | ||
293 | |||
294 | if (dib7000p_reset_gpio(state) != 0) | ||
295 | dprintk("-E- GPIO reset was not successful.\n"); | ||
296 | |||
297 | if (dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) != 0) | ||
298 | dprintk("-E- OUTPUT_MODE could not be resetted.\n"); | ||
299 | |||
300 | /* unforce divstr regardless whether i2c enumeration was done or not */ | ||
301 | dib7000p_write_word(state, 1285, dib7000p_read_word(state, 1285) & ~(1 << 1) ); | ||
302 | |||
303 | dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY); | ||
304 | |||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | static void dib7000p_restart_agc(struct dib7000p_state *state) | ||
309 | { | ||
310 | // P_restart_iqc & P_restart_agc | ||
311 | dib7000p_write_word(state, 770, 0x0c00); | ||
312 | dib7000p_write_word(state, 770, 0x0000); | ||
313 | } | ||
314 | |||
315 | static void dib7000p_update_lna(struct dib7000p_state *state) | ||
316 | { | ||
317 | int i; | ||
318 | u16 dyn_gain; | ||
319 | |||
320 | // when there is no LNA to program return immediatly | ||
321 | if (state->cfg.update_lna == NULL) | ||
322 | return; | ||
323 | |||
324 | for (i = 0; i < 5; i++) { | ||
325 | // read dyn_gain here (because it is demod-dependent and not tuner) | ||
326 | dyn_gain = dib7000p_read_word(state, 394); | ||
327 | |||
328 | if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed | ||
329 | dib7000p_restart_agc(state); | ||
330 | msleep(5); | ||
331 | } else | ||
332 | break; | ||
333 | } | ||
334 | } | ||
335 | |||
336 | static void dib7000p_pll_clk_cfg(struct dib7000p_state *state) | ||
337 | { | ||
338 | u16 tmp = 0; | ||
339 | tmp = dib7000p_read_word(state, 903); | ||
340 | dib7000p_write_word(state, 903, (tmp | 0x1)); //pwr-up pll | ||
341 | tmp = dib7000p_read_word(state, 900); | ||
342 | dib7000p_write_word(state, 900, (tmp & 0x7fff) | (1 << 6)); //use High freq clock | ||
343 | } | ||
344 | |||
345 | static void dib7000p_update_timf_freq(struct dib7000p_state *state) | ||
346 | { | ||
347 | u32 timf = (dib7000p_read_word(state, 427) << 16) | dib7000p_read_word(state, 428); | ||
348 | state->timf = timf * 80 / (BW_INDEX_TO_KHZ(state->current_bandwidth) / 100); | ||
349 | dib7000p_write_word(state, 23, (u16) (timf >> 16)); | ||
350 | dib7000p_write_word(state, 24, (u16) (timf & 0xffff)); | ||
351 | dprintk("-D- Updated timf_frequency: %d (default: %d)\n",state->timf, state->cfg.bw->timf); | ||
352 | } | ||
353 | |||
354 | static void dib7000p_set_channel(struct dib7000p_state *state, struct dibx000_ofdm_channel *ch, u8 seq) | ||
355 | { | ||
356 | u16 tmp, est[4]; // reg_26, reg_32, reg_33, reg_187, reg_188, reg_189, reg_190, reg_207, reg_208; | ||
357 | |||
358 | /* nfft, guard, qam, alpha */ | ||
359 | dib7000p_write_word(state, 0, (ch->nfft << 7) | (ch->guard << 5) | (ch->nqam << 3) | (ch->vit_alpha)); | ||
360 | dib7000p_write_word(state, 5, (seq << 4) | 1); /* do not force tps, search list 0 */ | ||
361 | |||
362 | /* P_dintl_native, P_dintlv_inv, P_vit_hrch, P_vit_code_rate, P_vit_select_hp */ | ||
363 | tmp = (ch->intlv_native << 6) | (ch->vit_hrch << 4) | (ch->vit_select_hp & 0x1); | ||
364 | if (ch->vit_hrch == 0 || ch->vit_select_hp == 1) | ||
365 | tmp |= (ch->vit_code_rate_hp << 1); | ||
366 | else | ||
367 | tmp |= (ch->vit_code_rate_lp << 1); | ||
368 | dib7000p_write_word(state, 208, tmp); | ||
369 | |||
370 | /* P_dvsy_sync_wait */ | ||
371 | switch (ch->nfft) { | ||
372 | case 1: tmp = 256; break; | ||
373 | case 2: tmp = 128; break; | ||
374 | case 0: | ||
375 | default: tmp = 64; break; | ||
376 | } | ||
377 | tmp *= ((1 << (ch->guard)) * 3 / 2); // add 50% SFN margin | ||
378 | tmp <<= 4; | ||
379 | |||
380 | /* deactive the possibility of diversity reception if extended interleave */ | ||
381 | /* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */ | ||
382 | if (ch->intlv_native || ch->nfft == 1) | ||
383 | tmp |= (1 << 2) | (2 << 0); | ||
384 | dib7000p_write_word(state, 207, tmp); | ||
385 | |||
386 | dib7000p_write_word(state, 26, 0x6680); // timf(6xxx) | ||
387 | dib7000p_write_word(state, 29, 0x1273); // isi inh1273 on1073 | ||
388 | dib7000p_write_word(state, 32, 0x0003); // pha_off_max(xxx3) | ||
389 | dib7000p_write_word(state, 33, 0x0005); // sfreq(xxx5) | ||
390 | |||
391 | /* channel estimation fine configuration */ | ||
392 | switch (ch->nqam) { | ||
393 | case 2: | ||
394 | est[0] = 0x0148; /* P_adp_regul_cnt 0.04 */ | ||
395 | est[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */ | ||
396 | est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ | ||
397 | est[3] = 0xfff8; /* P_adp_noise_ext -0.001 */ | ||
398 | break; | ||
399 | case 1: | ||
400 | est[0] = 0x023d; /* P_adp_regul_cnt 0.07 */ | ||
401 | est[1] = 0xffdf; /* P_adp_noise_cnt -0.004 */ | ||
402 | est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ | ||
403 | est[3] = 0xfff0; /* P_adp_noise_ext -0.002 */ | ||
404 | break; | ||
405 | default: | ||
406 | est[0] = 0x099a; /* P_adp_regul_cnt 0.3 */ | ||
407 | est[1] = 0xffae; /* P_adp_noise_cnt -0.01 */ | ||
408 | est[2] = 0x0333; /* P_adp_regul_ext 0.1 */ | ||
409 | est[3] = 0xfff8; /* P_adp_noise_ext -0.002 */ | ||
410 | break; | ||
411 | } | ||
412 | for (tmp = 0; tmp < 4; tmp++) | ||
413 | dib7000p_write_word(state, 187 + tmp, est[tmp]); | ||
414 | |||
415 | // set power-up level: interf+analog+AGC | ||
416 | dib7000p_set_power_mode(state, DIB7000P_POWER_ALL); | ||
417 | dib7000p_set_adc_state(state, DIBX000_ADC_ON); | ||
418 | dib7000p_pll_clk_cfg(state); | ||
419 | msleep(7); | ||
420 | |||
421 | // AGC initialization | ||
422 | if (state->cfg.agc_control) | ||
423 | state->cfg.agc_control(&state->demod, 1); | ||
424 | |||
425 | dib7000p_restart_agc(state); | ||
426 | |||
427 | // wait AGC rough lock time | ||
428 | msleep(5); | ||
429 | |||
430 | dib7000p_update_lna(state); | ||
431 | |||
432 | // wait AGC accurate lock time | ||
433 | msleep(7); | ||
434 | if (state->cfg.agc_control) | ||
435 | state->cfg.agc_control(&state->demod, 0); | ||
436 | } | ||
437 | |||
438 | static int dib7000p_autosearch_start(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch) | ||
439 | { | ||
440 | struct dib7000p_state *state = demod->demodulator_priv; | ||
441 | struct dibx000_ofdm_channel auto_ch; | ||
442 | u32 value; | ||
443 | |||
444 | INIT_OFDM_CHANNEL(&auto_ch); | ||
445 | auto_ch.RF_kHz = ch->RF_kHz; | ||
446 | auto_ch.Bw = ch->Bw; | ||
447 | auto_ch.nqam = 2; | ||
448 | auto_ch.guard = 0; | ||
449 | auto_ch.nfft = 1; | ||
450 | auto_ch.vit_alpha = 1; | ||
451 | auto_ch.vit_select_hp = 1; | ||
452 | auto_ch.vit_code_rate_hp = 2; | ||
453 | auto_ch.vit_code_rate_lp = 3; | ||
454 | auto_ch.vit_hrch = 0; | ||
455 | auto_ch.intlv_native = 1; | ||
456 | |||
457 | dib7000p_set_channel(state, &auto_ch, 7); | ||
458 | |||
459 | // always use the setting for 8MHz here lock_time for 7,6 MHz are longer | ||
460 | value = 30 * state->cfg.bw->internal; | ||
461 | dib7000p_write_word(state, 6, (u16) ((value >> 16) & 0xffff)); // lock0 wait time | ||
462 | dib7000p_write_word(state, 7, (u16) (value & 0xffff)); // lock0 wait time | ||
463 | value = 100 * state->cfg.bw->internal; | ||
464 | dib7000p_write_word(state, 8, (u16) ((value >> 16) & 0xffff)); // lock1 wait time | ||
465 | dib7000p_write_word(state, 9, (u16) (value & 0xffff)); // lock1 wait time | ||
466 | value = 500 * state->cfg.bw->internal; | ||
467 | dib7000p_write_word(state, 10, (u16) ((value >> 16) & 0xffff)); // lock2 wait time | ||
468 | dib7000p_write_word(state, 11, (u16) (value & 0xffff)); // lock2 wait time | ||
469 | |||
470 | value = dib7000p_read_word(state, 0); | ||
471 | dib7000p_write_word(state, 0, (1 << 9) | value); | ||
472 | dib7000p_read_word(state, 1284); | ||
473 | dib7000p_write_word(state, 0, (u16) value); | ||
474 | |||
475 | return 0; | ||
476 | } | ||
477 | |||
478 | static int dib7000p_autosearch_is_irq(struct dvb_frontend *demod) | ||
479 | { | ||
480 | struct dib7000p_state *state = demod->demodulator_priv; | ||
481 | u16 irq_pending = dib7000p_read_word(state, 1284); | ||
482 | |||
483 | if (irq_pending & 0x1) // failed | ||
484 | return 1; | ||
485 | |||
486 | if (irq_pending & 0x2) // succeeded | ||
487 | return 2; | ||
488 | |||
489 | return 0; // still pending | ||
490 | } | ||
491 | |||
492 | static int dib7000p_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch) | ||
493 | { | ||
494 | struct dib7000p_state *state = demod->demodulator_priv; | ||
495 | u16 tmp = 0; | ||
496 | |||
497 | if (ch != NULL) | ||
498 | dib7000p_set_channel(state, ch, 0); | ||
499 | else | ||
500 | return -EINVAL; | ||
501 | |||
502 | // restart demod | ||
503 | dib7000p_write_word(state, 770, 0x4000); | ||
504 | dib7000p_write_word(state, 770, 0x0000); | ||
505 | msleep(45); | ||
506 | |||
507 | /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */ | ||
508 | dib7000p_write_word(state, 29, (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3)); | ||
509 | |||
510 | // never achieved a lock with that bandwidth so far - wait for osc-freq to update | ||
511 | if (state->timf == 0) | ||
512 | msleep(200); | ||
513 | |||
514 | /* offset loop parameters */ | ||
515 | |||
516 | /* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */ | ||
517 | tmp = (6 << 8) | 0x80; | ||
518 | switch (ch->nfft) { | ||
519 | case 0: tmp |= (7 << 12); break; | ||
520 | case 1: tmp |= (9 << 12); break; | ||
521 | case 2: tmp |= (8 << 12); break; | ||
522 | } | ||
523 | dib7000p_write_word(state, 26, tmp); /* timf_a(6xxx) */ | ||
524 | |||
525 | /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */ | ||
526 | tmp = (0 << 4); | ||
527 | switch (ch->nfft) { | ||
528 | case 0: tmp |= 0x6; break; | ||
529 | case 1: tmp |= 0x8; break; | ||
530 | case 2: tmp |= 0x7; break; | ||
531 | } | ||
532 | dib7000p_write_word(state, 32, tmp); | ||
533 | |||
534 | /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */ | ||
535 | tmp = (0 << 4); | ||
536 | switch (ch->nfft) { | ||
537 | case 0: tmp |= 0x6; break; | ||
538 | case 1: tmp |= 0x8; break; | ||
539 | case 2: tmp |= 0x7; break; | ||
540 | } | ||
541 | dib7000p_write_word(state, 33, tmp); | ||
542 | |||
543 | tmp = dib7000p_read_word(state,509); | ||
544 | if (!((tmp >> 6) & 0x1)) { | ||
545 | /* restart the fec */ | ||
546 | tmp = dib7000p_read_word(state,771); | ||
547 | dib7000p_write_word(state, 771, tmp | (1 << 1)); | ||
548 | dib7000p_write_word(state, 771, tmp); | ||
549 | msleep(10); | ||
550 | tmp = dib7000p_read_word(state,509); | ||
551 | } | ||
552 | |||
553 | // we achieved a lock - it's time to update the osc freq | ||
554 | if ((tmp >> 6) & 0x1) | ||
555 | dib7000p_update_timf_freq(state); | ||
556 | |||
557 | return 0; | ||
558 | } | ||
559 | |||
560 | static int dib7000p_init(struct dvb_frontend *demod) | ||
561 | { | ||
562 | struct dibx000_agc_config *agc; | ||
563 | struct dib7000p_state *state = demod->demodulator_priv; | ||
564 | int ret = 0; | ||
565 | |||
566 | // Demodulator default configuration | ||
567 | agc = state->cfg.agc; | ||
568 | |||
569 | dib7000p_set_power_mode(state, DIB7000P_POWER_ALL); | ||
570 | dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_ON); | ||
571 | |||
572 | /* AGC */ | ||
573 | ret |= dib7000p_write_word(state, 75 , agc->setup ); | ||
574 | ret |= dib7000p_write_word(state, 76 , agc->inv_gain ); | ||
575 | ret |= dib7000p_write_word(state, 77 , agc->time_stabiliz ); | ||
576 | ret |= dib7000p_write_word(state, 100, (agc->alpha_level << 12) | agc->thlock); | ||
577 | |||
578 | // Demod AGC loop configuration | ||
579 | ret |= dib7000p_write_word(state, 101, (agc->alpha_mant << 5) | agc->alpha_exp); | ||
580 | ret |= dib7000p_write_word(state, 102, (agc->beta_mant << 6) | agc->beta_exp); | ||
581 | |||
582 | /* AGC continued */ | ||
583 | dprintk("-D- WBD: ref: %d, sel: %d, active: %d, alpha: %d\n", | ||
584 | state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel); | ||
585 | |||
586 | if (state->wbd_ref != 0) | ||
587 | ret |= dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | state->wbd_ref); | ||
588 | else | ||
589 | ret |= dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | agc->wbd_ref); | ||
590 | |||
591 | ret |= dib7000p_write_word(state, 106, (agc->wbd_sel << 13) | (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8) ); | ||
592 | |||
593 | ret |= dib7000p_write_word(state, 107, agc->agc1_max); | ||
594 | ret |= dib7000p_write_word(state, 108, agc->agc1_min); | ||
595 | ret |= dib7000p_write_word(state, 109, agc->agc2_max); | ||
596 | ret |= dib7000p_write_word(state, 110, agc->agc2_min); | ||
597 | ret |= dib7000p_write_word(state, 111, (agc->agc1_pt1 << 8) | agc->agc1_pt2 ); | ||
598 | ret |= dib7000p_write_word(state, 112, agc->agc1_pt3); | ||
599 | ret |= dib7000p_write_word(state, 113, (agc->agc1_slope1 << 8) | agc->agc1_slope2); | ||
600 | ret |= dib7000p_write_word(state, 114, (agc->agc2_pt1 << 8) | agc->agc2_pt2); | ||
601 | ret |= dib7000p_write_word(state, 115, (agc->agc2_slope1 << 8) | agc->agc2_slope2); | ||
602 | |||
603 | /* disable power smoothing */ | ||
604 | ret |= dib7000p_write_word(state, 145, 0); | ||
605 | ret |= dib7000p_write_word(state, 146, 0); | ||
606 | ret |= dib7000p_write_word(state, 147, 0); | ||
607 | ret |= dib7000p_write_word(state, 148, 0); | ||
608 | ret |= dib7000p_write_word(state, 149, 0); | ||
609 | ret |= dib7000p_write_word(state, 150, 0); | ||
610 | ret |= dib7000p_write_word(state, 151, 0); | ||
611 | ret |= dib7000p_write_word(state, 152, 0); | ||
612 | |||
613 | // P_timf_alpha=6, P_corm_alpha=6, P_corm_thres=128 default: 6,4,26 | ||
614 | ret |= dib7000p_write_word(state, 26 ,0x6680); | ||
615 | |||
616 | // P_palf_filter_on=1, P_palf_filter_freeze=0, P_palf_alpha_regul=16 | ||
617 | ret |= dib7000p_write_word(state, 142,0x0410); | ||
618 | // P_fft_freq_dir=1, P_fft_nb_to_cut=0 | ||
619 | ret |= dib7000p_write_word(state, 154,1 << 13); | ||
620 | // P_pha3_thres, default 0x3000 | ||
621 | ret |= dib7000p_write_word(state, 168,0x0ccd); | ||
622 | // P_cti_use_cpe=0, P_cti_use_prog=0, P_cti_win_len=16, default: 0x0010 | ||
623 | //ret |= dib7000p_write_word(state, 169,0x0010); | ||
624 | // P_cspu_regul=512, P_cspu_win_cut=15, default: 0x2005 | ||
625 | ret |= dib7000p_write_word(state, 183,0x200f); | ||
626 | // P_adp_regul_cnt=573, default: 410 | ||
627 | ret |= dib7000p_write_word(state, 187,0x023d); | ||
628 | // P_adp_noise_cnt= | ||
629 | ret |= dib7000p_write_word(state, 188,0x00a4); | ||
630 | // P_adp_regul_ext | ||
631 | ret |= dib7000p_write_word(state, 189,0x00a4); | ||
632 | // P_adp_noise_ext | ||
633 | ret |= dib7000p_write_word(state, 190,0x7ff0); | ||
634 | // P_adp_fil | ||
635 | ret |= dib7000p_write_word(state, 191,0x3ccc); | ||
636 | |||
637 | ret |= dib7000p_write_word(state, 222,0x0010); | ||
638 | // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard | ||
639 | ret |= dib7000p_write_word(state, 235,0x0062); | ||
640 | |||
641 | // P_iqc_alpha_pha, P_iqc_alpha_amp_dcc_alpha, ... | ||
642 | if(state->cfg.tuner_is_baseband) | ||
643 | ret |= dib7000p_write_word(state, 36,0x0755); | ||
644 | else | ||
645 | ret |= dib7000p_write_word(state, 36,0x1f55); | ||
646 | |||
647 | // auto search configuration | ||
648 | ret |= dib7000p_write_word(state, 2 ,0x0004); | ||
649 | ret |= dib7000p_write_word(state, 3 ,0x1000); | ||
650 | |||
651 | /* Equal Lock */ | ||
652 | ret |= dib7000p_write_word(state, 4 ,0x0814); | ||
653 | |||
654 | ret |= dib7000p_write_word(state, 6 ,0x001b); | ||
655 | ret |= dib7000p_write_word(state, 7 ,0x7740); | ||
656 | ret |= dib7000p_write_word(state, 8 ,0x005b); | ||
657 | ret |= dib7000p_write_word(state, 9 ,0x8d80); | ||
658 | ret |= dib7000p_write_word(state, 10 ,0x01c9); | ||
659 | ret |= dib7000p_write_word(state, 11 ,0xc380); | ||
660 | ret |= dib7000p_write_word(state, 12 ,0x0000); | ||
661 | ret |= dib7000p_write_word(state, 13 ,0x0080); | ||
662 | ret |= dib7000p_write_word(state, 14 ,0x0000); | ||
663 | ret |= dib7000p_write_word(state, 15 ,0x0090); | ||
664 | ret |= dib7000p_write_word(state, 16 ,0x0001); | ||
665 | ret |= dib7000p_write_word(state, 17 ,0xd4c0); | ||
666 | |||
667 | // P_clk_cfg1 | ||
668 | ret |= dib7000p_write_word(state, 901, 0x0006); | ||
669 | |||
670 | // P_divclksel=3 P_divbitsel=1 | ||
671 | ret |= dib7000p_write_word(state, 902, (3 << 10) | (1 << 6)); | ||
672 | |||
673 | // Tuner IO bank: max drive (14mA) + divout pads max drive | ||
674 | ret |= dib7000p_write_word(state, 905, 0x2c8e); | ||
675 | |||
676 | ret |= dib7000p_set_bandwidth(&state->demod, BANDWIDTH_8_MHZ); | ||
677 | dib7000p_sad_calib(state); | ||
678 | |||
679 | return ret; | ||
680 | } | ||
681 | |||
682 | static int dib7000p_sleep(struct dvb_frontend *demod) | ||
683 | { | ||
684 | struct dib7000p_state *state = demod->demodulator_priv; | ||
685 | return dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) | dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY); | ||
686 | } | ||
687 | |||
688 | static int dib7000p_identify(struct dib7000p_state *st) | ||
689 | { | ||
690 | u16 value; | ||
691 | dprintk("-I- DiB7000PC: checking demod on I2C address: %d (%x)\n", | ||
692 | st->i2c_addr, st->i2c_addr); | ||
693 | |||
694 | if ((value = dib7000p_read_word(st, 768)) != 0x01b3) { | ||
695 | dprintk("-E- DiB7000PC: wrong Vendor ID (read=0x%x)\n",value); | ||
696 | return -EREMOTEIO; | ||
697 | } | ||
698 | |||
699 | if ((value = dib7000p_read_word(st, 769)) != 0x4000) { | ||
700 | dprintk("-E- DiB7000PC: wrong Device ID (%x)\n",value); | ||
701 | return -EREMOTEIO; | ||
702 | } | ||
703 | |||
704 | return 0; | ||
705 | } | ||
706 | |||
707 | |||
708 | static int dib7000p_get_frontend(struct dvb_frontend* fe, | ||
709 | struct dvb_frontend_parameters *fep) | ||
710 | { | ||
711 | struct dib7000p_state *state = fe->demodulator_priv; | ||
712 | u16 tps = dib7000p_read_word(state,463); | ||
713 | |||
714 | fep->inversion = INVERSION_AUTO; | ||
715 | |||
716 | fep->u.ofdm.bandwidth = state->current_bandwidth; | ||
717 | |||
718 | switch ((tps >> 8) & 0x3) { | ||
719 | case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break; | ||
720 | case 1: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; break; | ||
721 | /* case 2: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_4K; break; */ | ||
722 | } | ||
723 | |||
724 | switch (tps & 0x3) { | ||
725 | case 0: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break; | ||
726 | case 1: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; break; | ||
727 | case 2: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; break; | ||
728 | case 3: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; break; | ||
729 | } | ||
730 | |||
731 | switch ((tps >> 14) & 0x3) { | ||
732 | case 0: fep->u.ofdm.constellation = QPSK; break; | ||
733 | case 1: fep->u.ofdm.constellation = QAM_16; break; | ||
734 | case 2: | ||
735 | default: fep->u.ofdm.constellation = QAM_64; break; | ||
736 | } | ||
737 | |||
738 | /* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */ | ||
739 | /* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */ | ||
740 | |||
741 | fep->u.ofdm.hierarchy_information = HIERARCHY_NONE; | ||
742 | switch ((tps >> 5) & 0x7) { | ||
743 | case 1: fep->u.ofdm.code_rate_HP = FEC_1_2; break; | ||
744 | case 2: fep->u.ofdm.code_rate_HP = FEC_2_3; break; | ||
745 | case 3: fep->u.ofdm.code_rate_HP = FEC_3_4; break; | ||
746 | case 5: fep->u.ofdm.code_rate_HP = FEC_5_6; break; | ||
747 | case 7: | ||
748 | default: fep->u.ofdm.code_rate_HP = FEC_7_8; break; | ||
749 | |||
750 | } | ||
751 | |||
752 | switch ((tps >> 2) & 0x7) { | ||
753 | case 1: fep->u.ofdm.code_rate_LP = FEC_1_2; break; | ||
754 | case 2: fep->u.ofdm.code_rate_LP = FEC_2_3; break; | ||
755 | case 3: fep->u.ofdm.code_rate_LP = FEC_3_4; break; | ||
756 | case 5: fep->u.ofdm.code_rate_LP = FEC_5_6; break; | ||
757 | case 7: | ||
758 | default: fep->u.ofdm.code_rate_LP = FEC_7_8; break; | ||
759 | } | ||
760 | |||
761 | /* native interleaver: (dib7000p_read_word(state, 464) >> 5) & 0x1 */ | ||
762 | |||
763 | return 0; | ||
764 | } | ||
765 | |||
766 | static int dib7000p_set_frontend(struct dvb_frontend* fe, | ||
767 | struct dvb_frontend_parameters *fep) | ||
768 | { | ||
769 | struct dib7000p_state *state = fe->demodulator_priv; | ||
770 | struct dibx000_ofdm_channel ch; | ||
771 | |||
772 | INIT_OFDM_CHANNEL(&ch); | ||
773 | FEP2DIB(fep,&ch); | ||
774 | |||
775 | state->current_bandwidth = fep->u.ofdm.bandwidth; | ||
776 | dib7000p_set_bandwidth(fe, fep->u.ofdm.bandwidth); | ||
777 | |||
778 | if (fe->ops.tuner_ops.set_params) | ||
779 | fe->ops.tuner_ops.set_params(fe, fep); | ||
780 | |||
781 | if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO || | ||
782 | fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO || | ||
783 | fep->u.ofdm.constellation == QAM_AUTO || | ||
784 | fep->u.ofdm.code_rate_HP == FEC_AUTO) { | ||
785 | int i = 800, found; | ||
786 | |||
787 | dib7000p_autosearch_start(fe, &ch); | ||
788 | do { | ||
789 | msleep(1); | ||
790 | found = dib7000p_autosearch_is_irq(fe); | ||
791 | } while (found == 0 && i--); | ||
792 | |||
793 | dprintk("autosearch returns: %d\n",found); | ||
794 | if (found == 0 || found == 1) | ||
795 | return 0; // no channel found | ||
796 | |||
797 | dib7000p_get_frontend(fe, fep); | ||
798 | FEP2DIB(fep, &ch); | ||
799 | } | ||
800 | |||
801 | /* make this a config parameter */ | ||
802 | dib7000p_set_output_mode(state, OUTMODE_MPEG2_FIFO); | ||
803 | |||
804 | return dib7000p_tune(fe, &ch); | ||
805 | } | ||
806 | |||
807 | static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t *stat) | ||
808 | { | ||
809 | struct dib7000p_state *state = fe->demodulator_priv; | ||
810 | u16 lock = dib7000p_read_word(state, 509); | ||
811 | |||
812 | *stat = 0; | ||
813 | |||
814 | if (lock & 0x8000) | ||
815 | *stat |= FE_HAS_SIGNAL; | ||
816 | if (lock & 0x3000) | ||
817 | *stat |= FE_HAS_CARRIER; | ||
818 | if (lock & 0x0100) | ||
819 | *stat |= FE_HAS_VITERBI; | ||
820 | if (lock & 0x0010) | ||
821 | *stat |= FE_HAS_SYNC; | ||
822 | if (lock & 0x0008) | ||
823 | *stat |= FE_HAS_LOCK; | ||
824 | |||
825 | return 0; | ||
826 | } | ||
827 | |||
828 | static int dib7000p_read_ber(struct dvb_frontend *fe, u32 *ber) | ||
829 | { | ||
830 | struct dib7000p_state *state = fe->demodulator_priv; | ||
831 | *ber = (dib7000p_read_word(state, 500) << 16) | dib7000p_read_word(state, 501); | ||
832 | return 0; | ||
833 | } | ||
834 | |||
835 | static int dib7000p_read_unc_blocks(struct dvb_frontend *fe, u32 *unc) | ||
836 | { | ||
837 | struct dib7000p_state *state = fe->demodulator_priv; | ||
838 | *unc = dib7000p_read_word(state, 506); | ||
839 | return 0; | ||
840 | } | ||
841 | |||
842 | static int dib7000p_read_signal_strength(struct dvb_frontend *fe, u16 *strength) | ||
843 | { | ||
844 | struct dib7000p_state *state = fe->demodulator_priv; | ||
845 | u16 val = dib7000p_read_word(state, 394); | ||
846 | *strength = 65535 - val; | ||
847 | return 0; | ||
848 | } | ||
849 | |||
850 | static int dib7000p_read_snr(struct dvb_frontend* fe, u16 *snr) | ||
851 | { | ||
852 | *snr = 0x0000; | ||
853 | return 0; | ||
854 | } | ||
855 | |||
856 | static int dib7000p_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) | ||
857 | { | ||
858 | tune->min_delay_ms = 1000; | ||
859 | return 0; | ||
860 | } | ||
861 | |||
862 | static void dib7000p_release(struct dvb_frontend *demod) | ||
863 | { | ||
864 | struct dib7000p_state *st = demod->demodulator_priv; | ||
865 | dibx000_exit_i2c_master(&st->i2c_master); | ||
866 | kfree(st); | ||
867 | } | ||
868 | |||
869 | int dib7000pc_detection(struct i2c_adapter *i2c_adap) | ||
870 | { | ||
871 | u8 tx[2], rx[2]; | ||
872 | struct i2c_msg msg[2] = { | ||
873 | { .addr = 18 >> 1, .flags = 0, .buf = tx, .len = 2 }, | ||
874 | { .addr = 18 >> 1, .flags = I2C_M_RD, .buf = rx, .len = 2 }, | ||
875 | }; | ||
876 | |||
877 | tx[0] = 0x03; | ||
878 | tx[1] = 0x00; | ||
879 | |||
880 | if (i2c_transfer(i2c_adap, msg, 2) == 2) | ||
881 | if (rx[0] == 0x01 && rx[1] == 0xb3) { | ||
882 | dprintk("-D- DiB7000PC detected\n"); | ||
883 | return 1; | ||
884 | } | ||
885 | |||
886 | msg[0].addr = msg[1].addr = 0x40; | ||
887 | |||
888 | if (i2c_transfer(i2c_adap, msg, 2) == 2) | ||
889 | if (rx[0] == 0x01 && rx[1] == 0xb3) { | ||
890 | dprintk("-D- DiB7000PC detected\n"); | ||
891 | return 1; | ||
892 | } | ||
893 | |||
894 | dprintk("-D- DiB7000PC not detected\n"); | ||
895 | return 0; | ||
896 | } | ||
897 | EXPORT_SYMBOL(dib7000pc_detection); | ||
898 | |||
899 | struct i2c_adapter * dib7000p_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating) | ||
900 | { | ||
901 | struct dib7000p_state *st = demod->demodulator_priv; | ||
902 | return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating); | ||
903 | } | ||
904 | EXPORT_SYMBOL(dib7000p_get_i2c_master); | ||
905 | |||
906 | int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]) | ||
907 | { | ||
908 | struct dib7000p_state st = { .i2c_adap = i2c }; | ||
909 | int k = 0; | ||
910 | u8 new_addr = 0; | ||
911 | |||
912 | for (k = no_of_demods-1; k >= 0; k--) { | ||
913 | st.cfg = cfg[k]; | ||
914 | |||
915 | /* designated i2c address */ | ||
916 | new_addr = (0x40 + k) << 1; | ||
917 | st.i2c_addr = new_addr; | ||
918 | if (dib7000p_identify(&st) != 0) { | ||
919 | st.i2c_addr = default_addr; | ||
920 | if (dib7000p_identify(&st) != 0) { | ||
921 | dprintk("DiB7000P #%d: not identified\n", k); | ||
922 | return -EIO; | ||
923 | } | ||
924 | } | ||
925 | |||
926 | /* start diversity to pull_down div_str - just for i2c-enumeration */ | ||
927 | dib7000p_set_output_mode(&st, OUTMODE_DIVERSITY); | ||
928 | |||
929 | /* set new i2c address and force divstart */ | ||
930 | dib7000p_write_word(&st, 1285, (new_addr << 2) | 0x2); | ||
931 | |||
932 | dprintk("IC %d initialized (to i2c_address 0x%x)\n", k, new_addr); | ||
933 | } | ||
934 | |||
935 | for (k = 0; k < no_of_demods; k++) { | ||
936 | st.cfg = cfg[k]; | ||
937 | st.i2c_addr = (0x40 + k) << 1; | ||
938 | |||
939 | // unforce divstr | ||
940 | dib7000p_write_word(&st, 1285, st.i2c_addr << 2); | ||
941 | |||
942 | /* deactivate div - it was just for i2c-enumeration */ | ||
943 | dib7000p_set_output_mode(&st, OUTMODE_HIGH_Z); | ||
944 | } | ||
945 | |||
946 | return 0; | ||
947 | } | ||
948 | EXPORT_SYMBOL(dib7000p_i2c_enumeration); | ||
949 | |||
950 | static struct dvb_frontend_ops dib7000p_ops; | ||
951 | struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg) | ||
952 | { | ||
953 | struct dvb_frontend *demod; | ||
954 | struct dib7000p_state *st; | ||
955 | st = kzalloc(sizeof(struct dib7000p_state), GFP_KERNEL); | ||
956 | if (st == NULL) | ||
957 | return NULL; | ||
958 | |||
959 | memcpy(&st->cfg, cfg, sizeof(struct dib7000p_config)); | ||
960 | st->i2c_adap = i2c_adap; | ||
961 | st->i2c_addr = i2c_addr; | ||
962 | st->gpio_val = cfg->gpio_val; | ||
963 | st->gpio_dir = cfg->gpio_dir; | ||
964 | |||
965 | demod = &st->demod; | ||
966 | demod->demodulator_priv = st; | ||
967 | memcpy(&st->demod.ops, &dib7000p_ops, sizeof(struct dvb_frontend_ops)); | ||
968 | |||
969 | if (dib7000p_identify(st) != 0) | ||
970 | goto error; | ||
971 | |||
972 | dibx000_init_i2c_master(&st->i2c_master, DIB7000P, st->i2c_adap, st->i2c_addr); | ||
973 | |||
974 | dib7000p_demod_reset(st); | ||
975 | |||
976 | return demod; | ||
977 | |||
978 | error: | ||
979 | kfree(st); | ||
980 | return NULL; | ||
981 | } | ||
982 | EXPORT_SYMBOL(dib7000p_attach); | ||
983 | |||
984 | static struct dvb_frontend_ops dib7000p_ops = { | ||
985 | .info = { | ||
986 | .name = "DiBcom 7000PC", | ||
987 | .type = FE_OFDM, | ||
988 | .frequency_min = 44250000, | ||
989 | .frequency_max = 867250000, | ||
990 | .frequency_stepsize = 62500, | ||
991 | .caps = FE_CAN_INVERSION_AUTO | | ||
992 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||
993 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | | ||
994 | FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | | ||
995 | FE_CAN_TRANSMISSION_MODE_AUTO | | ||
996 | FE_CAN_GUARD_INTERVAL_AUTO | | ||
997 | FE_CAN_RECOVER | | ||
998 | FE_CAN_HIERARCHY_AUTO, | ||
999 | }, | ||
1000 | |||
1001 | .release = dib7000p_release, | ||
1002 | |||
1003 | .init = dib7000p_init, | ||
1004 | .sleep = dib7000p_sleep, | ||
1005 | |||
1006 | .set_frontend = dib7000p_set_frontend, | ||
1007 | .get_tune_settings = dib7000p_fe_get_tune_settings, | ||
1008 | .get_frontend = dib7000p_get_frontend, | ||
1009 | |||
1010 | .read_status = dib7000p_read_status, | ||
1011 | .read_ber = dib7000p_read_ber, | ||
1012 | .read_signal_strength = dib7000p_read_signal_strength, | ||
1013 | .read_snr = dib7000p_read_snr, | ||
1014 | .read_ucblocks = dib7000p_read_unc_blocks, | ||
1015 | }; | ||
1016 | |||
1017 | MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>"); | ||
1018 | MODULE_DESCRIPTION("Driver for the DiBcom 7000PC COFDM demodulator"); | ||
1019 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/frontends/dib7000p.h b/drivers/media/dvb/frontends/dib7000p.h new file mode 100644 index 000000000000..79465cf1aced --- /dev/null +++ b/drivers/media/dvb/frontends/dib7000p.h | |||
@@ -0,0 +1,46 @@ | |||
1 | #ifndef DIB7000P_H | ||
2 | #define DIB7000P_H | ||
3 | |||
4 | #include "dibx000_common.h" | ||
5 | |||
6 | struct dib7000p_config { | ||
7 | u8 output_mpeg2_in_188_bytes; | ||
8 | u8 hostbus_diversity; | ||
9 | u8 tuner_is_baseband; | ||
10 | int (*update_lna) (struct dvb_frontend *, u16 agc_global); | ||
11 | |||
12 | struct dibx000_agc_config *agc; | ||
13 | struct dibx000_bandwidth_config *bw; | ||
14 | |||
15 | #define DIB7000P_GPIO_DEFAULT_DIRECTIONS 0xffff | ||
16 | u16 gpio_dir; | ||
17 | #define DIB7000P_GPIO_DEFAULT_VALUES 0x0000 | ||
18 | u16 gpio_val; | ||
19 | #define DIB7000P_GPIO_PWM_POS0(v) ((v & 0xf) << 12) | ||
20 | #define DIB7000P_GPIO_PWM_POS1(v) ((v & 0xf) << 8 ) | ||
21 | #define DIB7000P_GPIO_PWM_POS2(v) ((v & 0xf) << 4 ) | ||
22 | #define DIB7000P_GPIO_PWM_POS3(v) (v & 0xf) | ||
23 | #define DIB7000P_GPIO_DEFAULT_PWM_POS 0xffff | ||
24 | u16 gpio_pwm_pos; | ||
25 | |||
26 | u16 pwm_freq_div; | ||
27 | |||
28 | u8 quartz_direct; | ||
29 | |||
30 | int (*agc_control) (struct dvb_frontend *, u8 before); | ||
31 | }; | ||
32 | |||
33 | #define DEFAULT_DIB7000P_I2C_ADDRESS 18 | ||
34 | |||
35 | extern struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg); | ||
36 | extern struct i2c_adapter * dib7000p_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int); | ||
37 | extern int dib7000pc_detection(struct i2c_adapter *i2c_adap); | ||
38 | |||
39 | /* TODO | ||
40 | extern INT dib7000p_set_gpio(struct dibDemod *demod, UCHAR num, UCHAR dir, UCHAR val); | ||
41 | extern INT dib7000p_enable_vbg_voltage(struct dibDemod *demod); | ||
42 | extern void dib7000p_set_hostbus_diversity(struct dibDemod *demod, UCHAR onoff); | ||
43 | extern USHORT dib7000p_get_current_agc_global(struct dibDemod *demod); | ||
44 | */ | ||
45 | |||
46 | #endif | ||
diff --git a/drivers/media/dvb/frontends/dibx000_common.h b/drivers/media/dvb/frontends/dibx000_common.h index bb0c65f8aee8..a1df604366c3 100644 --- a/drivers/media/dvb/frontends/dibx000_common.h +++ b/drivers/media/dvb/frontends/dibx000_common.h | |||
@@ -32,6 +32,13 @@ extern void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst); | |||
32 | #define BAND_LBAND 0x01 | 32 | #define BAND_LBAND 0x01 |
33 | #define BAND_UHF 0x02 | 33 | #define BAND_UHF 0x02 |
34 | #define BAND_VHF 0x04 | 34 | #define BAND_VHF 0x04 |
35 | #define BAND_SBAND 0x08 | ||
36 | #define BAND_FM 0x10 | ||
37 | |||
38 | #define BAND_OF_FREQUENCY(freq_kHz) ( (freq_kHz) <= 115000 ? BAND_FM : \ | ||
39 | (freq_kHz) <= 250000 ? BAND_VHF : \ | ||
40 | (freq_kHz) <= 863000 ? BAND_UHF : \ | ||
41 | (freq_kHz) <= 2000000 ? BAND_LBAND : BAND_SBAND ) | ||
35 | 42 | ||
36 | struct dibx000_agc_config { | 43 | struct dibx000_agc_config { |
37 | /* defines the capabilities of this AGC-setting - using the BAND_-defines*/ | 44 | /* defines the capabilities of this AGC-setting - using the BAND_-defines*/ |
@@ -129,6 +136,7 @@ enum dibx000_adc_states { | |||
129 | 136 | ||
130 | /* I hope I can get rid of the following kludge in the near future */ | 137 | /* I hope I can get rid of the following kludge in the near future */ |
131 | struct dibx000_ofdm_channel { | 138 | struct dibx000_ofdm_channel { |
139 | u32 RF_kHz; | ||
132 | u8 Bw; | 140 | u8 Bw; |
133 | s16 nfft; | 141 | s16 nfft; |
134 | s16 guard; | 142 | s16 guard; |
@@ -138,9 +146,11 @@ struct dibx000_ofdm_channel { | |||
138 | s16 vit_alpha; | 146 | s16 vit_alpha; |
139 | s16 vit_code_rate_hp; | 147 | s16 vit_code_rate_hp; |
140 | s16 vit_code_rate_lp; | 148 | s16 vit_code_rate_lp; |
149 | u8 intlv_native; | ||
141 | }; | 150 | }; |
142 | 151 | ||
143 | #define FEP2DIB(fep,ch) \ | 152 | #define FEP2DIB(fep,ch) \ |
153 | (ch)->RF_kHz = (fep)->frequency / 1000; \ | ||
144 | (ch)->Bw = (fep)->u.ofdm.bandwidth; \ | 154 | (ch)->Bw = (fep)->u.ofdm.bandwidth; \ |
145 | (ch)->nfft = (fep)->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ? -1 : (fep)->u.ofdm.transmission_mode; \ | 155 | (ch)->nfft = (fep)->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ? -1 : (fep)->u.ofdm.transmission_mode; \ |
146 | (ch)->guard = (fep)->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ? -1 : (fep)->u.ofdm.guard_interval; \ | 156 | (ch)->guard = (fep)->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ? -1 : (fep)->u.ofdm.guard_interval; \ |
@@ -149,7 +159,8 @@ struct dibx000_ofdm_channel { | |||
149 | (ch)->vit_select_hp = 1; \ | 159 | (ch)->vit_select_hp = 1; \ |
150 | (ch)->vit_alpha = 1; \ | 160 | (ch)->vit_alpha = 1; \ |
151 | (ch)->vit_code_rate_hp = (fep)->u.ofdm.code_rate_HP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_HP; \ | 161 | (ch)->vit_code_rate_hp = (fep)->u.ofdm.code_rate_HP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_HP; \ |
152 | (ch)->vit_code_rate_lp = (fep)->u.ofdm.code_rate_LP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_LP; | 162 | (ch)->vit_code_rate_lp = (fep)->u.ofdm.code_rate_LP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_LP; \ |
163 | (ch)->intlv_native = 1; | ||
153 | 164 | ||
154 | #define INIT_OFDM_CHANNEL(ch) do {\ | 165 | #define INIT_OFDM_CHANNEL(ch) do {\ |
155 | (ch)->Bw = 0; \ | 166 | (ch)->Bw = 0; \ |
diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index b7e7108ee5b3..62de760c844f 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c | |||
@@ -472,14 +472,14 @@ int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, | |||
472 | printk("pll: %s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n", | 472 | printk("pll: %s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n", |
473 | desc->name, div, buf[0], buf[1], buf[2], buf[3]); | 473 | desc->name, div, buf[0], buf[1], buf[2], buf[3]); |
474 | 474 | ||
475 | return 0; | 475 | // calculate the frequency we set it to |
476 | return (div * desc->entries[i].stepsize) - desc->entries[i].offset; | ||
476 | } | 477 | } |
477 | EXPORT_SYMBOL(dvb_pll_configure); | 478 | EXPORT_SYMBOL(dvb_pll_configure); |
478 | 479 | ||
479 | static int dvb_pll_release(struct dvb_frontend *fe) | 480 | static int dvb_pll_release(struct dvb_frontend *fe) |
480 | { | 481 | { |
481 | if (fe->tuner_priv) | 482 | kfree(fe->tuner_priv); |
482 | kfree(fe->tuner_priv); | ||
483 | fe->tuner_priv = NULL; | 483 | fe->tuner_priv = NULL; |
484 | return 0; | 484 | return 0; |
485 | } | 485 | } |
@@ -489,7 +489,8 @@ static int dvb_pll_sleep(struct dvb_frontend *fe) | |||
489 | struct dvb_pll_priv *priv = fe->tuner_priv; | 489 | struct dvb_pll_priv *priv = fe->tuner_priv; |
490 | u8 buf[4]; | 490 | u8 buf[4]; |
491 | struct i2c_msg msg = | 491 | struct i2c_msg msg = |
492 | { .addr = priv->pll_i2c_address, .flags = 0, .buf = buf, .len = sizeof(buf) }; | 492 | { .addr = priv->pll_i2c_address, .flags = 0, |
493 | .buf = buf, .len = sizeof(buf) }; | ||
493 | int i; | 494 | int i; |
494 | int result; | 495 | int result; |
495 | 496 | ||
@@ -517,16 +518,16 @@ static int dvb_pll_sleep(struct dvb_frontend *fe) | |||
517 | return 0; | 518 | return 0; |
518 | } | 519 | } |
519 | 520 | ||
520 | static int dvb_pll_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) | 521 | static int dvb_pll_set_params(struct dvb_frontend *fe, |
522 | struct dvb_frontend_parameters *params) | ||
521 | { | 523 | { |
522 | struct dvb_pll_priv *priv = fe->tuner_priv; | 524 | struct dvb_pll_priv *priv = fe->tuner_priv; |
523 | u8 buf[4]; | 525 | u8 buf[4]; |
524 | struct i2c_msg msg = | 526 | struct i2c_msg msg = |
525 | { .addr = priv->pll_i2c_address, .flags = 0, .buf = buf, .len = sizeof(buf) }; | 527 | { .addr = priv->pll_i2c_address, .flags = 0, |
528 | .buf = buf, .len = sizeof(buf) }; | ||
526 | int result; | 529 | int result; |
527 | u32 div; | 530 | u32 bandwidth = 0, frequency = 0; |
528 | int i; | ||
529 | u32 bandwidth = 0; | ||
530 | 531 | ||
531 | if (priv->i2c == NULL) | 532 | if (priv->i2c == NULL) |
532 | return -EINVAL; | 533 | return -EINVAL; |
@@ -536,8 +537,11 @@ static int dvb_pll_set_params(struct dvb_frontend *fe, struct dvb_frontend_param | |||
536 | bandwidth = params->u.ofdm.bandwidth; | 537 | bandwidth = params->u.ofdm.bandwidth; |
537 | } | 538 | } |
538 | 539 | ||
539 | if ((result = dvb_pll_configure(priv->pll_desc, buf, params->frequency, bandwidth)) != 0) | 540 | if ((result = dvb_pll_configure(priv->pll_desc, buf, |
541 | params->frequency, bandwidth)) < 0) | ||
540 | return result; | 542 | return result; |
543 | else | ||
544 | frequency = result; | ||
541 | 545 | ||
542 | if (fe->ops.i2c_gate_ctrl) | 546 | if (fe->ops.i2c_gate_ctrl) |
543 | fe->ops.i2c_gate_ctrl(fe, 1); | 547 | fe->ops.i2c_gate_ctrl(fe, 1); |
@@ -545,26 +549,19 @@ static int dvb_pll_set_params(struct dvb_frontend *fe, struct dvb_frontend_param | |||
545 | return result; | 549 | return result; |
546 | } | 550 | } |
547 | 551 | ||
548 | // calculate the frequency we set it to | 552 | priv->frequency = frequency; |
549 | for (i = 0; i < priv->pll_desc->count; i++) { | ||
550 | if (params->frequency > priv->pll_desc->entries[i].limit) | ||
551 | continue; | ||
552 | break; | ||
553 | } | ||
554 | div = (params->frequency + priv->pll_desc->entries[i].offset) / priv->pll_desc->entries[i].stepsize; | ||
555 | priv->frequency = (div * priv->pll_desc->entries[i].stepsize) - priv->pll_desc->entries[i].offset; | ||
556 | priv->bandwidth = bandwidth; | 553 | priv->bandwidth = bandwidth; |
557 | 554 | ||
558 | return 0; | 555 | return 0; |
559 | } | 556 | } |
560 | 557 | ||
561 | static int dvb_pll_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8 *buf, int buf_len) | 558 | static int dvb_pll_calc_regs(struct dvb_frontend *fe, |
559 | struct dvb_frontend_parameters *params, | ||
560 | u8 *buf, int buf_len) | ||
562 | { | 561 | { |
563 | struct dvb_pll_priv *priv = fe->tuner_priv; | 562 | struct dvb_pll_priv *priv = fe->tuner_priv; |
564 | int result; | 563 | int result; |
565 | u32 div; | 564 | u32 bandwidth = 0, frequency = 0; |
566 | int i; | ||
567 | u32 bandwidth = 0; | ||
568 | 565 | ||
569 | if (buf_len < 5) | 566 | if (buf_len < 5) |
570 | return -EINVAL; | 567 | return -EINVAL; |
@@ -574,18 +571,15 @@ static int dvb_pll_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parame | |||
574 | bandwidth = params->u.ofdm.bandwidth; | 571 | bandwidth = params->u.ofdm.bandwidth; |
575 | } | 572 | } |
576 | 573 | ||
577 | if ((result = dvb_pll_configure(priv->pll_desc, buf+1, params->frequency, bandwidth)) != 0) | 574 | if ((result = dvb_pll_configure(priv->pll_desc, buf+1, |
575 | params->frequency, bandwidth)) < 0) | ||
578 | return result; | 576 | return result; |
577 | else | ||
578 | frequency = result; | ||
579 | |||
579 | buf[0] = priv->pll_i2c_address; | 580 | buf[0] = priv->pll_i2c_address; |
580 | 581 | ||
581 | // calculate the frequency we set it to | 582 | priv->frequency = frequency; |
582 | for (i = 0; i < priv->pll_desc->count; i++) { | ||
583 | if (params->frequency > priv->pll_desc->entries[i].limit) | ||
584 | continue; | ||
585 | break; | ||
586 | } | ||
587 | div = (params->frequency + priv->pll_desc->entries[i].offset) / priv->pll_desc->entries[i].stepsize; | ||
588 | priv->frequency = (div * priv->pll_desc->entries[i].stepsize) - priv->pll_desc->entries[i].offset; | ||
589 | priv->bandwidth = bandwidth; | 583 | priv->bandwidth = bandwidth; |
590 | 584 | ||
591 | return 5; | 585 | return 5; |
@@ -614,10 +608,13 @@ static struct dvb_tuner_ops dvb_pll_tuner_ops = { | |||
614 | .get_bandwidth = dvb_pll_get_bandwidth, | 608 | .get_bandwidth = dvb_pll_get_bandwidth, |
615 | }; | 609 | }; |
616 | 610 | ||
617 | struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc) | 611 | struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, |
612 | struct i2c_adapter *i2c, | ||
613 | struct dvb_pll_desc *desc) | ||
618 | { | 614 | { |
619 | u8 b1 [] = { 0 }; | 615 | u8 b1 [] = { 0 }; |
620 | struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD, .buf = b1, .len = 1 }; | 616 | struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD, |
617 | .buf = b1, .len = 1 }; | ||
621 | struct dvb_pll_priv *priv = NULL; | 618 | struct dvb_pll_priv *priv = NULL; |
622 | int ret; | 619 | int ret; |
623 | 620 | ||
@@ -640,7 +637,9 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struc | |||
640 | priv->i2c = i2c; | 637 | priv->i2c = i2c; |
641 | priv->pll_desc = desc; | 638 | priv->pll_desc = desc; |
642 | 639 | ||
643 | memcpy(&fe->ops.tuner_ops, &dvb_pll_tuner_ops, sizeof(struct dvb_tuner_ops)); | 640 | memcpy(&fe->ops.tuner_ops, &dvb_pll_tuner_ops, |
641 | sizeof(struct dvb_tuner_ops)); | ||
642 | |||
644 | strncpy(fe->ops.tuner_ops.info.name, desc->name, 128); | 643 | strncpy(fe->ops.tuner_ops.info.name, desc->name, 128); |
645 | fe->ops.tuner_ops.info.frequency_min = desc->min; | 644 | fe->ops.tuner_ops.info.frequency_min = desc->min; |
646 | fe->ops.tuner_ops.info.frequency_min = desc->max; | 645 | fe->ops.tuner_ops.info.frequency_min = desc->max; |
diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h index ed5ac5a361ae..681186a5e5eb 100644 --- a/drivers/media/dvb/frontends/dvb-pll.h +++ b/drivers/media/dvb/frontends/dvb-pll.h | |||
@@ -48,7 +48,7 @@ extern struct dvb_pll_desc dvb_pll_philips_td1316; | |||
48 | extern struct dvb_pll_desc dvb_pll_thomson_fe6600; | 48 | extern struct dvb_pll_desc dvb_pll_thomson_fe6600; |
49 | 49 | ||
50 | extern int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, | 50 | extern int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, |
51 | u32 freq, int bandwidth); | 51 | u32 freq, int bandwidth); |
52 | 52 | ||
53 | /** | 53 | /** |
54 | * Attach a dvb-pll to the supplied frontend structure. | 54 | * Attach a dvb-pll to the supplied frontend structure. |
@@ -59,6 +59,9 @@ extern int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, | |||
59 | * @param desc dvb_pll_desc to use. | 59 | * @param desc dvb_pll_desc to use. |
60 | * @return Frontend pointer on success, NULL on failure | 60 | * @return Frontend pointer on success, NULL on failure |
61 | */ | 61 | */ |
62 | extern struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc); | 62 | extern struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, |
63 | int pll_addr, | ||
64 | struct i2c_adapter *i2c, | ||
65 | struct dvb_pll_desc *desc); | ||
63 | 66 | ||
64 | #endif | 67 | #endif |
diff --git a/drivers/media/dvb/frontends/lg_h06xf.h b/drivers/media/dvb/frontends/lg_h06xf.h deleted file mode 100644 index 754d51d11120..000000000000 --- a/drivers/media/dvb/frontends/lg_h06xf.h +++ /dev/null | |||
@@ -1,64 +0,0 @@ | |||
1 | /* | ||
2 | * lg_h06xf.h - ATSC Tuner support for LG TDVS-H06xF | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | */ | ||
18 | |||
19 | #ifndef _LG_H06XF_H_ | ||
20 | #define _LG_H06XF_H_ | ||
21 | #include "dvb-pll.h" | ||
22 | |||
23 | static int lg_h06xf_pll_set(struct dvb_frontend* fe, struct i2c_adapter* i2c_adap, | ||
24 | struct dvb_frontend_parameters* params) | ||
25 | { | ||
26 | u8 buf[4]; | ||
27 | struct i2c_msg msg = { .addr = 0x61, .flags = 0, | ||
28 | .buf = buf, .len = sizeof(buf) }; | ||
29 | int err; | ||
30 | |||
31 | dvb_pll_configure(&dvb_pll_lg_tdvs_h06xf, buf, params->frequency, 0); | ||
32 | if (fe->ops.i2c_gate_ctrl) | ||
33 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
34 | if ((err = i2c_transfer(i2c_adap, &msg, 1)) != 1) { | ||
35 | printk(KERN_WARNING "lg_h06xf: %s error " | ||
36 | "(addr %02x <- %02x, err = %i)\n", | ||
37 | __FUNCTION__, buf[0], buf[1], err); | ||
38 | if (err < 0) | ||
39 | return err; | ||
40 | else | ||
41 | return -EREMOTEIO; | ||
42 | } | ||
43 | |||
44 | /* Set the Auxiliary Byte. */ | ||
45 | buf[0] = buf[2]; | ||
46 | buf[0] &= ~0x20; | ||
47 | buf[0] |= 0x18; | ||
48 | buf[1] = 0x50; | ||
49 | msg.len = 2; | ||
50 | if (fe->ops.i2c_gate_ctrl) | ||
51 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
52 | if ((err = i2c_transfer(i2c_adap, &msg, 1)) != 1) { | ||
53 | printk(KERN_WARNING "lg_h06xf: %s error " | ||
54 | "(addr %02x <- %02x, err = %i)\n", | ||
55 | __FUNCTION__, buf[0], buf[1], err); | ||
56 | if (err < 0) | ||
57 | return err; | ||
58 | else | ||
59 | return -EREMOTEIO; | ||
60 | } | ||
61 | |||
62 | return 0; | ||
63 | } | ||
64 | #endif | ||
diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c index 9a354708bd20..68aad0f6519f 100644 --- a/drivers/media/dvb/frontends/lgdt330x.c +++ b/drivers/media/dvb/frontends/lgdt330x.c | |||
@@ -31,9 +31,6 @@ | |||
31 | * Air2PC/AirStar 2 ATSC 3rd generation (HD5000) | 31 | * Air2PC/AirStar 2 ATSC 3rd generation (HD5000) |
32 | * pcHDTV HD5500 | 32 | * pcHDTV HD5500 |
33 | * | 33 | * |
34 | * TODO: | ||
35 | * signal strength always returns 0. | ||
36 | * | ||
37 | */ | 34 | */ |
38 | 35 | ||
39 | #include <linux/kernel.h> | 36 | #include <linux/kernel.h> |
@@ -46,9 +43,13 @@ | |||
46 | #include <asm/byteorder.h> | 43 | #include <asm/byteorder.h> |
47 | 44 | ||
48 | #include "dvb_frontend.h" | 45 | #include "dvb_frontend.h" |
46 | #include "dvb_math.h" | ||
49 | #include "lgdt330x_priv.h" | 47 | #include "lgdt330x_priv.h" |
50 | #include "lgdt330x.h" | 48 | #include "lgdt330x.h" |
51 | 49 | ||
50 | /* Use Equalizer Mean Squared Error instead of Phaser Tracker MSE */ | ||
51 | /* #define USE_EQMSE */ | ||
52 | |||
52 | static int debug = 0; | 53 | static int debug = 0; |
53 | module_param(debug, int, 0644); | 54 | module_param(debug, int, 0644); |
54 | MODULE_PARM_DESC(debug,"Turn on/off lgdt330x frontend debugging (default:off)."); | 55 | MODULE_PARM_DESC(debug,"Turn on/off lgdt330x frontend debugging (default:off)."); |
@@ -68,6 +69,7 @@ struct lgdt330x_state | |||
68 | 69 | ||
69 | /* Demodulator private data */ | 70 | /* Demodulator private data */ |
70 | fe_modulation_t current_modulation; | 71 | fe_modulation_t current_modulation; |
72 | u32 snr; /* Result of last SNR calculation */ | ||
71 | 73 | ||
72 | /* Tuner private data */ | 74 | /* Tuner private data */ |
73 | u32 current_frequency; | 75 | u32 current_frequency; |
@@ -302,10 +304,10 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe, | |||
302 | static u8 lgdt3303_8vsb_44_data[] = { | 304 | static u8 lgdt3303_8vsb_44_data[] = { |
303 | 0x04, 0x00, | 305 | 0x04, 0x00, |
304 | 0x0d, 0x40, | 306 | 0x0d, 0x40, |
305 | 0x0e, 0x87, | 307 | 0x0e, 0x87, |
306 | 0x0f, 0x8e, | 308 | 0x0f, 0x8e, |
307 | 0x10, 0x01, | 309 | 0x10, 0x01, |
308 | 0x47, 0x8b }; | 310 | 0x47, 0x8b }; |
309 | 311 | ||
310 | /* | 312 | /* |
311 | * Array of byte pairs <address, value> | 313 | * Array of byte pairs <address, value> |
@@ -435,9 +437,6 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status) | |||
435 | /* Test signal does not exist flag */ | 437 | /* Test signal does not exist flag */ |
436 | /* as well as the AGC lock flag. */ | 438 | /* as well as the AGC lock flag. */ |
437 | *status |= FE_HAS_SIGNAL; | 439 | *status |= FE_HAS_SIGNAL; |
438 | } else { | ||
439 | /* Without a signal all other status bits are meaningless */ | ||
440 | return 0; | ||
441 | } | 440 | } |
442 | 441 | ||
443 | /* | 442 | /* |
@@ -500,9 +499,6 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status) | |||
500 | /* Test input signal does not exist flag */ | 499 | /* Test input signal does not exist flag */ |
501 | /* as well as the AGC lock flag. */ | 500 | /* as well as the AGC lock flag. */ |
502 | *status |= FE_HAS_SIGNAL; | 501 | *status |= FE_HAS_SIGNAL; |
503 | } else { | ||
504 | /* Without a signal all other status bits are meaningless */ | ||
505 | return 0; | ||
506 | } | 502 | } |
507 | 503 | ||
508 | /* Carrier Recovery Lock Status Register */ | 504 | /* Carrier Recovery Lock Status Register */ |
@@ -543,151 +539,150 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status) | |||
543 | return 0; | 539 | return 0; |
544 | } | 540 | } |
545 | 541 | ||
546 | static int lgdt330x_read_signal_strength(struct dvb_frontend* fe, u16* strength) | 542 | /* Calculate SNR estimation (scaled by 2^24) |
543 | |||
544 | 8-VSB SNR equations from LGDT3302 and LGDT3303 datasheets, QAM | ||
545 | equations from LGDT3303 datasheet. VSB is the same between the '02 | ||
546 | and '03, so maybe QAM is too? Perhaps someone with a newer datasheet | ||
547 | that has QAM information could verify? | ||
548 | |||
549 | For 8-VSB: (two ways, take your pick) | ||
550 | LGDT3302: | ||
551 | SNR_EQ = 10 * log10(25 * 24^2 / EQ_MSE) | ||
552 | LGDT3303: | ||
553 | SNR_EQ = 10 * log10(25 * 32^2 / EQ_MSE) | ||
554 | LGDT3302 & LGDT3303: | ||
555 | SNR_PT = 10 * log10(25 * 32^2 / PT_MSE) (we use this one) | ||
556 | For 64-QAM: | ||
557 | SNR = 10 * log10( 688128 / MSEQAM) | ||
558 | For 256-QAM: | ||
559 | SNR = 10 * log10( 696320 / MSEQAM) | ||
560 | |||
561 | We re-write the snr equation as: | ||
562 | SNR * 2^24 = 10*(c - intlog10(MSE)) | ||
563 | Where for 256-QAM, c = log10(696320) * 2^24, and so on. */ | ||
564 | |||
565 | static u32 calculate_snr(u32 mse, u32 c) | ||
547 | { | 566 | { |
548 | /* not directly available. */ | 567 | if (mse == 0) /* No signal */ |
549 | *strength = 0; | 568 | return 0; |
550 | return 0; | 569 | |
570 | mse = intlog10(mse); | ||
571 | if (mse > c) { | ||
572 | /* Negative SNR, which is possible, but realisticly the | ||
573 | demod will lose lock before the signal gets this bad. The | ||
574 | API only allows for unsigned values, so just return 0 */ | ||
575 | return 0; | ||
576 | } | ||
577 | return 10*(c - mse); | ||
551 | } | 578 | } |
552 | 579 | ||
553 | static int lgdt3302_read_snr(struct dvb_frontend* fe, u16* snr) | 580 | static int lgdt3302_read_snr(struct dvb_frontend* fe, u16* snr) |
554 | { | 581 | { |
555 | #ifdef SNR_IN_DB | ||
556 | /* | ||
557 | * Spec sheet shows formula for SNR_EQ = 10 log10(25 * 24**2 / noise) | ||
558 | * and SNR_PH = 10 log10(25 * 32**2 / noise) for equalizer and phase tracker | ||
559 | * respectively. The following tables are built on these formulas. | ||
560 | * The usual definition is SNR = 20 log10(signal/noise) | ||
561 | * If the specification is wrong the value retuned is 1/2 the actual SNR in db. | ||
562 | * | ||
563 | * This table is a an ordered list of noise values computed by the | ||
564 | * formula from the spec sheet such that the index into the table | ||
565 | * starting at 43 or 45 is the SNR value in db. There are duplicate noise | ||
566 | * value entries at the beginning because the SNR varies more than | ||
567 | * 1 db for a change of 1 digit in noise at very small values of noise. | ||
568 | * | ||
569 | * Examples from SNR_EQ table: | ||
570 | * noise SNR | ||
571 | * 0 43 | ||
572 | * 1 42 | ||
573 | * 2 39 | ||
574 | * 3 37 | ||
575 | * 4 36 | ||
576 | * 5 35 | ||
577 | * 6 34 | ||
578 | * 7 33 | ||
579 | * 8 33 | ||
580 | * 9 32 | ||
581 | * 10 32 | ||
582 | * 11 31 | ||
583 | * 12 31 | ||
584 | * 13 30 | ||
585 | */ | ||
586 | |||
587 | static const u32 SNR_EQ[] = | ||
588 | { 1, 2, 2, 2, 3, 3, 4, 4, 5, 7, | ||
589 | 9, 11, 13, 17, 21, 26, 33, 41, 52, 65, | ||
590 | 81, 102, 129, 162, 204, 257, 323, 406, 511, 644, | ||
591 | 810, 1020, 1284, 1616, 2035, 2561, 3224, 4059, 5110, 6433, | ||
592 | 8098, 10195, 12835, 16158, 20341, 25608, 32238, 40585, 51094, 64323, | ||
593 | 80978, 101945, 128341, 161571, 203406, 256073, 0x40000 | ||
594 | }; | ||
595 | |||
596 | static const u32 SNR_PH[] = | ||
597 | { 1, 2, 2, 2, 3, 3, 4, 5, 6, 8, | ||
598 | 10, 12, 15, 19, 23, 29, 37, 46, 58, 73, | ||
599 | 91, 115, 144, 182, 229, 288, 362, 456, 574, 722, | ||
600 | 909, 1144, 1440, 1813, 2282, 2873, 3617, 4553, 5732, 7216, | ||
601 | 9084, 11436, 14396, 18124, 22817, 28724, 36161, 45524, 57312, 72151, | ||
602 | 90833, 114351, 143960, 181235, 228161, 0x080000 | ||
603 | }; | ||
604 | |||
605 | static u8 buf[5];/* read data buffer */ | ||
606 | static u32 noise; /* noise value */ | ||
607 | static u32 snr_db; /* index into SNR_EQ[] */ | ||
608 | struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; | 582 | struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; |
583 | u8 buf[5]; /* read data buffer */ | ||
584 | u32 noise; /* noise value */ | ||
585 | u32 c; /* per-modulation SNR calculation constant */ | ||
609 | 586 | ||
610 | /* read both equalizer and phase tracker noise data */ | 587 | switch(state->current_modulation) { |
611 | i2c_read_demod_bytes(state, EQPH_ERR0, buf, sizeof(buf)); | 588 | case VSB_8: |
612 | 589 | i2c_read_demod_bytes(state, LGDT3302_EQPH_ERR0, buf, 5); | |
613 | if (state->current_modulation == VSB_8) { | 590 | #ifdef USE_EQMSE |
614 | /* Equalizer Mean-Square Error Register for VSB */ | 591 | /* Use Equalizer Mean-Square Error Register */ |
592 | /* SNR for ranges from -15.61 to +41.58 */ | ||
615 | noise = ((buf[0] & 7) << 16) | (buf[1] << 8) | buf[2]; | 593 | noise = ((buf[0] & 7) << 16) | (buf[1] << 8) | buf[2]; |
616 | 594 | c = 69765745; /* log10(25*24^2)*2^24 */ | |
617 | /* | ||
618 | * Look up noise value in table. | ||
619 | * A better search algorithm could be used... | ||
620 | * watch out there are duplicate entries. | ||
621 | */ | ||
622 | for (snr_db = 0; snr_db < sizeof(SNR_EQ); snr_db++) { | ||
623 | if (noise < SNR_EQ[snr_db]) { | ||
624 | *snr = 43 - snr_db; | ||
625 | break; | ||
626 | } | ||
627 | } | ||
628 | } else { | ||
629 | /* Phase Tracker Mean-Square Error Register for QAM */ | ||
630 | noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4]; | ||
631 | |||
632 | /* Look up noise value in table. */ | ||
633 | for (snr_db = 0; snr_db < sizeof(SNR_PH); snr_db++) { | ||
634 | if (noise < SNR_PH[snr_db]) { | ||
635 | *snr = 45 - snr_db; | ||
636 | break; | ||
637 | } | ||
638 | } | ||
639 | } | ||
640 | #else | 595 | #else |
641 | /* Return the raw noise value */ | 596 | /* Use Phase Tracker Mean-Square Error Register */ |
642 | static u8 buf[5];/* read data buffer */ | 597 | /* SNR for ranges from -13.11 to +44.08 */ |
643 | static u32 noise; /* noise value */ | ||
644 | struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; | ||
645 | |||
646 | /* read both equalizer and pase tracker noise data */ | ||
647 | i2c_read_demod_bytes(state, EQPH_ERR0, buf, sizeof(buf)); | ||
648 | |||
649 | if (state->current_modulation == VSB_8) { | ||
650 | /* Phase Tracker Mean-Square Error Register for VSB */ | ||
651 | noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4]; | 598 | noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4]; |
652 | } else { | 599 | c = 73957994; /* log10(25*32^2)*2^24 */ |
653 | 600 | #endif | |
654 | /* Carrier Recovery Mean-Square Error for QAM */ | 601 | break; |
655 | i2c_read_demod_bytes(state, 0x1a, buf, 2); | 602 | case QAM_64: |
603 | case QAM_256: | ||
604 | i2c_read_demod_bytes(state, CARRIER_MSEQAM1, buf, 2); | ||
656 | noise = ((buf[0] & 3) << 8) | buf[1]; | 605 | noise = ((buf[0] & 3) << 8) | buf[1]; |
606 | c = state->current_modulation == QAM_64 ? 97939837 : 98026066; | ||
607 | /* log10(688128)*2^24 and log10(696320)*2^24 */ | ||
608 | break; | ||
609 | default: | ||
610 | printk(KERN_ERR "lgdt330x: %s: Modulation set to unsupported value\n", | ||
611 | __FUNCTION__); | ||
612 | return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */ | ||
657 | } | 613 | } |
658 | 614 | ||
659 | /* Small values for noise mean signal is better so invert noise */ | 615 | state->snr = calculate_snr(noise, c); |
660 | *snr = ~noise; | 616 | *snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */ |
661 | #endif | ||
662 | 617 | ||
663 | dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr); | 618 | dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise, |
619 | state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16); | ||
664 | 620 | ||
665 | return 0; | 621 | return 0; |
666 | } | 622 | } |
667 | 623 | ||
668 | static int lgdt3303_read_snr(struct dvb_frontend* fe, u16* snr) | 624 | static int lgdt3303_read_snr(struct dvb_frontend* fe, u16* snr) |
669 | { | 625 | { |
670 | /* Return the raw noise value */ | ||
671 | static u8 buf[5];/* read data buffer */ | ||
672 | static u32 noise; /* noise value */ | ||
673 | struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; | 626 | struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; |
627 | u8 buf[5]; /* read data buffer */ | ||
628 | u32 noise; /* noise value */ | ||
629 | u32 c; /* per-modulation SNR calculation constant */ | ||
674 | 630 | ||
675 | if (state->current_modulation == VSB_8) { | 631 | switch(state->current_modulation) { |
676 | 632 | case VSB_8: | |
677 | i2c_read_demod_bytes(state, 0x6e, buf, 5); | 633 | i2c_read_demod_bytes(state, LGDT3303_EQPH_ERR0, buf, 5); |
678 | /* Phase Tracker Mean-Square Error Register for VSB */ | 634 | #ifdef USE_EQMSE |
635 | /* Use Equalizer Mean-Square Error Register */ | ||
636 | /* SNR for ranges from -16.12 to +44.08 */ | ||
637 | noise = ((buf[0] & 0x78) << 13) | (buf[1] << 8) | buf[2]; | ||
638 | c = 73957994; /* log10(25*32^2)*2^24 */ | ||
639 | #else | ||
640 | /* Use Phase Tracker Mean-Square Error Register */ | ||
641 | /* SNR for ranges from -13.11 to +44.08 */ | ||
679 | noise = ((buf[0] & 7) << 16) | (buf[3] << 8) | buf[4]; | 642 | noise = ((buf[0] & 7) << 16) | (buf[3] << 8) | buf[4]; |
680 | } else { | 643 | c = 73957994; /* log10(25*32^2)*2^24 */ |
681 | 644 | #endif | |
682 | /* Carrier Recovery Mean-Square Error for QAM */ | 645 | break; |
683 | i2c_read_demod_bytes(state, 0x1a, buf, 2); | 646 | case QAM_64: |
647 | case QAM_256: | ||
648 | i2c_read_demod_bytes(state, CARRIER_MSEQAM1, buf, 2); | ||
684 | noise = (buf[0] << 8) | buf[1]; | 649 | noise = (buf[0] << 8) | buf[1]; |
650 | c = state->current_modulation == QAM_64 ? 97939837 : 98026066; | ||
651 | /* log10(688128)*2^24 and log10(696320)*2^24 */ | ||
652 | break; | ||
653 | default: | ||
654 | printk(KERN_ERR "lgdt330x: %s: Modulation set to unsupported value\n", | ||
655 | __FUNCTION__); | ||
656 | return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */ | ||
685 | } | 657 | } |
686 | 658 | ||
687 | /* Small values for noise mean signal is better so invert noise */ | 659 | state->snr = calculate_snr(noise, c); |
688 | *snr = ~noise; | 660 | *snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */ |
661 | |||
662 | dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise, | ||
663 | state->snr >> 24, (((state->snr >> 8) & 0xffff) * 100) >> 16); | ||
664 | |||
665 | return 0; | ||
666 | } | ||
667 | |||
668 | static int lgdt330x_read_signal_strength(struct dvb_frontend* fe, u16* strength) | ||
669 | { | ||
670 | /* Calculate Strength from SNR up to 35dB */ | ||
671 | /* Even though the SNR can go higher than 35dB, there is some comfort */ | ||
672 | /* factor in having a range of strong signals that can show at 100% */ | ||
673 | struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; | ||
674 | u16 snr; | ||
675 | int ret; | ||
689 | 676 | ||
690 | dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr); | 677 | ret = fe->ops.read_snr(fe, &snr); |
678 | if (ret != 0) | ||
679 | return ret; | ||
680 | /* Rather than use the 8.8 value snr, use state->snr which is 8.24 */ | ||
681 | /* scale the range 0 - 35*2^24 into 0 - 65535 */ | ||
682 | if (state->snr >= 8960 * 0x10000) | ||
683 | *strength = 0xffff; | ||
684 | else | ||
685 | *strength = state->snr / 8960; | ||
691 | 686 | ||
692 | return 0; | 687 | return 0; |
693 | } | 688 | } |
diff --git a/drivers/media/dvb/frontends/lgdt330x_priv.h b/drivers/media/dvb/frontends/lgdt330x_priv.h index 59b7c5b9012d..38c76695abfe 100644 --- a/drivers/media/dvb/frontends/lgdt330x_priv.h +++ b/drivers/media/dvb/frontends/lgdt330x_priv.h | |||
@@ -51,14 +51,19 @@ enum I2C_REG { | |||
51 | AGC_RFIF_ACC2= 0x3b, | 51 | AGC_RFIF_ACC2= 0x3b, |
52 | AGC_STATUS= 0x3f, | 52 | AGC_STATUS= 0x3f, |
53 | SYNC_STATUS_VSB= 0x43, | 53 | SYNC_STATUS_VSB= 0x43, |
54 | EQPH_ERR0= 0x47, | ||
55 | EQ_ERR1= 0x48, | ||
56 | EQ_ERR2= 0x49, | ||
57 | PH_ERR1= 0x4a, | ||
58 | PH_ERR2= 0x4b, | ||
59 | DEMUX_CONTROL= 0x66, | 54 | DEMUX_CONTROL= 0x66, |
55 | LGDT3302_EQPH_ERR0= 0x47, | ||
56 | LGDT3302_EQ_ERR1= 0x48, | ||
57 | LGDT3302_EQ_ERR2= 0x49, | ||
58 | LGDT3302_PH_ERR1= 0x4a, | ||
59 | LGDT3302_PH_ERR2= 0x4b, | ||
60 | LGDT3302_PACKET_ERR_COUNTER1= 0x6a, | 60 | LGDT3302_PACKET_ERR_COUNTER1= 0x6a, |
61 | LGDT3302_PACKET_ERR_COUNTER2= 0x6b, | 61 | LGDT3302_PACKET_ERR_COUNTER2= 0x6b, |
62 | LGDT3303_EQPH_ERR0= 0x6e, | ||
63 | LGDT3303_EQ_ERR1= 0x6f, | ||
64 | LGDT3303_EQ_ERR2= 0x70, | ||
65 | LGDT3303_PH_ERR1= 0x71, | ||
66 | LGDT3303_PH_ERR2= 0x72, | ||
62 | LGDT3303_PACKET_ERR_COUNTER1= 0x8b, | 67 | LGDT3303_PACKET_ERR_COUNTER1= 0x8b, |
63 | LGDT3303_PACKET_ERR_COUNTER2= 0x8c, | 68 | LGDT3303_PACKET_ERR_COUNTER2= 0x8c, |
64 | }; | 69 | }; |
diff --git a/drivers/media/dvb/frontends/lgh06xf.c b/drivers/media/dvb/frontends/lgh06xf.c new file mode 100644 index 000000000000..2202d0cc878b --- /dev/null +++ b/drivers/media/dvb/frontends/lgh06xf.c | |||
@@ -0,0 +1,134 @@ | |||
1 | /* | ||
2 | * lgh06xf.c - ATSC Tuner support for LG TDVS-H06xF | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | */ | ||
18 | |||
19 | #include "dvb-pll.h" | ||
20 | #include "lgh06xf.h" | ||
21 | |||
22 | #define LG_H06XF_PLL_I2C_ADDR 0x61 | ||
23 | |||
24 | struct lgh06xf_priv { | ||
25 | struct i2c_adapter *i2c; | ||
26 | u32 frequency; | ||
27 | }; | ||
28 | |||
29 | static int lgh06xf_release(struct dvb_frontend *fe) | ||
30 | { | ||
31 | kfree(fe->tuner_priv); | ||
32 | fe->tuner_priv = NULL; | ||
33 | return 0; | ||
34 | } | ||
35 | |||
36 | static int lgh06xf_set_params(struct dvb_frontend* fe, | ||
37 | struct dvb_frontend_parameters* params) | ||
38 | { | ||
39 | struct lgh06xf_priv *priv = fe->tuner_priv; | ||
40 | u8 buf[4]; | ||
41 | struct i2c_msg msg = { .addr = LG_H06XF_PLL_I2C_ADDR, .flags = 0, | ||
42 | .buf = buf, .len = sizeof(buf) }; | ||
43 | u32 frequency; | ||
44 | int result; | ||
45 | |||
46 | if ((result = dvb_pll_configure(&dvb_pll_lg_tdvs_h06xf, buf, | ||
47 | params->frequency, 0)) < 0) | ||
48 | return result; | ||
49 | else | ||
50 | frequency = result; | ||
51 | |||
52 | if (fe->ops.i2c_gate_ctrl) | ||
53 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
54 | if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) { | ||
55 | printk(KERN_WARNING "lgh06xf: %s error " | ||
56 | "(addr %02x <- %02x, result = %i)\n", | ||
57 | __FUNCTION__, buf[0], buf[1], result); | ||
58 | if (result < 0) | ||
59 | return result; | ||
60 | else | ||
61 | return -EREMOTEIO; | ||
62 | } | ||
63 | |||
64 | /* Set the Auxiliary Byte. */ | ||
65 | buf[0] = buf[2]; | ||
66 | buf[0] &= ~0x20; | ||
67 | buf[0] |= 0x18; | ||
68 | buf[1] = 0x50; | ||
69 | msg.len = 2; | ||
70 | if (fe->ops.i2c_gate_ctrl) | ||
71 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
72 | if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) { | ||
73 | printk(KERN_WARNING "lgh06xf: %s error " | ||
74 | "(addr %02x <- %02x, result = %i)\n", | ||
75 | __FUNCTION__, buf[0], buf[1], result); | ||
76 | if (result < 0) | ||
77 | return result; | ||
78 | else | ||
79 | return -EREMOTEIO; | ||
80 | } | ||
81 | |||
82 | priv->frequency = frequency; | ||
83 | |||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | static int lgh06xf_get_frequency(struct dvb_frontend *fe, u32 *frequency) | ||
88 | { | ||
89 | struct lgh06xf_priv *priv = fe->tuner_priv; | ||
90 | *frequency = priv->frequency; | ||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | static struct dvb_tuner_ops lgh06xf_tuner_ops = { | ||
95 | .release = lgh06xf_release, | ||
96 | .set_params = lgh06xf_set_params, | ||
97 | .get_frequency = lgh06xf_get_frequency, | ||
98 | }; | ||
99 | |||
100 | struct dvb_frontend* lgh06xf_attach(struct dvb_frontend *fe, | ||
101 | struct i2c_adapter *i2c) | ||
102 | { | ||
103 | struct lgh06xf_priv *priv = NULL; | ||
104 | |||
105 | priv = kzalloc(sizeof(struct lgh06xf_priv), GFP_KERNEL); | ||
106 | if (priv == NULL) | ||
107 | return NULL; | ||
108 | |||
109 | priv->i2c = i2c; | ||
110 | |||
111 | memcpy(&fe->ops.tuner_ops, &lgh06xf_tuner_ops, | ||
112 | sizeof(struct dvb_tuner_ops)); | ||
113 | |||
114 | strlcpy(fe->ops.tuner_ops.info.name, dvb_pll_lg_tdvs_h06xf.name, | ||
115 | sizeof(fe->ops.tuner_ops.info.name)); | ||
116 | |||
117 | fe->ops.tuner_ops.info.frequency_min = dvb_pll_lg_tdvs_h06xf.min; | ||
118 | fe->ops.tuner_ops.info.frequency_max = dvb_pll_lg_tdvs_h06xf.max; | ||
119 | |||
120 | fe->tuner_priv = priv; | ||
121 | return fe; | ||
122 | } | ||
123 | |||
124 | EXPORT_SYMBOL(lgh06xf_attach); | ||
125 | |||
126 | MODULE_DESCRIPTION("LG TDVS-H06xF ATSC Tuner support"); | ||
127 | MODULE_AUTHOR("Michael Krufky"); | ||
128 | MODULE_LICENSE("GPL"); | ||
129 | |||
130 | /* | ||
131 | * Local variables: | ||
132 | * c-basic-offset: 8 | ||
133 | * End: | ||
134 | */ | ||
diff --git a/drivers/media/dvb/frontends/lgh06xf.h b/drivers/media/dvb/frontends/lgh06xf.h new file mode 100644 index 000000000000..510b4bedfb24 --- /dev/null +++ b/drivers/media/dvb/frontends/lgh06xf.h | |||
@@ -0,0 +1,35 @@ | |||
1 | /* | ||
2 | * lgh06xf.h - ATSC Tuner support for LG TDVS-H06xF | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | */ | ||
18 | |||
19 | #ifndef _LGH06XF_H_ | ||
20 | #define _LGH06XF_H_ | ||
21 | #include "dvb_frontend.h" | ||
22 | |||
23 | #if defined(CONFIG_DVB_TUNER_LGH06XF) || (defined(CONFIG_DVB_TUNER_LGH06XF_MODULE) && defined(MODULE)) | ||
24 | extern struct dvb_frontend* lgh06xf_attach(struct dvb_frontend* fe, | ||
25 | struct i2c_adapter *i2c); | ||
26 | #else | ||
27 | static inline struct dvb_frontend* lgh06xf_attach(struct dvb_frontend* fe, | ||
28 | struct i2c_adapter *i2c) | ||
29 | { | ||
30 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); | ||
31 | return NULL; | ||
32 | } | ||
33 | #endif /* CONFIG_DVB_TUNER_LGH06XF */ | ||
34 | |||
35 | #endif /* _LGH06XF_H_ */ | ||
diff --git a/drivers/media/dvb/frontends/or51132.c b/drivers/media/dvb/frontends/or51132.c index d20ab30c1e83..5a3a6e53cda2 100644 --- a/drivers/media/dvb/frontends/or51132.c +++ b/drivers/media/dvb/frontends/or51132.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/slab.h> | 40 | #include <linux/slab.h> |
41 | #include <asm/byteorder.h> | 41 | #include <asm/byteorder.h> |
42 | 42 | ||
43 | #include "dvb_math.h" | ||
43 | #include "dvb_frontend.h" | 44 | #include "dvb_frontend.h" |
44 | #include "dvb-pll.h" | 45 | #include "dvb-pll.h" |
45 | #include "or51132.h" | 46 | #include "or51132.h" |
@@ -62,6 +63,7 @@ struct or51132_state | |||
62 | 63 | ||
63 | /* Demodulator private data */ | 64 | /* Demodulator private data */ |
64 | fe_modulation_t current_modulation; | 65 | fe_modulation_t current_modulation; |
66 | u32 snr; /* Result of last SNR calculation */ | ||
65 | 67 | ||
66 | /* Tuner private data */ | 68 | /* Tuner private data */ |
67 | u32 current_frequency; | 69 | u32 current_frequency; |
@@ -465,124 +467,128 @@ static int or51132_read_status(struct dvb_frontend* fe, fe_status_t* status) | |||
465 | return 0; | 467 | return 0; |
466 | } | 468 | } |
467 | 469 | ||
468 | /* log10-1 table at .5 increments from 1 to 100.5 */ | 470 | /* Calculate SNR estimation (scaled by 2^24) |
469 | static unsigned int i100x20log10[] = { | ||
470 | 0, 352, 602, 795, 954, 1088, 1204, 1306, 1397, 1480, | ||
471 | 1556, 1625, 1690, 1750, 1806, 1858, 1908, 1955, 2000, 2042, | ||
472 | 2082, 2121, 2158, 2193, 2227, 2260, 2292, 2322, 2352, 2380, | ||
473 | 2408, 2434, 2460, 2486, 2510, 2534, 2557, 2580, 2602, 2623, | ||
474 | 2644, 2664, 2684, 2704, 2723, 2742, 2760, 2778, 2795, 2813, | ||
475 | 2829, 2846, 2862, 2878, 2894, 2909, 2924, 2939, 2954, 2968, | ||
476 | 2982, 2996, 3010, 3023, 3037, 3050, 3062, 3075, 3088, 3100, | ||
477 | 3112, 3124, 3136, 3148, 3159, 3170, 3182, 3193, 3204, 3214, | ||
478 | 3225, 3236, 3246, 3256, 3266, 3276, 3286, 3296, 3306, 3316, | ||
479 | 3325, 3334, 3344, 3353, 3362, 3371, 3380, 3389, 3397, 3406, | ||
480 | 3415, 3423, 3432, 3440, 3448, 3456, 3464, 3472, 3480, 3488, | ||
481 | 3496, 3504, 3511, 3519, 3526, 3534, 3541, 3549, 3556, 3563, | ||
482 | 3570, 3577, 3584, 3591, 3598, 3605, 3612, 3619, 3625, 3632, | ||
483 | 3639, 3645, 3652, 3658, 3665, 3671, 3677, 3683, 3690, 3696, | ||
484 | 3702, 3708, 3714, 3720, 3726, 3732, 3738, 3744, 3750, 3755, | ||
485 | 3761, 3767, 3772, 3778, 3784, 3789, 3795, 3800, 3806, 3811, | ||
486 | 3816, 3822, 3827, 3832, 3838, 3843, 3848, 3853, 3858, 3863, | ||
487 | 3868, 3874, 3879, 3884, 3888, 3893, 3898, 3903, 3908, 3913, | ||
488 | 3918, 3922, 3927, 3932, 3936, 3941, 3946, 3950, 3955, 3960, | ||
489 | 3964, 3969, 3973, 3978, 3982, 3986, 3991, 3995, 4000, 4004, | ||
490 | }; | ||
491 | 471 | ||
492 | static unsigned int denom[] = {1,1,100,1000,10000,100000,1000000,10000000,100000000}; | 472 | 8-VSB SNR and QAM equations from Oren datasheets |
493 | 473 | ||
494 | static unsigned int i20Log10(unsigned short val) | 474 | For 8-VSB: |
495 | { | 475 | SNR[dB] = 10 * log10(897152044.8282 / MSE^2 ) - K |
496 | unsigned int rntval = 100; | 476 | |
497 | unsigned int tmp = val; | 477 | Where K = 0 if NTSC rejection filter is OFF; and |
498 | unsigned int exp = 1; | 478 | K = 3 if NTSC rejection filter is ON |
479 | |||
480 | For QAM64: | ||
481 | SNR[dB] = 10 * log10(897152044.8282 / MSE^2 ) | ||
499 | 482 | ||
500 | while(tmp > 100) {tmp /= 100; exp++;} | 483 | For QAM256: |
484 | SNR[dB] = 10 * log10(907832426.314266 / MSE^2 ) | ||
501 | 485 | ||
502 | val = (2 * val)/denom[exp]; | 486 | We re-write the snr equation as: |
503 | if (exp > 1) rntval = 2000*exp; | 487 | SNR * 2^24 = 10*(c - 2*intlog10(MSE)) |
488 | Where for QAM256, c = log10(907832426.314266) * 2^24 | ||
489 | and for 8-VSB and QAM64, c = log10(897152044.8282) * 2^24 */ | ||
504 | 490 | ||
505 | rntval += i100x20log10[val]; | 491 | static u32 calculate_snr(u32 mse, u32 c) |
506 | return rntval; | 492 | { |
493 | if (mse == 0) /* No signal */ | ||
494 | return 0; | ||
495 | |||
496 | mse = 2*intlog10(mse); | ||
497 | if (mse > c) { | ||
498 | /* Negative SNR, which is possible, but realisticly the | ||
499 | demod will lose lock before the signal gets this bad. The | ||
500 | API only allows for unsigned values, so just return 0 */ | ||
501 | return 0; | ||
502 | } | ||
503 | return 10*(c - mse); | ||
507 | } | 504 | } |
508 | 505 | ||
509 | static int or51132_read_signal_strength(struct dvb_frontend* fe, u16* strength) | 506 | static int or51132_read_snr(struct dvb_frontend* fe, u16* snr) |
510 | { | 507 | { |
511 | struct or51132_state* state = fe->demodulator_priv; | 508 | struct or51132_state* state = fe->demodulator_priv; |
512 | unsigned char rec_buf[2]; | 509 | u8 rec_buf[2]; |
513 | unsigned char snd_buf[2]; | 510 | u8 snd_buf[2]; |
514 | u8 rcvr_stat; | 511 | u32 noise; |
515 | u16 snr_equ; | 512 | u32 c; |
516 | u32 signal_strength; | 513 | u32 usK; |
517 | int usK; | ||
518 | 514 | ||
515 | /* Register is same for VSB or QAM firmware */ | ||
519 | snd_buf[0]=0x04; | 516 | snd_buf[0]=0x04; |
520 | snd_buf[1]=0x02; /* SNR after Equalizer */ | 517 | snd_buf[1]=0x02; /* SNR after Equalizer */ |
521 | msleep(30); /* 30ms */ | 518 | msleep(30); /* 30ms */ |
522 | if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) { | 519 | if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) { |
523 | printk(KERN_WARNING "or51132: read_status write error\n"); | 520 | printk(KERN_WARNING "or51132: snr write error\n"); |
524 | return -1; | 521 | return -EREMOTEIO; |
525 | } | 522 | } |
526 | msleep(30); /* 30ms */ | 523 | msleep(30); /* 30ms */ |
527 | if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { | 524 | if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { |
528 | printk(KERN_WARNING "or51132: read_status read error\n"); | 525 | printk(KERN_WARNING "or51132: snr read error\n"); |
529 | return -1; | 526 | return -EREMOTEIO; |
530 | } | 527 | } |
531 | snr_equ = rec_buf[0] | (rec_buf[1] << 8); | 528 | noise = rec_buf[0] | (rec_buf[1] << 8); |
532 | dprintk("read_signal_strength snr_equ %x %x (%i)\n",rec_buf[0],rec_buf[1],snr_equ); | 529 | dprintk("read_snr noise %x %x (%i)\n",rec_buf[0],rec_buf[1],noise); |
533 | 530 | ||
534 | /* Receiver Status */ | 531 | /* Read status, contains modulation type for QAM_AUTO and |
532 | NTSC filter for VSB */ | ||
535 | snd_buf[0]=0x04; | 533 | snd_buf[0]=0x04; |
536 | snd_buf[1]=0x00; | 534 | snd_buf[1]=0x00; /* Status register */ |
537 | msleep(30); /* 30ms */ | 535 | msleep(30); /* 30ms */ |
538 | if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) { | 536 | if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) { |
539 | printk(KERN_WARNING "or51132: read_signal_strength read_status write error\n"); | 537 | printk(KERN_WARNING "or51132: status write error\n"); |
540 | return -1; | 538 | return -EREMOTEIO; |
541 | } | 539 | } |
542 | msleep(30); /* 30ms */ | 540 | msleep(30); /* 30ms */ |
543 | if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { | 541 | if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { |
544 | printk(KERN_WARNING "or51132: read_signal_strength read_status read error\n"); | 542 | printk(KERN_WARNING "or51132: status read error\n"); |
545 | return -1; | 543 | return -EREMOTEIO; |
546 | } | 544 | } |
547 | dprintk("read_signal_strength read_status %x %x\n",rec_buf[0],rec_buf[1]); | ||
548 | rcvr_stat = rec_buf[1]; | ||
549 | usK = (rcvr_stat & 0x10) ? 3 : 0; | ||
550 | 545 | ||
551 | /* The value reported back from the frontend will be FFFF=100% 0000=0% */ | 546 | usK = 0; |
552 | signal_strength = (((8952 - i20Log10(snr_equ) - usK*100)/3+5)*65535)/1000; | 547 | switch (rec_buf[0]) { |
553 | if (signal_strength > 0xffff) | 548 | case 0x06: |
554 | *strength = 0xffff; | 549 | usK = (rec_buf[1] & 0x10) ? 0x03000000 : 0; |
555 | else | 550 | /* Fall through to QAM64 case */ |
556 | *strength = signal_strength; | 551 | case 0x43: |
557 | dprintk("read_signal_strength %i\n",*strength); | 552 | c = 150204167; |
553 | break; | ||
554 | case 0x45: | ||
555 | c = 150290396; | ||
556 | break; | ||
557 | default: | ||
558 | printk(KERN_ERR "or51132: unknown status 0x%02x\n", rec_buf[0]); | ||
559 | return -EREMOTEIO; | ||
560 | } | ||
561 | dprintk("%s: modulation %02x, NTSC rej O%s\n", __FUNCTION__, | ||
562 | rec_buf[0], rec_buf[1]&0x10?"n":"ff"); | ||
563 | |||
564 | /* Calculate SNR using noise, c, and NTSC rejection correction */ | ||
565 | state->snr = calculate_snr(noise, c) - usK; | ||
566 | *snr = (state->snr) >> 16; | ||
567 | |||
568 | dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise, | ||
569 | state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16); | ||
558 | 570 | ||
559 | return 0; | 571 | return 0; |
560 | } | 572 | } |
561 | 573 | ||
562 | static int or51132_read_snr(struct dvb_frontend* fe, u16* snr) | 574 | static int or51132_read_signal_strength(struct dvb_frontend* fe, u16* strength) |
563 | { | 575 | { |
564 | struct or51132_state* state = fe->demodulator_priv; | 576 | /* Calculate Strength from SNR up to 35dB */ |
565 | unsigned char rec_buf[2]; | 577 | /* Even though the SNR can go higher than 35dB, there is some comfort */ |
566 | unsigned char snd_buf[2]; | 578 | /* factor in having a range of strong signals that can show at 100% */ |
567 | u16 snr_equ; | 579 | struct or51132_state* state = (struct or51132_state*) fe->demodulator_priv; |
568 | 580 | u16 snr; | |
569 | snd_buf[0]=0x04; | 581 | int ret; |
570 | snd_buf[1]=0x02; /* SNR after Equalizer */ | ||
571 | msleep(30); /* 30ms */ | ||
572 | if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) { | ||
573 | printk(KERN_WARNING "or51132: read_snr write error\n"); | ||
574 | return -1; | ||
575 | } | ||
576 | msleep(30); /* 30ms */ | ||
577 | if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { | ||
578 | printk(KERN_WARNING "or51132: read_snr dvr read error\n"); | ||
579 | return -1; | ||
580 | } | ||
581 | snr_equ = rec_buf[0] | (rec_buf[1] << 8); | ||
582 | dprintk("read_snr snr_equ %x %x (%i)\n",rec_buf[0],rec_buf[1],snr_equ); | ||
583 | 582 | ||
584 | *snr = 0xFFFF - snr_equ; | 583 | ret = fe->ops.read_snr(fe, &snr); |
585 | dprintk("read_snr %i\n",*snr); | 584 | if (ret != 0) |
585 | return ret; | ||
586 | /* Rather than use the 8.8 value snr, use state->snr which is 8.24 */ | ||
587 | /* scale the range 0 - 35*2^24 into 0 - 65535 */ | ||
588 | if (state->snr >= 8960 * 0x10000) | ||
589 | *strength = 0xffff; | ||
590 | else | ||
591 | *strength = state->snr / 8960; | ||
586 | 592 | ||
587 | return 0; | 593 | return 0; |
588 | } | 594 | } |
diff --git a/drivers/media/dvb/frontends/or51211.c b/drivers/media/dvb/frontends/or51211.c index 2bf124b53689..048d7cfe12d3 100644 --- a/drivers/media/dvb/frontends/or51211.c +++ b/drivers/media/dvb/frontends/or51211.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <linux/slab.h> | 39 | #include <linux/slab.h> |
40 | #include <asm/byteorder.h> | 40 | #include <asm/byteorder.h> |
41 | 41 | ||
42 | #include "dvb_math.h" | ||
42 | #include "dvb_frontend.h" | 43 | #include "dvb_frontend.h" |
43 | #include "or51211.h" | 44 | #include "or51211.h" |
44 | 45 | ||
@@ -63,6 +64,7 @@ struct or51211_state { | |||
63 | 64 | ||
64 | /* Demodulator private data */ | 65 | /* Demodulator private data */ |
65 | u8 initialized:1; | 66 | u8 initialized:1; |
67 | u32 snr; /* Result of last SNR claculation */ | ||
66 | 68 | ||
67 | /* Tuner private data */ | 69 | /* Tuner private data */ |
68 | u32 current_frequency; | 70 | u32 current_frequency; |
@@ -292,107 +294,81 @@ static int or51211_read_status(struct dvb_frontend* fe, fe_status_t* status) | |||
292 | return 0; | 294 | return 0; |
293 | } | 295 | } |
294 | 296 | ||
295 | /* log10-1 table at .5 increments from 1 to 100.5 */ | 297 | /* Calculate SNR estimation (scaled by 2^24) |
296 | static unsigned int i100x20log10[] = { | ||
297 | 0, 352, 602, 795, 954, 1088, 1204, 1306, 1397, 1480, | ||
298 | 1556, 1625, 1690, 1750, 1806, 1858, 1908, 1955, 2000, 2042, | ||
299 | 2082, 2121, 2158, 2193, 2227, 2260, 2292, 2322, 2352, 2380, | ||
300 | 2408, 2434, 2460, 2486, 2510, 2534, 2557, 2580, 2602, 2623, | ||
301 | 2644, 2664, 2684, 2704, 2723, 2742, 2760, 2778, 2795, 2813, | ||
302 | 2829, 2846, 2862, 2878, 2894, 2909, 2924, 2939, 2954, 2968, | ||
303 | 2982, 2996, 3010, 3023, 3037, 3050, 3062, 3075, 3088, 3100, | ||
304 | 3112, 3124, 3136, 3148, 3159, 3170, 3182, 3193, 3204, 3214, | ||
305 | 3225, 3236, 3246, 3256, 3266, 3276, 3286, 3296, 3306, 3316, | ||
306 | 3325, 3334, 3344, 3353, 3362, 3371, 3380, 3389, 3397, 3406, | ||
307 | 3415, 3423, 3432, 3440, 3448, 3456, 3464, 3472, 3480, 3488, | ||
308 | 3496, 3504, 3511, 3519, 3526, 3534, 3541, 3549, 3556, 3563, | ||
309 | 3570, 3577, 3584, 3591, 3598, 3605, 3612, 3619, 3625, 3632, | ||
310 | 3639, 3645, 3652, 3658, 3665, 3671, 3677, 3683, 3690, 3696, | ||
311 | 3702, 3708, 3714, 3720, 3726, 3732, 3738, 3744, 3750, 3755, | ||
312 | 3761, 3767, 3772, 3778, 3784, 3789, 3795, 3800, 3806, 3811, | ||
313 | 3816, 3822, 3827, 3832, 3838, 3843, 3848, 3853, 3858, 3863, | ||
314 | 3868, 3874, 3879, 3884, 3888, 3893, 3898, 3903, 3908, 3913, | ||
315 | 3918, 3922, 3927, 3932, 3936, 3941, 3946, 3950, 3955, 3960, | ||
316 | 3964, 3969, 3973, 3978, 3982, 3986, 3991, 3995, 4000, 4004, | ||
317 | }; | ||
318 | |||
319 | static unsigned int denom[] = {1,1,100,1000,10000,100000,1000000,10000000,100000000}; | ||
320 | 298 | ||
321 | static unsigned int i20Log10(unsigned short val) | 299 | 8-VSB SNR equation from Oren datasheets |
322 | { | ||
323 | unsigned int rntval = 100; | ||
324 | unsigned int tmp = val; | ||
325 | unsigned int exp = 1; | ||
326 | 300 | ||
327 | while(tmp > 100) {tmp /= 100; exp++;} | 301 | For 8-VSB: |
302 | SNR[dB] = 10 * log10(219037.9454 / MSE^2 ) | ||
328 | 303 | ||
329 | val = (2 * val)/denom[exp]; | 304 | We re-write the snr equation as: |
330 | if (exp > 1) rntval = 2000*exp; | 305 | SNR * 2^24 = 10*(c - 2*intlog10(MSE)) |
306 | Where for 8-VSB, c = log10(219037.9454) * 2^24 */ | ||
331 | 307 | ||
332 | rntval += i100x20log10[val]; | 308 | static u32 calculate_snr(u32 mse, u32 c) |
333 | return rntval; | 309 | { |
310 | if (mse == 0) /* No signal */ | ||
311 | return 0; | ||
312 | |||
313 | mse = 2*intlog10(mse); | ||
314 | if (mse > c) { | ||
315 | /* Negative SNR, which is possible, but realisticly the | ||
316 | demod will lose lock before the signal gets this bad. The | ||
317 | API only allows for unsigned values, so just return 0 */ | ||
318 | return 0; | ||
319 | } | ||
320 | return 10*(c - mse); | ||
334 | } | 321 | } |
335 | 322 | ||
336 | static int or51211_read_signal_strength(struct dvb_frontend* fe, u16* strength) | 323 | static int or51211_read_snr(struct dvb_frontend* fe, u16* snr) |
337 | { | 324 | { |
338 | struct or51211_state* state = fe->demodulator_priv; | 325 | struct or51211_state* state = fe->demodulator_priv; |
339 | u8 rec_buf[2]; | 326 | u8 rec_buf[2]; |
340 | u8 snd_buf[4]; | 327 | u8 snd_buf[3]; |
341 | u8 snr_equ; | ||
342 | u32 signal_strength; | ||
343 | 328 | ||
344 | /* SNR after Equalizer */ | 329 | /* SNR after Equalizer */ |
345 | snd_buf[0] = 0x04; | 330 | snd_buf[0] = 0x04; |
346 | snd_buf[1] = 0x00; | 331 | snd_buf[1] = 0x00; |
347 | snd_buf[2] = 0x04; | 332 | snd_buf[2] = 0x04; |
348 | snd_buf[3] = 0x00; | ||
349 | 333 | ||
350 | if (i2c_writebytes(state,state->config->demod_address,snd_buf,3)) { | 334 | if (i2c_writebytes(state,state->config->demod_address,snd_buf,3)) { |
351 | printk(KERN_WARNING "or51211: read_status write error\n"); | 335 | printk(KERN_WARNING "%s: error writing snr reg\n", |
336 | __FUNCTION__); | ||
352 | return -1; | 337 | return -1; |
353 | } | 338 | } |
354 | msleep(3); | ||
355 | if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { | 339 | if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { |
356 | printk(KERN_WARNING "or51211: read_status read error\n"); | 340 | printk(KERN_WARNING "%s: read_status read error\n", |
341 | __FUNCTION__); | ||
357 | return -1; | 342 | return -1; |
358 | } | 343 | } |
359 | snr_equ = rec_buf[0] & 0xff; | ||
360 | 344 | ||
361 | /* The value reported back from the frontend will be FFFF=100% 0000=0% */ | 345 | state->snr = calculate_snr(rec_buf[0], 89599047); |
362 | signal_strength = (((5334 - i20Log10(snr_equ))/3+5)*65535)/1000; | 346 | *snr = (state->snr) >> 16; |
363 | if (signal_strength > 0xffff) | 347 | |
364 | *strength = 0xffff; | 348 | dprintk("%s: noise = 0x%02x, snr = %d.%02d dB\n", __FUNCTION__, rec_buf[0], |
365 | else | 349 | state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16); |
366 | *strength = signal_strength; | ||
367 | dprintk("read_signal_strength %i\n",*strength); | ||
368 | 350 | ||
369 | return 0; | 351 | return 0; |
370 | } | 352 | } |
371 | 353 | ||
372 | static int or51211_read_snr(struct dvb_frontend* fe, u16* snr) | 354 | static int or51211_read_signal_strength(struct dvb_frontend* fe, u16* strength) |
373 | { | 355 | { |
374 | struct or51211_state* state = fe->demodulator_priv; | 356 | /* Calculate Strength from SNR up to 35dB */ |
375 | u8 rec_buf[2]; | 357 | /* Even though the SNR can go higher than 35dB, there is some comfort */ |
376 | u8 snd_buf[4]; | 358 | /* factor in having a range of strong signals that can show at 100% */ |
377 | 359 | struct or51211_state* state = (struct or51211_state*)fe->demodulator_priv; | |
378 | /* SNR after Equalizer */ | 360 | u16 snr; |
379 | snd_buf[0] = 0x04; | 361 | int ret; |
380 | snd_buf[1] = 0x00; | 362 | |
381 | snd_buf[2] = 0x04; | 363 | ret = fe->ops.read_snr(fe, &snr); |
382 | snd_buf[3] = 0x00; | 364 | if (ret != 0) |
383 | 365 | return ret; | |
384 | if (i2c_writebytes(state,state->config->demod_address,snd_buf,3)) { | 366 | /* Rather than use the 8.8 value snr, use state->snr which is 8.24 */ |
385 | printk(KERN_WARNING "or51211: read_status write error\n"); | 367 | /* scale the range 0 - 35*2^24 into 0 - 65535 */ |
386 | return -1; | 368 | if (state->snr >= 8960 * 0x10000) |
387 | } | 369 | *strength = 0xffff; |
388 | msleep(3); | 370 | else |
389 | if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { | 371 | *strength = state->snr / 8960; |
390 | printk(KERN_WARNING "or51211: read_status read error\n"); | ||
391 | return -1; | ||
392 | } | ||
393 | *snr = rec_buf[0] & 0xff; | ||
394 | |||
395 | dprintk("read_snr %i\n",*snr); | ||
396 | 372 | ||
397 | return 0; | 373 | return 0; |
398 | } | 374 | } |
diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c index 11e0dca9a2d7..00e4bcd9f1a4 100644 --- a/drivers/media/dvb/frontends/tda1004x.c +++ b/drivers/media/dvb/frontends/tda1004x.c | |||
@@ -648,18 +648,24 @@ static int tda10046_init(struct dvb_frontend* fe) | |||
648 | tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x0a); // AGC setup | 648 | tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x0a); // AGC setup |
649 | tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x00); // set AGC polarities | 649 | tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x00); // set AGC polarities |
650 | break; | 650 | break; |
651 | case TDA10046_AGC_TDA827X: | 651 | case TDA10046_AGC_TDA827X_GP11: |
652 | tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup | 652 | tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup |
653 | tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold | 653 | tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold |
654 | tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize | 654 | tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize |
655 | tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x6a); // set AGC polarities | 655 | tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x6a); // set AGC polarities |
656 | break; | 656 | break; |
657 | case TDA10046_AGC_TDA827X_GPL: | 657 | case TDA10046_AGC_TDA827X_GP00: |
658 | tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup | 658 | tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup |
659 | tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold | 659 | tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold |
660 | tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize | 660 | tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize |
661 | tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x60); // set AGC polarities | 661 | tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x60); // set AGC polarities |
662 | break; | 662 | break; |
663 | case TDA10046_AGC_TDA827X_GP01: | ||
664 | tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup | ||
665 | tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold | ||
666 | tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize | ||
667 | tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x62); // set AGC polarities | ||
668 | break; | ||
663 | } | 669 | } |
664 | tda1004x_write_byteI(state, TDA1004X_CONFADC2, 0x38); | 670 | tda1004x_write_byteI(state, TDA1004X_CONFADC2, 0x38); |
665 | tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0x61); // Turn both AGC outputs on | 671 | tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0x61); // Turn both AGC outputs on |
diff --git a/drivers/media/dvb/frontends/tda1004x.h b/drivers/media/dvb/frontends/tda1004x.h index 605ad2dfc09d..ec502d71b83c 100644 --- a/drivers/media/dvb/frontends/tda1004x.h +++ b/drivers/media/dvb/frontends/tda1004x.h | |||
@@ -35,8 +35,9 @@ enum tda10046_agc { | |||
35 | TDA10046_AGC_DEFAULT, /* original configuration */ | 35 | TDA10046_AGC_DEFAULT, /* original configuration */ |
36 | TDA10046_AGC_IFO_AUTO_NEG, /* IF AGC only, automatic, negtive */ | 36 | TDA10046_AGC_IFO_AUTO_NEG, /* IF AGC only, automatic, negtive */ |
37 | TDA10046_AGC_IFO_AUTO_POS, /* IF AGC only, automatic, positive */ | 37 | TDA10046_AGC_IFO_AUTO_POS, /* IF AGC only, automatic, positive */ |
38 | TDA10046_AGC_TDA827X, /* IF AGC only, special setup for tda827x */ | 38 | TDA10046_AGC_TDA827X_GP11, /* IF AGC only, special setup for tda827x */ |
39 | TDA10046_AGC_TDA827X_GPL, /* same as above, but GPIOs 0 */ | 39 | TDA10046_AGC_TDA827X_GP00, /* same as above, but GPIOs 0 */ |
40 | TDA10046_AGC_TDA827X_GP01, /* same as above, but GPIO3=0 GPIO1=1*/ | ||
40 | }; | 41 | }; |
41 | 42 | ||
42 | enum tda10046_if { | 43 | enum tda10046_if { |
diff --git a/drivers/media/dvb/frontends/tda8083.c b/drivers/media/dvb/frontends/tda8083.c index 3aa45ebbac3d..67415c9db6f7 100644 --- a/drivers/media/dvb/frontends/tda8083.c +++ b/drivers/media/dvb/frontends/tda8083.c | |||
@@ -262,12 +262,29 @@ static int tda8083_read_status(struct dvb_frontend* fe, fe_status_t* status) | |||
262 | if (sync & 0x10) | 262 | if (sync & 0x10) |
263 | *status |= FE_HAS_SYNC; | 263 | *status |= FE_HAS_SYNC; |
264 | 264 | ||
265 | if (sync & 0x20) /* frontend can not lock */ | ||
266 | *status |= FE_TIMEDOUT; | ||
267 | |||
265 | if ((sync & 0x1f) == 0x1f) | 268 | if ((sync & 0x1f) == 0x1f) |
266 | *status |= FE_HAS_LOCK; | 269 | *status |= FE_HAS_LOCK; |
267 | 270 | ||
268 | return 0; | 271 | return 0; |
269 | } | 272 | } |
270 | 273 | ||
274 | static int tda8083_read_ber(struct dvb_frontend* fe, u32* ber) | ||
275 | { | ||
276 | struct tda8083_state* state = fe->demodulator_priv; | ||
277 | int ret; | ||
278 | u8 buf[3]; | ||
279 | |||
280 | if ((ret = tda8083_readregs(state, 0x0b, buf, sizeof(buf)))) | ||
281 | return ret; | ||
282 | |||
283 | *ber = ((buf[0] & 0x1f) << 16) | (buf[1] << 8) | buf[2]; | ||
284 | |||
285 | return 0; | ||
286 | } | ||
287 | |||
271 | static int tda8083_read_signal_strength(struct dvb_frontend* fe, u16* strength) | 288 | static int tda8083_read_signal_strength(struct dvb_frontend* fe, u16* strength) |
272 | { | 289 | { |
273 | struct tda8083_state* state = fe->demodulator_priv; | 290 | struct tda8083_state* state = fe->demodulator_priv; |
@@ -288,6 +305,17 @@ static int tda8083_read_snr(struct dvb_frontend* fe, u16* snr) | |||
288 | return 0; | 305 | return 0; |
289 | } | 306 | } |
290 | 307 | ||
308 | static int tda8083_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) | ||
309 | { | ||
310 | struct tda8083_state* state = fe->demodulator_priv; | ||
311 | |||
312 | *ucblocks = tda8083_readreg(state, 0x0f); | ||
313 | if (*ucblocks == 0xff) | ||
314 | *ucblocks = 0xffffffff; | ||
315 | |||
316 | return 0; | ||
317 | } | ||
318 | |||
291 | static int tda8083_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) | 319 | static int tda8083_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) |
292 | { | 320 | { |
293 | struct tda8083_state* state = fe->demodulator_priv; | 321 | struct tda8083_state* state = fe->demodulator_priv; |
@@ -440,6 +468,8 @@ static struct dvb_frontend_ops tda8083_ops = { | |||
440 | .read_status = tda8083_read_status, | 468 | .read_status = tda8083_read_status, |
441 | .read_signal_strength = tda8083_read_signal_strength, | 469 | .read_signal_strength = tda8083_read_signal_strength, |
442 | .read_snr = tda8083_read_snr, | 470 | .read_snr = tda8083_read_snr, |
471 | .read_ber = tda8083_read_ber, | ||
472 | .read_ucblocks = tda8083_read_ucblocks, | ||
443 | 473 | ||
444 | .diseqc_send_master_cmd = tda8083_send_diseqc_msg, | 474 | .diseqc_send_master_cmd = tda8083_send_diseqc_msg, |
445 | .diseqc_send_burst = tda8083_diseqc_send_burst, | 475 | .diseqc_send_burst = tda8083_diseqc_send_burst, |
diff --git a/drivers/media/dvb/frontends/tda826x.c b/drivers/media/dvb/frontends/tda826x.c index 34815b0b97e4..79f971dc52b6 100644 --- a/drivers/media/dvb/frontends/tda826x.c +++ b/drivers/media/dvb/frontends/tda826x.c | |||
@@ -42,8 +42,7 @@ struct tda826x_priv { | |||
42 | 42 | ||
43 | static int tda826x_release(struct dvb_frontend *fe) | 43 | static int tda826x_release(struct dvb_frontend *fe) |
44 | { | 44 | { |
45 | if (fe->tuner_priv) | 45 | kfree(fe->tuner_priv); |
46 | kfree(fe->tuner_priv); | ||
47 | fe->tuner_priv = NULL; | 46 | fe->tuner_priv = NULL; |
48 | return 0; | 47 | return 0; |
49 | } | 48 | } |
@@ -133,18 +132,21 @@ struct dvb_frontend *tda826x_attach(struct dvb_frontend *fe, int addr, struct i2 | |||
133 | { | 132 | { |
134 | struct tda826x_priv *priv = NULL; | 133 | struct tda826x_priv *priv = NULL; |
135 | u8 b1 [] = { 0, 0 }; | 134 | u8 b1 [] = { 0, 0 }; |
136 | struct i2c_msg msg = { .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 2 }; | 135 | struct i2c_msg msg[2] = { |
136 | { .addr = addr, .flags = 0, .buf = NULL, .len = 0 }, | ||
137 | { .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 2 } | ||
138 | }; | ||
137 | int ret; | 139 | int ret; |
138 | 140 | ||
139 | dprintk("%s:\n", __FUNCTION__); | 141 | dprintk("%s:\n", __FUNCTION__); |
140 | 142 | ||
141 | if (fe->ops.i2c_gate_ctrl) | 143 | if (fe->ops.i2c_gate_ctrl) |
142 | fe->ops.i2c_gate_ctrl(fe, 1); | 144 | fe->ops.i2c_gate_ctrl(fe, 1); |
143 | ret = i2c_transfer (i2c, &msg, 1); | 145 | ret = i2c_transfer (i2c, msg, 2); |
144 | if (fe->ops.i2c_gate_ctrl) | 146 | if (fe->ops.i2c_gate_ctrl) |
145 | fe->ops.i2c_gate_ctrl(fe, 0); | 147 | fe->ops.i2c_gate_ctrl(fe, 0); |
146 | 148 | ||
147 | if (ret != 1) | 149 | if (ret != 2) |
148 | return NULL; | 150 | return NULL; |
149 | if (!(b1[1] & 0x80)) | 151 | if (!(b1[1] & 0x80)) |
150 | return NULL; | 152 | return NULL; |
diff --git a/drivers/media/dvb/frontends/tua6100.c b/drivers/media/dvb/frontends/tua6100.c index 88554393a9bf..6ba0029dcf2e 100644 --- a/drivers/media/dvb/frontends/tua6100.c +++ b/drivers/media/dvb/frontends/tua6100.c | |||
@@ -43,8 +43,7 @@ struct tua6100_priv { | |||
43 | 43 | ||
44 | static int tua6100_release(struct dvb_frontend *fe) | 44 | static int tua6100_release(struct dvb_frontend *fe) |
45 | { | 45 | { |
46 | if (fe->tuner_priv) | 46 | kfree(fe->tuner_priv); |
47 | kfree(fe->tuner_priv); | ||
48 | fe->tuner_priv = NULL; | 47 | fe->tuner_priv = NULL; |
49 | return 0; | 48 | return 0; |
50 | } | 49 | } |
diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig index 95531a624991..eec7ccf41f8b 100644 --- a/drivers/media/dvb/ttpci/Kconfig +++ b/drivers/media/dvb/ttpci/Kconfig | |||
@@ -92,6 +92,7 @@ config DVB_BUDGET_CI | |||
92 | select DVB_STV0299 if !DVB_FE_CUSTOMISE | 92 | select DVB_STV0299 if !DVB_FE_CUSTOMISE |
93 | select DVB_TDA1004X if !DVB_FE_CUSTOMISE | 93 | select DVB_TDA1004X if !DVB_FE_CUSTOMISE |
94 | select DVB_LNBP21 if !DVB_FE_CUSTOMISE | 94 | select DVB_LNBP21 if !DVB_FE_CUSTOMISE |
95 | select VIDEO_IR | ||
95 | help | 96 | help |
96 | Support for simple SAA7146 based DVB cards | 97 | Support for simple SAA7146 based DVB cards |
97 | (so called Budget- or Nova-PCI cards) without onboard | 98 | (so called Budget- or Nova-PCI cards) without onboard |
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index bba23bcd1b11..366c1371ee97 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c | |||
@@ -2828,7 +2828,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl); | |||
2828 | 2828 | ||
2829 | static struct saa7146_extension av7110_extension = { | 2829 | static struct saa7146_extension av7110_extension = { |
2830 | .name = "dvb", | 2830 | .name = "dvb", |
2831 | .flags = SAA7146_I2C_SHORT_DELAY, | 2831 | .flags = SAA7146_USE_I2C_IRQ, |
2832 | 2832 | ||
2833 | .module = THIS_MODULE, | 2833 | .module = THIS_MODULE, |
2834 | .pci_tbl = &pci_tbl[0], | 2834 | .pci_tbl = &pci_tbl[0], |
diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c index d54bbcdde2cc..e4544ea2b89b 100644 --- a/drivers/media/dvb/ttpci/av7110_ir.c +++ b/drivers/media/dvb/ttpci/av7110_ir.c | |||
@@ -48,7 +48,8 @@ static void av7110_emit_keyup(unsigned long data) | |||
48 | if (!data || !test_bit(data, input_dev->key)) | 48 | if (!data || !test_bit(data, input_dev->key)) |
49 | return; | 49 | return; |
50 | 50 | ||
51 | input_event(input_dev, EV_KEY, data, !!0); | 51 | input_report_key(input_dev, data, 0); |
52 | input_sync(input_dev); | ||
52 | } | 53 | } |
53 | 54 | ||
54 | 55 | ||
@@ -115,14 +116,17 @@ static void av7110_emit_key(unsigned long parm) | |||
115 | del_timer(&keyup_timer); | 116 | del_timer(&keyup_timer); |
116 | if (keyup_timer.data != keycode || new_toggle != old_toggle) { | 117 | if (keyup_timer.data != keycode || new_toggle != old_toggle) { |
117 | delay_timer_finished = 0; | 118 | delay_timer_finished = 0; |
118 | input_event(input_dev, EV_KEY, keyup_timer.data, !!0); | 119 | input_event(input_dev, EV_KEY, keyup_timer.data, 0); |
119 | input_event(input_dev, EV_KEY, keycode, !0); | 120 | input_event(input_dev, EV_KEY, keycode, 1); |
120 | } else | 121 | input_sync(input_dev); |
121 | if (delay_timer_finished) | 122 | } else if (delay_timer_finished) { |
122 | input_event(input_dev, EV_KEY, keycode, 2); | 123 | input_event(input_dev, EV_KEY, keycode, 2); |
124 | input_sync(input_dev); | ||
125 | } | ||
123 | } else { | 126 | } else { |
124 | delay_timer_finished = 0; | 127 | delay_timer_finished = 0; |
125 | input_event(input_dev, EV_KEY, keycode, !0); | 128 | input_event(input_dev, EV_KEY, keycode, 1); |
129 | input_sync(input_dev); | ||
126 | } | 130 | } |
127 | 131 | ||
128 | keyup_timer.expires = jiffies + UP_TIMEOUT; | 132 | keyup_timer.expires = jiffies + UP_TIMEOUT; |
@@ -211,6 +215,7 @@ static void ir_handler(struct av7110 *av7110, u32 ircom) | |||
211 | int __devinit av7110_ir_init(struct av7110 *av7110) | 215 | int __devinit av7110_ir_init(struct av7110 *av7110) |
212 | { | 216 | { |
213 | static struct proc_dir_entry *e; | 217 | static struct proc_dir_entry *e; |
218 | int err; | ||
214 | 219 | ||
215 | if (av_cnt >= sizeof av_list/sizeof av_list[0]) | 220 | if (av_cnt >= sizeof av_list/sizeof av_list[0]) |
216 | return -ENOSPC; | 221 | return -ENOSPC; |
@@ -231,7 +236,11 @@ int __devinit av7110_ir_init(struct av7110 *av7110) | |||
231 | set_bit(EV_KEY, input_dev->evbit); | 236 | set_bit(EV_KEY, input_dev->evbit); |
232 | set_bit(EV_REP, input_dev->evbit); | 237 | set_bit(EV_REP, input_dev->evbit); |
233 | input_register_keys(); | 238 | input_register_keys(); |
234 | input_register_device(input_dev); | 239 | err = input_register_device(input_dev); |
240 | if (err) { | ||
241 | input_free_device(input_dev); | ||
242 | return err; | ||
243 | } | ||
235 | input_dev->timer.function = input_repeat_key; | 244 | input_dev->timer.function = input_repeat_key; |
236 | 245 | ||
237 | e = create_proc_entry("av7110_ir", S_IFREG | S_IRUGO | S_IWUSR, NULL); | 246 | e = create_proc_entry("av7110_ir", S_IFREG | S_IRUGO | S_IWUSR, NULL); |
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c index 2235ff8b8a1d..89ab4b59155c 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/dvb/ttpci/budget-av.c | |||
@@ -360,7 +360,7 @@ static int ciintf_init(struct budget_av *budget_av) | |||
360 | saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO); | 360 | saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO); |
361 | 361 | ||
362 | /* Enable DEBI pins */ | 362 | /* Enable DEBI pins */ |
363 | saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800); | 363 | saa7146_write(saa, MC1, MASK_27 | MASK_11); |
364 | 364 | ||
365 | /* register CI interface */ | 365 | /* register CI interface */ |
366 | budget_av->ca.owner = THIS_MODULE; | 366 | budget_av->ca.owner = THIS_MODULE; |
@@ -386,7 +386,7 @@ static int ciintf_init(struct budget_av *budget_av) | |||
386 | return 0; | 386 | return 0; |
387 | 387 | ||
388 | error: | 388 | error: |
389 | saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16)); | 389 | saa7146_write(saa, MC1, MASK_27); |
390 | return result; | 390 | return result; |
391 | } | 391 | } |
392 | 392 | ||
@@ -403,7 +403,7 @@ static void ciintf_deinit(struct budget_av *budget_av) | |||
403 | dvb_ca_en50221_release(&budget_av->ca); | 403 | dvb_ca_en50221_release(&budget_av->ca); |
404 | 404 | ||
405 | /* disable DEBI pins */ | 405 | /* disable DEBI pins */ |
406 | saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16)); | 406 | saa7146_write(saa, MC1, MASK_27); |
407 | } | 407 | } |
408 | 408 | ||
409 | 409 | ||
@@ -655,6 +655,10 @@ static struct tda10021_config philips_cu1216_config = { | |||
655 | .demod_address = 0x0c, | 655 | .demod_address = 0x0c, |
656 | }; | 656 | }; |
657 | 657 | ||
658 | static struct tda10021_config philips_cu1216_config_altaddress = { | ||
659 | .demod_address = 0x0d, | ||
660 | }; | ||
661 | |||
658 | 662 | ||
659 | 663 | ||
660 | 664 | ||
@@ -831,7 +835,7 @@ static int philips_sd1878_tda8261_tuner_set_params(struct dvb_frontend *fe, | |||
831 | return -EINVAL; | 835 | return -EINVAL; |
832 | 836 | ||
833 | rc=dvb_pll_configure(&dvb_pll_philips_sd1878_tda8261, buf, | 837 | rc=dvb_pll_configure(&dvb_pll_philips_sd1878_tda8261, buf, |
834 | params->frequency, 0); | 838 | params->frequency, 0); |
835 | if(rc < 0) return rc; | 839 | if(rc < 0) return rc; |
836 | 840 | ||
837 | if (fe->ops.i2c_gate_ctrl) | 841 | if (fe->ops.i2c_gate_ctrl) |
@@ -914,6 +918,7 @@ static u8 read_pwm(struct budget_av *budget_av) | |||
914 | #define SUBID_DVBS_TV_STAR_CI 0x0016 | 918 | #define SUBID_DVBS_TV_STAR_CI 0x0016 |
915 | #define SUBID_DVBS_EASYWATCH_1 0x001a | 919 | #define SUBID_DVBS_EASYWATCH_1 0x001a |
916 | #define SUBID_DVBS_EASYWATCH 0x001e | 920 | #define SUBID_DVBS_EASYWATCH 0x001e |
921 | #define SUBID_DVBC_EASYWATCH 0x002a | ||
917 | #define SUBID_DVBC_KNC1 0x0020 | 922 | #define SUBID_DVBC_KNC1 0x0020 |
918 | #define SUBID_DVBC_KNC1_PLUS 0x0021 | 923 | #define SUBID_DVBC_KNC1_PLUS 0x0021 |
919 | #define SUBID_DVBC_CINERGY1200 0x1156 | 924 | #define SUBID_DVBC_CINERGY1200 0x1156 |
@@ -947,11 +952,15 @@ static void frontend_init(struct budget_av *budget_av) | |||
947 | /* Enable / PowerON Frontend */ | 952 | /* Enable / PowerON Frontend */ |
948 | saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO); | 953 | saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO); |
949 | 954 | ||
955 | /* Wait for PowerON */ | ||
956 | msleep(100); | ||
957 | |||
950 | /* additional setup necessary for the PLUS cards */ | 958 | /* additional setup necessary for the PLUS cards */ |
951 | switch (saa->pci->subsystem_device) { | 959 | switch (saa->pci->subsystem_device) { |
952 | case SUBID_DVBS_KNC1_PLUS: | 960 | case SUBID_DVBS_KNC1_PLUS: |
953 | case SUBID_DVBC_KNC1_PLUS: | 961 | case SUBID_DVBC_KNC1_PLUS: |
954 | case SUBID_DVBT_KNC1_PLUS: | 962 | case SUBID_DVBT_KNC1_PLUS: |
963 | case SUBID_DVBC_EASYWATCH: | ||
955 | saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTHI); | 964 | saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTHI); |
956 | break; | 965 | break; |
957 | } | 966 | } |
@@ -1006,10 +1015,15 @@ static void frontend_init(struct budget_av *budget_av) | |||
1006 | case SUBID_DVBC_KNC1: | 1015 | case SUBID_DVBC_KNC1: |
1007 | case SUBID_DVBC_KNC1_PLUS: | 1016 | case SUBID_DVBC_KNC1_PLUS: |
1008 | case SUBID_DVBC_CINERGY1200: | 1017 | case SUBID_DVBC_CINERGY1200: |
1018 | case SUBID_DVBC_EASYWATCH: | ||
1009 | budget_av->reinitialise_demod = 1; | 1019 | budget_av->reinitialise_demod = 1; |
1010 | fe = dvb_attach(tda10021_attach, &philips_cu1216_config, | 1020 | fe = dvb_attach(tda10021_attach, &philips_cu1216_config, |
1011 | &budget_av->budget.i2c_adap, | 1021 | &budget_av->budget.i2c_adap, |
1012 | read_pwm(budget_av)); | 1022 | read_pwm(budget_av)); |
1023 | if (fe == NULL) | ||
1024 | fe = dvb_attach(tda10021_attach, &philips_cu1216_config_altaddress, | ||
1025 | &budget_av->budget.i2c_adap, | ||
1026 | read_pwm(budget_av)); | ||
1013 | if (fe) { | 1027 | if (fe) { |
1014 | budget_av->tda10021_poclkp = 1; | 1028 | budget_av->tda10021_poclkp = 1; |
1015 | budget_av->tda10021_set_frontend = fe->ops.set_frontend; | 1029 | budget_av->tda10021_set_frontend = fe->ops.set_frontend; |
@@ -1242,6 +1256,7 @@ MAKE_BUDGET_INFO(knc1t, "KNC1 DVB-T", BUDGET_KNC1T); | |||
1242 | MAKE_BUDGET_INFO(kncxs, "KNC TV STAR DVB-S", BUDGET_TVSTAR); | 1256 | MAKE_BUDGET_INFO(kncxs, "KNC TV STAR DVB-S", BUDGET_TVSTAR); |
1243 | MAKE_BUDGET_INFO(satewpls, "Satelco EasyWatch DVB-S light", BUDGET_TVSTAR); | 1257 | MAKE_BUDGET_INFO(satewpls, "Satelco EasyWatch DVB-S light", BUDGET_TVSTAR); |
1244 | MAKE_BUDGET_INFO(satewpls1, "Satelco EasyWatch DVB-S light", BUDGET_KNC1S); | 1258 | MAKE_BUDGET_INFO(satewpls1, "Satelco EasyWatch DVB-S light", BUDGET_KNC1S); |
1259 | MAKE_BUDGET_INFO(satewplc, "Satelco EasyWatch DVB-C", BUDGET_KNC1CP); | ||
1245 | MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plus", BUDGET_KNC1SP); | 1260 | MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plus", BUDGET_KNC1SP); |
1246 | MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus", BUDGET_KNC1CP); | 1261 | MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus", BUDGET_KNC1CP); |
1247 | MAKE_BUDGET_INFO(knc1tp, "KNC1 DVB-T Plus", BUDGET_KNC1TP); | 1262 | MAKE_BUDGET_INFO(knc1tp, "KNC1 DVB-T Plus", BUDGET_KNC1TP); |
@@ -1260,6 +1275,7 @@ static struct pci_device_id pci_tbl[] = { | |||
1260 | MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0016), | 1275 | MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0016), |
1261 | MAKE_EXTENSION_PCI(satewpls, 0x1894, 0x001e), | 1276 | MAKE_EXTENSION_PCI(satewpls, 0x1894, 0x001e), |
1262 | MAKE_EXTENSION_PCI(satewpls1, 0x1894, 0x001a), | 1277 | MAKE_EXTENSION_PCI(satewpls1, 0x1894, 0x001a), |
1278 | MAKE_EXTENSION_PCI(satewplc, 0x1894, 0x002a), | ||
1263 | MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020), | 1279 | MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020), |
1264 | MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021), | 1280 | MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021), |
1265 | MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030), | 1281 | MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030), |
@@ -1277,7 +1293,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl); | |||
1277 | 1293 | ||
1278 | static struct saa7146_extension budget_extension = { | 1294 | static struct saa7146_extension budget_extension = { |
1279 | .name = "budget_av", | 1295 | .name = "budget_av", |
1280 | .flags = SAA7146_I2C_SHORT_DELAY, | 1296 | .flags = SAA7146_USE_I2C_IRQ, |
1281 | 1297 | ||
1282 | .pci_tbl = pci_tbl, | 1298 | .pci_tbl = pci_tbl, |
1283 | 1299 | ||
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index cd5ec489af1c..f2066b47baee 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/interrupt.h> | 37 | #include <linux/interrupt.h> |
38 | #include <linux/input.h> | 38 | #include <linux/input.h> |
39 | #include <linux/spinlock.h> | 39 | #include <linux/spinlock.h> |
40 | #include <media/ir-common.h> | ||
40 | 41 | ||
41 | #include "dvb_ca_en50221.h" | 42 | #include "dvb_ca_en50221.h" |
42 | #include "stv0299.h" | 43 | #include "stv0299.h" |
@@ -72,162 +73,218 @@ | |||
72 | #define SLOTSTATUS_READY 8 | 73 | #define SLOTSTATUS_READY 8 |
73 | #define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY) | 74 | #define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY) |
74 | 75 | ||
76 | /* Milliseconds during which key presses are regarded as key repeat and during | ||
77 | * which the debounce logic is active | ||
78 | */ | ||
79 | #define IR_REPEAT_TIMEOUT 350 | ||
80 | |||
81 | /* RC5 device wildcard */ | ||
82 | #define IR_DEVICE_ANY 255 | ||
83 | |||
84 | /* Some remotes sends multiple sequences per keypress (e.g. Zenith sends two), | ||
85 | * this setting allows the superflous sequences to be ignored | ||
86 | */ | ||
87 | static int debounce = 0; | ||
88 | module_param(debounce, int, 0644); | ||
89 | MODULE_PARM_DESC(debounce, "ignore repeated IR sequences (default: 0 = ignore no sequences)"); | ||
90 | |||
91 | static int rc5_device = -1; | ||
92 | module_param(rc5_device, int, 0644); | ||
93 | MODULE_PARM_DESC(rc5_device, "only IR commands to given RC5 device (device = 0 - 31, any device = 255, default: autodetect)"); | ||
94 | |||
95 | static int ir_debug = 0; | ||
96 | module_param(ir_debug, int, 0644); | ||
97 | MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding"); | ||
98 | |||
99 | struct budget_ci_ir { | ||
100 | struct input_dev *dev; | ||
101 | struct tasklet_struct msp430_irq_tasklet; | ||
102 | char name[72]; /* 40 + 32 for (struct saa7146_dev).name */ | ||
103 | char phys[32]; | ||
104 | struct ir_input_state state; | ||
105 | int rc5_device; | ||
106 | }; | ||
107 | |||
75 | struct budget_ci { | 108 | struct budget_ci { |
76 | struct budget budget; | 109 | struct budget budget; |
77 | struct input_dev *input_dev; | ||
78 | struct tasklet_struct msp430_irq_tasklet; | ||
79 | struct tasklet_struct ciintf_irq_tasklet; | 110 | struct tasklet_struct ciintf_irq_tasklet; |
80 | int slot_status; | 111 | int slot_status; |
81 | int ci_irq; | 112 | int ci_irq; |
82 | struct dvb_ca_en50221 ca; | 113 | struct dvb_ca_en50221 ca; |
83 | char ir_dev_name[50]; | 114 | struct budget_ci_ir ir; |
84 | u8 tuner_pll_address; /* used for philips_tdm1316l configs */ | 115 | u8 tuner_pll_address; /* used for philips_tdm1316l configs */ |
85 | }; | 116 | }; |
86 | 117 | ||
87 | /* from reading the following remotes: | 118 | static void msp430_ir_keyup(unsigned long data) |
88 | Zenith Universal 7 / TV Mode 807 / VCR Mode 837 | ||
89 | Hauppauge (from NOVA-CI-s box product) | ||
90 | i've taken a "middle of the road" approach and note the differences | ||
91 | */ | ||
92 | static u16 key_map[64] = { | ||
93 | /* 0x0X */ | ||
94 | KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, | ||
95 | KEY_9, | ||
96 | KEY_ENTER, | ||
97 | KEY_RED, | ||
98 | KEY_POWER, /* RADIO on Hauppauge */ | ||
99 | KEY_MUTE, | ||
100 | 0, | ||
101 | KEY_A, /* TV on Hauppauge */ | ||
102 | /* 0x1X */ | ||
103 | KEY_VOLUMEUP, KEY_VOLUMEDOWN, | ||
104 | 0, 0, | ||
105 | KEY_B, | ||
106 | 0, 0, 0, 0, 0, 0, 0, | ||
107 | KEY_UP, KEY_DOWN, | ||
108 | KEY_OPTION, /* RESERVED on Hauppauge */ | ||
109 | KEY_BREAK, | ||
110 | /* 0x2X */ | ||
111 | KEY_CHANNELUP, KEY_CHANNELDOWN, | ||
112 | KEY_PREVIOUS, /* Prev. Ch on Zenith, SOURCE on Hauppauge */ | ||
113 | 0, KEY_RESTART, KEY_OK, | ||
114 | KEY_CYCLEWINDOWS, /* MINIMIZE on Hauppauge */ | ||
115 | 0, | ||
116 | KEY_ENTER, /* VCR mode on Zenith */ | ||
117 | KEY_PAUSE, | ||
118 | 0, | ||
119 | KEY_RIGHT, KEY_LEFT, | ||
120 | 0, | ||
121 | KEY_MENU, /* FULL SCREEN on Hauppauge */ | ||
122 | 0, | ||
123 | /* 0x3X */ | ||
124 | KEY_SLOW, | ||
125 | KEY_PREVIOUS, /* VCR mode on Zenith */ | ||
126 | KEY_REWIND, | ||
127 | 0, | ||
128 | KEY_FASTFORWARD, | ||
129 | KEY_PLAY, KEY_STOP, | ||
130 | KEY_RECORD, | ||
131 | KEY_TUNER, /* TV/VCR on Zenith */ | ||
132 | 0, | ||
133 | KEY_C, | ||
134 | 0, | ||
135 | KEY_EXIT, | ||
136 | KEY_POWER2, | ||
137 | KEY_TUNER, /* VCR mode on Zenith */ | ||
138 | 0, | ||
139 | }; | ||
140 | |||
141 | static void msp430_ir_debounce(unsigned long data) | ||
142 | { | 119 | { |
143 | struct input_dev *dev = (struct input_dev *) data; | 120 | struct budget_ci_ir *ir = (struct budget_ci_ir *) data; |
144 | 121 | ir_input_nokey(ir->dev, &ir->state); | |
145 | if (dev->rep[0] == 0 || dev->rep[0] == ~0) { | ||
146 | input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0); | ||
147 | return; | ||
148 | } | ||
149 | |||
150 | dev->rep[0] = 0; | ||
151 | dev->timer.expires = jiffies + HZ * 350 / 1000; | ||
152 | add_timer(&dev->timer); | ||
153 | input_event(dev, EV_KEY, key_map[dev->repeat_key], 2); /* REPEAT */ | ||
154 | } | 122 | } |
155 | 123 | ||
156 | static void msp430_ir_interrupt(unsigned long data) | 124 | static void msp430_ir_interrupt(unsigned long data) |
157 | { | 125 | { |
158 | struct budget_ci *budget_ci = (struct budget_ci *) data; | 126 | struct budget_ci *budget_ci = (struct budget_ci *) data; |
159 | struct input_dev *dev = budget_ci->input_dev; | 127 | struct input_dev *dev = budget_ci->ir.dev; |
160 | unsigned int code = | 128 | static int bounces = 0; |
161 | ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8; | 129 | int device; |
130 | int toggle; | ||
131 | static int prev_toggle = -1; | ||
132 | static u32 ir_key; | ||
133 | u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8; | ||
134 | |||
135 | /* | ||
136 | * The msp430 chip can generate two different bytes, command and device | ||
137 | * | ||
138 | * type1: X1CCCCCC, C = command bits (0 - 63) | ||
139 | * type2: X0TDDDDD, D = device bits (0 - 31), T = RC5 toggle bit | ||
140 | * | ||
141 | * More than one command byte may be generated before the device byte | ||
142 | * Only when we have both, a correct keypress is generated | ||
143 | */ | ||
144 | |||
145 | /* Is this a RC5 command byte? */ | ||
146 | if (command & 0x40) { | ||
147 | if (ir_debug) | ||
148 | printk("budget_ci: received command byte 0x%02x\n", command); | ||
149 | ir_key = command & 0x3f; | ||
150 | return; | ||
151 | } | ||
162 | 152 | ||
163 | if (code & 0x40) { | 153 | /* It's a RC5 device byte */ |
164 | code &= 0x3f; | 154 | if (ir_debug) |
155 | printk("budget_ci: received device byte 0x%02x\n", command); | ||
156 | device = command & 0x1f; | ||
157 | toggle = command & 0x20; | ||
165 | 158 | ||
166 | if (timer_pending(&dev->timer)) { | 159 | if (budget_ci->ir.rc5_device != IR_DEVICE_ANY && budget_ci->ir.rc5_device != device) |
167 | if (code == dev->repeat_key) { | 160 | return; |
168 | ++dev->rep[0]; | ||
169 | return; | ||
170 | } | ||
171 | del_timer(&dev->timer); | ||
172 | input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0); | ||
173 | } | ||
174 | 161 | ||
175 | if (!key_map[code]) { | 162 | /* Ignore repeated key sequences if requested */ |
176 | printk("DVB (%s): no key for %02x!\n", __FUNCTION__, code); | 163 | if (toggle == prev_toggle && ir_key == dev->repeat_key && |
177 | return; | 164 | bounces > 0 && timer_pending(&dev->timer)) { |
178 | } | 165 | if (ir_debug) |
166 | printk("budget_ci: debounce logic ignored IR command\n"); | ||
167 | bounces--; | ||
168 | return; | ||
169 | } | ||
170 | prev_toggle = toggle; | ||
179 | 171 | ||
180 | /* initialize debounce and repeat */ | 172 | /* Are we still waiting for a keyup event? */ |
181 | dev->repeat_key = code; | 173 | if (del_timer(&dev->timer)) |
182 | /* Zenith remote _always_ sends 2 sequences */ | 174 | ir_input_nokey(dev, &budget_ci->ir.state); |
183 | dev->rep[0] = ~0; | 175 | |
184 | /* 350 milliseconds */ | 176 | /* Generate keypress */ |
185 | dev->timer.expires = jiffies + HZ * 350 / 1000; | 177 | if (ir_debug) |
186 | /* MAKE */ | 178 | printk("budget_ci: generating keypress 0x%02x\n", ir_key); |
187 | input_event(dev, EV_KEY, key_map[code], !0); | 179 | ir_input_keydown(dev, &budget_ci->ir.state, ir_key, (ir_key & (command << 8))); |
188 | add_timer(&dev->timer); | 180 | |
181 | /* Do we want to delay the keyup event? */ | ||
182 | if (debounce) { | ||
183 | bounces = debounce; | ||
184 | mod_timer(&dev->timer, jiffies + msecs_to_jiffies(IR_REPEAT_TIMEOUT)); | ||
185 | } else { | ||
186 | ir_input_nokey(dev, &budget_ci->ir.state); | ||
189 | } | 187 | } |
190 | } | 188 | } |
191 | 189 | ||
192 | static int msp430_ir_init(struct budget_ci *budget_ci) | 190 | static int msp430_ir_init(struct budget_ci *budget_ci) |
193 | { | 191 | { |
194 | struct saa7146_dev *saa = budget_ci->budget.dev; | 192 | struct saa7146_dev *saa = budget_ci->budget.dev; |
195 | struct input_dev *input_dev; | 193 | struct input_dev *input_dev = budget_ci->ir.dev; |
196 | int i; | 194 | int error; |
195 | |||
196 | budget_ci->ir.dev = input_dev = input_allocate_device(); | ||
197 | if (!input_dev) { | ||
198 | printk(KERN_ERR "budget_ci: IR interface initialisation failed\n"); | ||
199 | error = -ENOMEM; | ||
200 | goto out1; | ||
201 | } | ||
202 | |||
203 | snprintf(budget_ci->ir.name, sizeof(budget_ci->ir.name), | ||
204 | "Budget-CI dvb ir receiver %s", saa->name); | ||
205 | snprintf(budget_ci->ir.phys, sizeof(budget_ci->ir.phys), | ||
206 | "pci-%s/ir0", pci_name(saa->pci)); | ||
197 | 207 | ||
198 | budget_ci->input_dev = input_dev = input_allocate_device(); | 208 | input_dev->name = budget_ci->ir.name; |
199 | if (!input_dev) | ||
200 | return -ENOMEM; | ||
201 | 209 | ||
202 | sprintf(budget_ci->ir_dev_name, "Budget-CI dvb ir receiver %s", saa->name); | 210 | input_dev->phys = budget_ci->ir.phys; |
211 | input_dev->id.bustype = BUS_PCI; | ||
212 | input_dev->id.version = 1; | ||
213 | if (saa->pci->subsystem_vendor) { | ||
214 | input_dev->id.vendor = saa->pci->subsystem_vendor; | ||
215 | input_dev->id.product = saa->pci->subsystem_device; | ||
216 | } else { | ||
217 | input_dev->id.vendor = saa->pci->vendor; | ||
218 | input_dev->id.product = saa->pci->device; | ||
219 | } | ||
220 | input_dev->cdev.dev = &saa->pci->dev; | ||
203 | 221 | ||
204 | input_dev->name = budget_ci->ir_dev_name; | 222 | /* Select keymap and address */ |
223 | switch (budget_ci->budget.dev->pci->subsystem_device) { | ||
224 | case 0x100c: | ||
225 | case 0x100f: | ||
226 | case 0x1010: | ||
227 | case 0x1011: | ||
228 | case 0x1012: | ||
229 | case 0x1017: | ||
230 | /* The hauppauge keymap is a superset of these remotes */ | ||
231 | ir_input_init(input_dev, &budget_ci->ir.state, | ||
232 | IR_TYPE_RC5, ir_codes_hauppauge_new); | ||
233 | |||
234 | if (rc5_device < 0) | ||
235 | budget_ci->ir.rc5_device = 0x1f; | ||
236 | else | ||
237 | budget_ci->ir.rc5_device = rc5_device; | ||
238 | break; | ||
239 | default: | ||
240 | /* unknown remote */ | ||
241 | ir_input_init(input_dev, &budget_ci->ir.state, | ||
242 | IR_TYPE_RC5, ir_codes_budget_ci_old); | ||
243 | |||
244 | if (rc5_device < 0) | ||
245 | budget_ci->ir.rc5_device = IR_DEVICE_ANY; | ||
246 | else | ||
247 | budget_ci->ir.rc5_device = rc5_device; | ||
248 | break; | ||
249 | } | ||
205 | 250 | ||
206 | set_bit(EV_KEY, input_dev->evbit); | 251 | /* initialise the key-up debounce timeout handler */ |
207 | for (i = 0; i < ARRAY_SIZE(key_map); i++) | 252 | input_dev->timer.function = msp430_ir_keyup; |
208 | if (key_map[i]) | 253 | input_dev->timer.data = (unsigned long) &budget_ci->ir; |
209 | set_bit(key_map[i], input_dev->keybit); | ||
210 | 254 | ||
211 | input_register_device(budget_ci->input_dev); | 255 | error = input_register_device(input_dev); |
256 | if (error) { | ||
257 | printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error); | ||
258 | goto out2; | ||
259 | } | ||
212 | 260 | ||
213 | input_dev->timer.function = msp430_ir_debounce; | 261 | tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt, |
262 | (unsigned long) budget_ci); | ||
214 | 263 | ||
215 | saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_06); | 264 | SAA7146_IER_ENABLE(saa, MASK_06); |
216 | saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI); | 265 | saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI); |
217 | 266 | ||
218 | return 0; | 267 | return 0; |
268 | |||
269 | out2: | ||
270 | input_free_device(input_dev); | ||
271 | out1: | ||
272 | return error; | ||
219 | } | 273 | } |
220 | 274 | ||
221 | static void msp430_ir_deinit(struct budget_ci *budget_ci) | 275 | static void msp430_ir_deinit(struct budget_ci *budget_ci) |
222 | { | 276 | { |
223 | struct saa7146_dev *saa = budget_ci->budget.dev; | 277 | struct saa7146_dev *saa = budget_ci->budget.dev; |
224 | struct input_dev *dev = budget_ci->input_dev; | 278 | struct input_dev *dev = budget_ci->ir.dev; |
225 | 279 | ||
226 | saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_06); | 280 | SAA7146_IER_DISABLE(saa, MASK_06); |
227 | saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT); | 281 | saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT); |
282 | tasklet_kill(&budget_ci->ir.msp430_irq_tasklet); | ||
228 | 283 | ||
229 | if (del_timer(&dev->timer)) | 284 | if (del_timer(&dev->timer)) { |
230 | input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0); | 285 | ir_input_nokey(dev, &budget_ci->ir.state); |
286 | input_sync(dev); | ||
287 | } | ||
231 | 288 | ||
232 | input_unregister_device(dev); | 289 | input_unregister_device(dev); |
233 | } | 290 | } |
@@ -428,7 +485,7 @@ static int ciintf_init(struct budget_ci *budget_ci) | |||
428 | memset(&budget_ci->ca, 0, sizeof(struct dvb_ca_en50221)); | 485 | memset(&budget_ci->ca, 0, sizeof(struct dvb_ca_en50221)); |
429 | 486 | ||
430 | // enable DEBI pins | 487 | // enable DEBI pins |
431 | saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800); | 488 | saa7146_write(saa, MC1, MASK_27 | MASK_11); |
432 | 489 | ||
433 | // test if it is there | 490 | // test if it is there |
434 | ci_version = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0); | 491 | ci_version = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0); |
@@ -480,7 +537,7 @@ static int ciintf_init(struct budget_ci *budget_ci) | |||
480 | } else { | 537 | } else { |
481 | saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI); | 538 | saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI); |
482 | } | 539 | } |
483 | saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_03); | 540 | SAA7146_IER_ENABLE(saa, MASK_03); |
484 | } | 541 | } |
485 | 542 | ||
486 | // enable interface | 543 | // enable interface |
@@ -502,7 +559,7 @@ static int ciintf_init(struct budget_ci *budget_ci) | |||
502 | return 0; | 559 | return 0; |
503 | 560 | ||
504 | error: | 561 | error: |
505 | saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16)); | 562 | saa7146_write(saa, MC1, MASK_27); |
506 | return result; | 563 | return result; |
507 | } | 564 | } |
508 | 565 | ||
@@ -512,7 +569,7 @@ static void ciintf_deinit(struct budget_ci *budget_ci) | |||
512 | 569 | ||
513 | // disable CI interrupts | 570 | // disable CI interrupts |
514 | if (budget_ci->ci_irq) { | 571 | if (budget_ci->ci_irq) { |
515 | saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_03); | 572 | SAA7146_IER_DISABLE(saa, MASK_03); |
516 | saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT); | 573 | saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT); |
517 | tasklet_kill(&budget_ci->ciintf_irq_tasklet); | 574 | tasklet_kill(&budget_ci->ciintf_irq_tasklet); |
518 | } | 575 | } |
@@ -530,7 +587,7 @@ static void ciintf_deinit(struct budget_ci *budget_ci) | |||
530 | dvb_ca_en50221_release(&budget_ci->ca); | 587 | dvb_ca_en50221_release(&budget_ci->ca); |
531 | 588 | ||
532 | // disable DEBI pins | 589 | // disable DEBI pins |
533 | saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16)); | 590 | saa7146_write(saa, MC1, MASK_27); |
534 | } | 591 | } |
535 | 592 | ||
536 | static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr) | 593 | static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr) |
@@ -540,7 +597,7 @@ static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr) | |||
540 | dprintk(8, "dev: %p, budget_ci: %p\n", dev, budget_ci); | 597 | dprintk(8, "dev: %p, budget_ci: %p\n", dev, budget_ci); |
541 | 598 | ||
542 | if (*isr & MASK_06) | 599 | if (*isr & MASK_06) |
543 | tasklet_schedule(&budget_ci->msp430_irq_tasklet); | 600 | tasklet_schedule(&budget_ci->ir.msp430_irq_tasklet); |
544 | 601 | ||
545 | if (*isr & MASK_10) | 602 | if (*isr & MASK_10) |
546 | ttpci_budget_irq10_handler(dev, isr); | 603 | ttpci_budget_irq10_handler(dev, isr); |
@@ -835,7 +892,7 @@ static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struc | |||
835 | band = 1; | 892 | band = 1; |
836 | } else if (tuner_frequency < 200000000) { | 893 | } else if (tuner_frequency < 200000000) { |
837 | cp = 6; | 894 | cp = 6; |
838 | band = 1; | 895 | band = 2; |
839 | } else if (tuner_frequency < 290000000) { | 896 | } else if (tuner_frequency < 290000000) { |
840 | cp = 3; | 897 | cp = 3; |
841 | band = 2; | 898 | band = 2; |
@@ -1083,24 +1140,23 @@ static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio | |||
1083 | struct budget_ci *budget_ci; | 1140 | struct budget_ci *budget_ci; |
1084 | int err; | 1141 | int err; |
1085 | 1142 | ||
1086 | if (!(budget_ci = kmalloc(sizeof(struct budget_ci), GFP_KERNEL))) | 1143 | budget_ci = kzalloc(sizeof(struct budget_ci), GFP_KERNEL); |
1087 | return -ENOMEM; | 1144 | if (!budget_ci) { |
1145 | err = -ENOMEM; | ||
1146 | goto out1; | ||
1147 | } | ||
1088 | 1148 | ||
1089 | dprintk(2, "budget_ci: %p\n", budget_ci); | 1149 | dprintk(2, "budget_ci: %p\n", budget_ci); |
1090 | 1150 | ||
1091 | budget_ci->budget.ci_present = 0; | ||
1092 | |||
1093 | dev->ext_priv = budget_ci; | 1151 | dev->ext_priv = budget_ci; |
1094 | 1152 | ||
1095 | if ((err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE))) { | 1153 | err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE); |
1096 | kfree(budget_ci); | 1154 | if (err) |
1097 | return err; | 1155 | goto out2; |
1098 | } | ||
1099 | |||
1100 | tasklet_init(&budget_ci->msp430_irq_tasklet, msp430_ir_interrupt, | ||
1101 | (unsigned long) budget_ci); | ||
1102 | 1156 | ||
1103 | msp430_ir_init(budget_ci); | 1157 | err = msp430_ir_init(budget_ci); |
1158 | if (err) | ||
1159 | goto out3; | ||
1104 | 1160 | ||
1105 | ciintf_init(budget_ci); | 1161 | ciintf_init(budget_ci); |
1106 | 1162 | ||
@@ -1110,6 +1166,13 @@ static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio | |||
1110 | ttpci_budget_init_hooks(&budget_ci->budget); | 1166 | ttpci_budget_init_hooks(&budget_ci->budget); |
1111 | 1167 | ||
1112 | return 0; | 1168 | return 0; |
1169 | |||
1170 | out3: | ||
1171 | ttpci_budget_deinit(&budget_ci->budget); | ||
1172 | out2: | ||
1173 | kfree(budget_ci); | ||
1174 | out1: | ||
1175 | return err; | ||
1113 | } | 1176 | } |
1114 | 1177 | ||
1115 | static int budget_ci_detach(struct saa7146_dev *dev) | 1178 | static int budget_ci_detach(struct saa7146_dev *dev) |
@@ -1120,16 +1183,13 @@ static int budget_ci_detach(struct saa7146_dev *dev) | |||
1120 | 1183 | ||
1121 | if (budget_ci->budget.ci_present) | 1184 | if (budget_ci->budget.ci_present) |
1122 | ciintf_deinit(budget_ci); | 1185 | ciintf_deinit(budget_ci); |
1186 | msp430_ir_deinit(budget_ci); | ||
1123 | if (budget_ci->budget.dvb_frontend) { | 1187 | if (budget_ci->budget.dvb_frontend) { |
1124 | dvb_unregister_frontend(budget_ci->budget.dvb_frontend); | 1188 | dvb_unregister_frontend(budget_ci->budget.dvb_frontend); |
1125 | dvb_frontend_detach(budget_ci->budget.dvb_frontend); | 1189 | dvb_frontend_detach(budget_ci->budget.dvb_frontend); |
1126 | } | 1190 | } |
1127 | err = ttpci_budget_deinit(&budget_ci->budget); | 1191 | err = ttpci_budget_deinit(&budget_ci->budget); |
1128 | 1192 | ||
1129 | tasklet_kill(&budget_ci->msp430_irq_tasklet); | ||
1130 | |||
1131 | msp430_ir_deinit(budget_ci); | ||
1132 | |||
1133 | // disable frontend and CI interface | 1193 | // disable frontend and CI interface |
1134 | saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT); | 1194 | saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT); |
1135 | 1195 | ||
@@ -1162,7 +1222,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl); | |||
1162 | 1222 | ||
1163 | static struct saa7146_extension budget_extension = { | 1223 | static struct saa7146_extension budget_extension = { |
1164 | .name = "budget_ci dvb", | 1224 | .name = "budget_ci dvb", |
1165 | .flags = SAA7146_I2C_SHORT_DELAY, | 1225 | .flags = SAA7146_USE_I2C_IRQ, |
1166 | 1226 | ||
1167 | .module = THIS_MODULE, | 1227 | .module = THIS_MODULE, |
1168 | .pci_tbl = &pci_tbl[0], | 1228 | .pci_tbl = &pci_tbl[0], |
diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index 56f1c80defc6..9268a82bada6 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c | |||
@@ -555,7 +555,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl); | |||
555 | 555 | ||
556 | static struct saa7146_extension budget_extension = { | 556 | static struct saa7146_extension budget_extension = { |
557 | .name = "budget dvb", | 557 | .name = "budget dvb", |
558 | .flags = SAA7146_I2C_SHORT_DELAY, | 558 | .flags = SAA7146_USE_I2C_IRQ, |
559 | 559 | ||
560 | .module = THIS_MODULE, | 560 | .module = THIS_MODULE, |
561 | .pci_tbl = pci_tbl, | 561 | .pci_tbl = pci_tbl, |
diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c index 10b121ada833..bd6e7baae2ec 100644 --- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c | |||
@@ -238,6 +238,7 @@ static void ttusb_dec_handle_irq( struct urb *urb) | |||
238 | * for now lets report each signal as a key down and up*/ | 238 | * for now lets report each signal as a key down and up*/ |
239 | dprintk("%s:rc signal:%d\n", __FUNCTION__, buffer[4]); | 239 | dprintk("%s:rc signal:%d\n", __FUNCTION__, buffer[4]); |
240 | input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 1); | 240 | input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 1); |
241 | input_sync(dec->rc_input_dev); | ||
241 | input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 0); | 242 | input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 0); |
242 | input_sync(dec->rc_input_dev); | 243 | input_sync(dec->rc_input_dev); |
243 | } | 244 | } |
@@ -1187,11 +1188,12 @@ static int ttusb_init_rc( struct ttusb_dec *dec) | |||
1187 | struct input_dev *input_dev; | 1188 | struct input_dev *input_dev; |
1188 | u8 b[] = { 0x00, 0x01 }; | 1189 | u8 b[] = { 0x00, 0x01 }; |
1189 | int i; | 1190 | int i; |
1191 | int err; | ||
1190 | 1192 | ||
1191 | usb_make_path(dec->udev, dec->rc_phys, sizeof(dec->rc_phys)); | 1193 | usb_make_path(dec->udev, dec->rc_phys, sizeof(dec->rc_phys)); |
1192 | strlcpy(dec->rc_phys, "/input0", sizeof(dec->rc_phys)); | 1194 | strlcpy(dec->rc_phys, "/input0", sizeof(dec->rc_phys)); |
1193 | 1195 | ||
1194 | dec->rc_input_dev = input_dev = input_allocate_device(); | 1196 | input_dev = input_allocate_device(); |
1195 | if (!input_dev) | 1197 | if (!input_dev) |
1196 | return -ENOMEM; | 1198 | return -ENOMEM; |
1197 | 1199 | ||
@@ -1205,8 +1207,13 @@ static int ttusb_init_rc( struct ttusb_dec *dec) | |||
1205 | for (i = 0; i < ARRAY_SIZE(rc_keys); i++) | 1207 | for (i = 0; i < ARRAY_SIZE(rc_keys); i++) |
1206 | set_bit(rc_keys[i], input_dev->keybit); | 1208 | set_bit(rc_keys[i], input_dev->keybit); |
1207 | 1209 | ||
1208 | input_register_device(input_dev); | 1210 | err = input_register_device(input_dev); |
1211 | if (err) { | ||
1212 | input_free_device(input_dev); | ||
1213 | return err; | ||
1214 | } | ||
1209 | 1215 | ||
1216 | dec->rc_input_dev = input_dev; | ||
1210 | if (usb_submit_urb(dec->irq_urb, GFP_KERNEL)) | 1217 | if (usb_submit_urb(dec->irq_urb, GFP_KERNEL)) |
1211 | printk("%s: usb_submit_urb failed\n",__FUNCTION__); | 1218 | printk("%s: usb_submit_urb failed\n",__FUNCTION__); |
1212 | /* enable irq pipe */ | 1219 | /* enable irq pipe */ |
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index b8fde5cf4735..29a11c1db1b7 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig | |||
@@ -184,6 +184,14 @@ config VIDEO_KS0127 | |||
184 | To compile this driver as a module, choose M here: the | 184 | To compile this driver as a module, choose M here: the |
185 | module will be called ks0127. | 185 | module will be called ks0127. |
186 | 186 | ||
187 | config VIDEO_OV7670 | ||
188 | tristate "OmniVision OV7670 sensor support" | ||
189 | depends on I2C && VIDEO_V4L2 | ||
190 | ---help--- | ||
191 | This is a Video4Linux2 sensor-level driver for the OmniVision | ||
192 | OV7670 VGA camera. It currently only works with the M88ALP01 | ||
193 | controller. | ||
194 | |||
187 | config VIDEO_SAA7110 | 195 | config VIDEO_SAA7110 |
188 | tristate "Philips SAA7110 video decoder" | 196 | tristate "Philips SAA7110 video decoder" |
189 | depends on VIDEO_V4L1 && I2C | 197 | depends on VIDEO_V4L1 && I2C |
@@ -567,18 +575,6 @@ config VIDEO_ZORAN_AVS6EYES | |||
567 | help | 575 | help |
568 | Support for the AverMedia 6 Eyes video surveillance card. | 576 | Support for the AverMedia 6 Eyes video surveillance card. |
569 | 577 | ||
570 | config VIDEO_ZR36120 | ||
571 | tristate "Zoran ZR36120/36125 Video For Linux" | ||
572 | depends on PCI && I2C && VIDEO_V4L1 && BROKEN | ||
573 | help | ||
574 | Support for ZR36120/ZR36125 based frame grabber/overlay boards. | ||
575 | This includes the Victor II, WaveWatcher, Video Wonder, Maxi-TV, | ||
576 | and Buster boards. Please read the material in | ||
577 | <file:Documentation/video4linux/zr36120.txt> for more information. | ||
578 | |||
579 | To compile this driver as a module, choose M here: the | ||
580 | module will be called zr36120. | ||
581 | |||
582 | config VIDEO_MEYE | 578 | config VIDEO_MEYE |
583 | tristate "Sony Vaio Picturebook Motion Eye Video For Linux" | 579 | tristate "Sony Vaio Picturebook Motion Eye Video For Linux" |
584 | depends on PCI && SONYPI && VIDEO_V4L1 | 580 | depends on PCI && SONYPI && VIDEO_V4L1 |
@@ -670,6 +666,15 @@ config VIDEO_M32R_AR_M64278 | |||
670 | To compile this driver as a module, choose M here: the | 666 | To compile this driver as a module, choose M here: the |
671 | module will be called arv. | 667 | module will be called arv. |
672 | 668 | ||
669 | config VIDEO_CAFE_CCIC | ||
670 | tristate "Marvell 88ALP01 (Cafe) CMOS Camera Controller support" | ||
671 | depends on I2C && VIDEO_V4L2 | ||
672 | select VIDEO_OV7670 | ||
673 | ---help--- | ||
674 | This is a video4linux2 driver for the Marvell 88ALP01 integrated | ||
675 | CMOS camera controller. This is the controller found on first- | ||
676 | generation OLPC systems. | ||
677 | |||
673 | # | 678 | # |
674 | # USB Multimedia device configuration | 679 | # USB Multimedia device configuration |
675 | # | 680 | # |
@@ -681,6 +686,8 @@ source "drivers/media/video/pvrusb2/Kconfig" | |||
681 | 686 | ||
682 | source "drivers/media/video/em28xx/Kconfig" | 687 | source "drivers/media/video/em28xx/Kconfig" |
683 | 688 | ||
689 | source "drivers/media/video/usbvision/Kconfig" | ||
690 | |||
684 | source "drivers/media/video/usbvideo/Kconfig" | 691 | source "drivers/media/video/usbvideo/Kconfig" |
685 | 692 | ||
686 | source "drivers/media/video/et61x251/Kconfig" | 693 | source "drivers/media/video/et61x251/Kconfig" |
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index af57abce8a6e..9b1f3f06bb7c 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile | |||
@@ -2,7 +2,6 @@ | |||
2 | # Makefile for the video capture/playback device drivers. | 2 | # Makefile for the video capture/playback device drivers. |
3 | # | 3 | # |
4 | 4 | ||
5 | zoran-objs := zr36120.o zr36120_i2c.o zr36120_mem.o | ||
6 | zr36067-objs := zoran_procfs.o zoran_device.o \ | 5 | zr36067-objs := zoran_procfs.o zoran_device.o \ |
7 | zoran_driver.o zoran_card.o | 6 | zoran_driver.o zoran_card.o |
8 | tuner-objs := tuner-core.o tuner-types.o tuner-simple.o \ | 7 | tuner-objs := tuner-core.o tuner-types.o tuner-simple.o \ |
@@ -23,7 +22,6 @@ obj-$(CONFIG_VIDEO_TDA7432) += tda7432.o | |||
23 | obj-$(CONFIG_VIDEO_TDA9875) += tda9875.o | 22 | obj-$(CONFIG_VIDEO_TDA9875) += tda9875.o |
24 | obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o | 23 | obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o |
25 | 24 | ||
26 | obj-$(CONFIG_VIDEO_ZR36120) += zoran.o | ||
27 | obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o | 25 | obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o |
28 | obj-$(CONFIG_VIDEO_SAA5246A) += saa5246a.o | 26 | obj-$(CONFIG_VIDEO_SAA5246A) += saa5246a.o |
29 | obj-$(CONFIG_VIDEO_SAA5249) += saa5249.o | 27 | obj-$(CONFIG_VIDEO_SAA5249) += saa5249.o |
@@ -64,6 +62,7 @@ obj-$(CONFIG_VIDEO_MEYE) += meye.o | |||
64 | obj-$(CONFIG_VIDEO_SAA7134) += ir-kbd-i2c.o saa7134/ | 62 | obj-$(CONFIG_VIDEO_SAA7134) += ir-kbd-i2c.o saa7134/ |
65 | obj-$(CONFIG_VIDEO_CX88) += cx88/ | 63 | obj-$(CONFIG_VIDEO_CX88) += cx88/ |
66 | obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ | 64 | obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ |
65 | obj-$(CONFIG_VIDEO_USBVISION) += usbvision/ | ||
67 | obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o | 66 | obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o |
68 | obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/ | 67 | obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/ |
69 | obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o | 68 | obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o |
@@ -92,6 +91,9 @@ obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o | |||
92 | obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o | 91 | obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o |
93 | obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o | 92 | obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o |
94 | 93 | ||
94 | obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o | ||
95 | obj-$(CONFIG_VIDEO_OV7670) += ov7670.o | ||
96 | |||
95 | obj-$(CONFIG_USB_DABUSB) += dabusb.o | 97 | obj-$(CONFIG_USB_DABUSB) += dabusb.o |
96 | obj-$(CONFIG_USB_OV511) += ov511.o | 98 | obj-$(CONFIG_USB_OV511) += ov511.o |
97 | obj-$(CONFIG_USB_SE401) += se401.o | 99 | obj-$(CONFIG_USB_SE401) += se401.o |
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 6e1ddad9f0c1..3c8e4742dccc 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c | |||
@@ -1793,7 +1793,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) | |||
1793 | memset(i,0,sizeof(*i)); | 1793 | memset(i,0,sizeof(*i)); |
1794 | i->index = n; | 1794 | i->index = n; |
1795 | i->type = V4L2_INPUT_TYPE_CAMERA; | 1795 | i->type = V4L2_INPUT_TYPE_CAMERA; |
1796 | i->audioset = 0; | 1796 | i->audioset = 1; |
1797 | if (i->index == bttv_tvcards[btv->c.type].tuner) { | 1797 | if (i->index == bttv_tvcards[btv->c.type].tuner) { |
1798 | sprintf(i->name, "Television"); | 1798 | sprintf(i->name, "Television"); |
1799 | i->type = V4L2_INPUT_TYPE_TUNER; | 1799 | i->type = V4L2_INPUT_TYPE_TUNER; |
diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index 933d6db09acb..cbc012f71f52 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c | |||
@@ -259,24 +259,59 @@ static void bttv_rc5_timer_keyup(unsigned long data) | |||
259 | 259 | ||
260 | /* ---------------------------------------------------------------------- */ | 260 | /* ---------------------------------------------------------------------- */ |
261 | 261 | ||
262 | static void bttv_ir_start(struct bttv *btv, struct bttv_ir *ir) | ||
263 | { | ||
264 | if (ir->polling) { | ||
265 | init_timer(&ir->timer); | ||
266 | ir->timer.function = bttv_input_timer; | ||
267 | ir->timer.data = (unsigned long)btv; | ||
268 | ir->timer.expires = jiffies + HZ; | ||
269 | add_timer(&ir->timer); | ||
270 | } else if (ir->rc5_gpio) { | ||
271 | /* set timer_end for code completion */ | ||
272 | init_timer(&ir->timer_end); | ||
273 | ir->timer_end.function = bttv_rc5_timer_end; | ||
274 | ir->timer_end.data = (unsigned long)ir; | ||
275 | |||
276 | init_timer(&ir->timer_keyup); | ||
277 | ir->timer_keyup.function = bttv_rc5_timer_keyup; | ||
278 | ir->timer_keyup.data = (unsigned long)ir; | ||
279 | } | ||
280 | } | ||
281 | |||
282 | static void bttv_ir_stop(struct bttv *btv) | ||
283 | { | ||
284 | if (btv->remote->polling) { | ||
285 | del_timer_sync(&btv->remote->timer); | ||
286 | flush_scheduled_work(); | ||
287 | } | ||
288 | |||
289 | if (btv->remote->rc5_gpio) { | ||
290 | u32 gpio; | ||
291 | |||
292 | del_timer_sync(&btv->remote->timer_end); | ||
293 | flush_scheduled_work(); | ||
294 | |||
295 | gpio = bttv_gpio_read(&btv->c); | ||
296 | bttv_gpio_write(&btv->c, gpio & ~(1 << 4)); | ||
297 | } | ||
298 | } | ||
299 | |||
262 | int bttv_input_init(struct bttv *btv) | 300 | int bttv_input_init(struct bttv *btv) |
263 | { | 301 | { |
264 | struct bttv_ir *ir; | 302 | struct bttv_ir *ir; |
265 | IR_KEYTAB_TYPE *ir_codes = NULL; | 303 | IR_KEYTAB_TYPE *ir_codes = NULL; |
266 | struct input_dev *input_dev; | 304 | struct input_dev *input_dev; |
267 | int ir_type = IR_TYPE_OTHER; | 305 | int ir_type = IR_TYPE_OTHER; |
306 | int err = -ENOMEM; | ||
268 | 307 | ||
269 | if (!btv->has_remote) | 308 | if (!btv->has_remote) |
270 | return -ENODEV; | 309 | return -ENODEV; |
271 | 310 | ||
272 | ir = kzalloc(sizeof(*ir),GFP_KERNEL); | 311 | ir = kzalloc(sizeof(*ir),GFP_KERNEL); |
273 | input_dev = input_allocate_device(); | 312 | input_dev = input_allocate_device(); |
274 | if (!ir || !input_dev) { | 313 | if (!ir || !input_dev) |
275 | kfree(ir); | 314 | goto err_out_free; |
276 | input_free_device(input_dev); | ||
277 | return -ENOMEM; | ||
278 | } | ||
279 | memset(ir,0,sizeof(*ir)); | ||
280 | 315 | ||
281 | /* detect & configure */ | 316 | /* detect & configure */ |
282 | switch (btv->c.type) { | 317 | switch (btv->c.type) { |
@@ -348,10 +383,9 @@ int bttv_input_init(struct bttv *btv) | |||
348 | break; | 383 | break; |
349 | } | 384 | } |
350 | if (NULL == ir_codes) { | 385 | if (NULL == ir_codes) { |
351 | dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n",btv->c.type); | 386 | dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n", btv->c.type); |
352 | kfree(ir); | 387 | err = -ENODEV; |
353 | input_free_device(input_dev); | 388 | goto err_out_free; |
354 | return -ENODEV; | ||
355 | } | 389 | } |
356 | 390 | ||
357 | if (ir->rc5_gpio) { | 391 | if (ir->rc5_gpio) { |
@@ -389,32 +423,26 @@ int bttv_input_init(struct bttv *btv) | |||
389 | input_dev->cdev.dev = &btv->c.pci->dev; | 423 | input_dev->cdev.dev = &btv->c.pci->dev; |
390 | 424 | ||
391 | btv->remote = ir; | 425 | btv->remote = ir; |
392 | if (ir->polling) { | 426 | bttv_ir_start(btv, ir); |
393 | init_timer(&ir->timer); | ||
394 | ir->timer.function = bttv_input_timer; | ||
395 | ir->timer.data = (unsigned long)btv; | ||
396 | ir->timer.expires = jiffies + HZ; | ||
397 | add_timer(&ir->timer); | ||
398 | } else if (ir->rc5_gpio) { | ||
399 | /* set timer_end for code completion */ | ||
400 | init_timer(&ir->timer_end); | ||
401 | ir->timer_end.function = bttv_rc5_timer_end; | ||
402 | ir->timer_end.data = (unsigned long)ir; | ||
403 | |||
404 | init_timer(&ir->timer_keyup); | ||
405 | ir->timer_keyup.function = bttv_rc5_timer_keyup; | ||
406 | ir->timer_keyup.data = (unsigned long)ir; | ||
407 | } | ||
408 | 427 | ||
409 | /* all done */ | 428 | /* all done */ |
410 | input_register_device(btv->remote->dev); | 429 | err = input_register_device(btv->remote->dev); |
411 | printk(DEVNAME ": %s detected at %s\n",ir->name,ir->phys); | 430 | if (err) |
431 | goto err_out_stop; | ||
412 | 432 | ||
413 | /* the remote isn't as bouncy as a keyboard */ | 433 | /* the remote isn't as bouncy as a keyboard */ |
414 | ir->dev->rep[REP_DELAY] = repeat_delay; | 434 | ir->dev->rep[REP_DELAY] = repeat_delay; |
415 | ir->dev->rep[REP_PERIOD] = repeat_period; | 435 | ir->dev->rep[REP_PERIOD] = repeat_period; |
416 | 436 | ||
417 | return 0; | 437 | return 0; |
438 | |||
439 | err_out_stop: | ||
440 | bttv_ir_stop(btv); | ||
441 | btv->remote = NULL; | ||
442 | err_out_free: | ||
443 | input_free_device(input_dev); | ||
444 | kfree(ir); | ||
445 | return err; | ||
418 | } | 446 | } |
419 | 447 | ||
420 | void bttv_input_fini(struct bttv *btv) | 448 | void bttv_input_fini(struct bttv *btv) |
@@ -422,22 +450,7 @@ void bttv_input_fini(struct bttv *btv) | |||
422 | if (btv->remote == NULL) | 450 | if (btv->remote == NULL) |
423 | return; | 451 | return; |
424 | 452 | ||
425 | if (btv->remote->polling) { | 453 | bttv_ir_stop(btv); |
426 | del_timer_sync(&btv->remote->timer); | ||
427 | flush_scheduled_work(); | ||
428 | } | ||
429 | |||
430 | |||
431 | if (btv->remote->rc5_gpio) { | ||
432 | u32 gpio; | ||
433 | |||
434 | del_timer_sync(&btv->remote->timer_end); | ||
435 | flush_scheduled_work(); | ||
436 | |||
437 | gpio = bttv_gpio_read(&btv->c); | ||
438 | bttv_gpio_write(&btv->c, gpio & ~(1 << 4)); | ||
439 | } | ||
440 | |||
441 | input_unregister_device(btv->remote->dev); | 454 | input_unregister_device(btv->remote->dev); |
442 | kfree(btv->remote); | 455 | kfree(btv->remote); |
443 | btv->remote = NULL; | 456 | btv->remote = NULL; |
diff --git a/drivers/media/video/cafe_ccic-regs.h b/drivers/media/video/cafe_ccic-regs.h new file mode 100644 index 000000000000..b2c22a0d6643 --- /dev/null +++ b/drivers/media/video/cafe_ccic-regs.h | |||
@@ -0,0 +1,160 @@ | |||
1 | /* | ||
2 | * Register definitions for the m88alp01 camera interface. Offsets in bytes | ||
3 | * as given in the spec. | ||
4 | * | ||
5 | * Copyright 2006 One Laptop Per Child Association, Inc. | ||
6 | * | ||
7 | * Written by Jonathan Corbet, corbet@lwn.net. | ||
8 | * | ||
9 | * This file may be distributed under the terms of the GNU General | ||
10 | * Public License, version 2. | ||
11 | */ | ||
12 | #define REG_Y0BAR 0x00 | ||
13 | #define REG_Y1BAR 0x04 | ||
14 | #define REG_Y2BAR 0x08 | ||
15 | /* ... */ | ||
16 | |||
17 | #define REG_IMGPITCH 0x24 /* Image pitch register */ | ||
18 | #define IMGP_YP_SHFT 2 /* Y pitch params */ | ||
19 | #define IMGP_YP_MASK 0x00003ffc /* Y pitch field */ | ||
20 | #define IMGP_UVP_SHFT 18 /* UV pitch (planar) */ | ||
21 | #define IMGP_UVP_MASK 0x3ffc0000 | ||
22 | #define REG_IRQSTATRAW 0x28 /* RAW IRQ Status */ | ||
23 | #define IRQ_EOF0 0x00000001 /* End of frame 0 */ | ||
24 | #define IRQ_EOF1 0x00000002 /* End of frame 1 */ | ||
25 | #define IRQ_EOF2 0x00000004 /* End of frame 2 */ | ||
26 | #define IRQ_SOF0 0x00000008 /* Start of frame 0 */ | ||
27 | #define IRQ_SOF1 0x00000010 /* Start of frame 1 */ | ||
28 | #define IRQ_SOF2 0x00000020 /* Start of frame 2 */ | ||
29 | #define IRQ_OVERFLOW 0x00000040 /* FIFO overflow */ | ||
30 | #define IRQ_TWSIW 0x00010000 /* TWSI (smbus) write */ | ||
31 | #define IRQ_TWSIR 0x00020000 /* TWSI read */ | ||
32 | #define IRQ_TWSIE 0x00040000 /* TWSI error */ | ||
33 | #define TWSIIRQS (IRQ_TWSIW|IRQ_TWSIR|IRQ_TWSIE) | ||
34 | #define FRAMEIRQS (IRQ_EOF0|IRQ_EOF1|IRQ_EOF2|IRQ_SOF0|IRQ_SOF1|IRQ_SOF2) | ||
35 | #define ALLIRQS (TWSIIRQS|FRAMEIRQS|IRQ_OVERFLOW) | ||
36 | #define REG_IRQMASK 0x2c /* IRQ mask - same bits as IRQSTAT */ | ||
37 | #define REG_IRQSTAT 0x30 /* IRQ status / clear */ | ||
38 | |||
39 | #define REG_IMGSIZE 0x34 /* Image size */ | ||
40 | #define IMGSZ_V_MASK 0x1fff0000 | ||
41 | #define IMGSZ_V_SHIFT 16 | ||
42 | #define IMGSZ_H_MASK 0x00003fff | ||
43 | #define REG_IMGOFFSET 0x38 /* IMage offset */ | ||
44 | |||
45 | #define REG_CTRL0 0x3c /* Control 0 */ | ||
46 | #define C0_ENABLE 0x00000001 /* Makes the whole thing go */ | ||
47 | |||
48 | /* Mask for all the format bits */ | ||
49 | #define C0_DF_MASK 0x00fffffc /* Bits 2-23 */ | ||
50 | |||
51 | /* RGB ordering */ | ||
52 | #define C0_RGB4_RGBX 0x00000000 | ||
53 | #define C0_RGB4_XRGB 0x00000004 | ||
54 | #define C0_RGB4_BGRX 0x00000008 | ||
55 | #define C0_RGB4_XBGR 0x0000000c | ||
56 | #define C0_RGB5_RGGB 0x00000000 | ||
57 | #define C0_RGB5_GRBG 0x00000004 | ||
58 | #define C0_RGB5_GBRG 0x00000008 | ||
59 | #define C0_RGB5_BGGR 0x0000000c | ||
60 | |||
61 | /* Spec has two fields for DIN and DOUT, but they must match, so | ||
62 | combine them here. */ | ||
63 | #define C0_DF_YUV 0x00000000 /* Data is YUV */ | ||
64 | #define C0_DF_RGB 0x000000a0 /* ... RGB */ | ||
65 | #define C0_DF_BAYER 0x00000140 /* ... Bayer */ | ||
66 | /* 8-8-8 must be missing from the below - ask */ | ||
67 | #define C0_RGBF_565 0x00000000 | ||
68 | #define C0_RGBF_444 0x00000800 | ||
69 | #define C0_RGB_BGR 0x00001000 /* Blue comes first */ | ||
70 | #define C0_YUV_PLANAR 0x00000000 /* YUV 422 planar format */ | ||
71 | #define C0_YUV_PACKED 0x00008000 /* YUV 422 packed */ | ||
72 | #define C0_YUV_420PL 0x0000a000 /* YUV 420 planar */ | ||
73 | /* Think that 420 packed must be 111 - ask */ | ||
74 | #define C0_YUVE_YUYV 0x00000000 /* Y1CbY0Cr */ | ||
75 | #define C0_YUVE_YVYU 0x00010000 /* Y1CrY0Cb */ | ||
76 | #define C0_YUVE_VYUY 0x00020000 /* CrY1CbY0 */ | ||
77 | #define C0_YUVE_UYVY 0x00030000 /* CbY1CrY0 */ | ||
78 | #define C0_YUVE_XYUV 0x00000000 /* 420: .YUV */ | ||
79 | #define C0_YUVE_XYVU 0x00010000 /* 420: .YVU */ | ||
80 | #define C0_YUVE_XUVY 0x00020000 /* 420: .UVY */ | ||
81 | #define C0_YUVE_XVUY 0x00030000 /* 420: .VUY */ | ||
82 | /* Bayer bits 18,19 if needed */ | ||
83 | #define C0_HPOL_LOW 0x01000000 /* HSYNC polarity active low */ | ||
84 | #define C0_VPOL_LOW 0x02000000 /* VSYNC polarity active low */ | ||
85 | #define C0_VCLK_LOW 0x04000000 /* VCLK on falling edge */ | ||
86 | #define C0_DOWNSCALE 0x08000000 /* Enable downscaler */ | ||
87 | #define C0_SIFM_MASK 0xc0000000 /* SIF mode bits */ | ||
88 | #define C0_SIF_HVSYNC 0x00000000 /* Use H/VSYNC */ | ||
89 | #define CO_SOF_NOSYNC 0x40000000 /* Use inband active signaling */ | ||
90 | |||
91 | |||
92 | #define REG_CTRL1 0x40 /* Control 1 */ | ||
93 | #define C1_444ALPHA 0x00f00000 /* Alpha field in RGB444 */ | ||
94 | #define C1_ALPHA_SHFT 20 | ||
95 | #define C1_DMAB32 0x00000000 /* 32-byte DMA burst */ | ||
96 | #define C1_DMAB16 0x02000000 /* 16-byte DMA burst */ | ||
97 | #define C1_DMAB64 0x04000000 /* 64-byte DMA burst */ | ||
98 | #define C1_DMAB_MASK 0x06000000 | ||
99 | #define C1_TWOBUFS 0x08000000 /* Use only two DMA buffers */ | ||
100 | #define C1_PWRDWN 0x10000000 /* Power down */ | ||
101 | |||
102 | #define REG_CLKCTRL 0x88 /* Clock control */ | ||
103 | #define CLK_DIV_MASK 0x0000ffff /* Upper bits RW "reserved" */ | ||
104 | |||
105 | #define REG_GPR 0xb4 /* General purpose register. This | ||
106 | controls inputs to the power and reset | ||
107 | pins on the OV7670 used with OLPC; | ||
108 | other deployments could differ. */ | ||
109 | #define GPR_C1EN 0x00000020 /* Pad 1 (power down) enable */ | ||
110 | #define GPR_C0EN 0x00000010 /* Pad 0 (reset) enable */ | ||
111 | #define GPR_C1 0x00000002 /* Control 1 value */ | ||
112 | /* | ||
113 | * Control 0 is wired to reset on OLPC machines. For ov7x sensors, | ||
114 | * it is active low, for 0v6x, instead, it's active high. What | ||
115 | * fun. | ||
116 | */ | ||
117 | #define GPR_C0 0x00000001 /* Control 0 value */ | ||
118 | |||
119 | #define REG_TWSIC0 0xb8 /* TWSI (smbus) control 0 */ | ||
120 | #define TWSIC0_EN 0x00000001 /* TWSI enable */ | ||
121 | #define TWSIC0_MODE 0x00000002 /* 1 = 16-bit, 0 = 8-bit */ | ||
122 | #define TWSIC0_SID 0x000003fc /* Slave ID */ | ||
123 | #define TWSIC0_SID_SHIFT 2 | ||
124 | #define TWSIC0_CLKDIV 0x0007fc00 /* Clock divider */ | ||
125 | #define TWSIC0_MASKACK 0x00400000 /* Mask ack from sensor */ | ||
126 | #define TWSIC0_OVMAGIC 0x00800000 /* Make it work on OV sensors */ | ||
127 | |||
128 | #define REG_TWSIC1 0xbc /* TWSI control 1 */ | ||
129 | #define TWSIC1_DATA 0x0000ffff /* Data to/from camchip */ | ||
130 | #define TWSIC1_ADDR 0x00ff0000 /* Address (register) */ | ||
131 | #define TWSIC1_ADDR_SHIFT 16 | ||
132 | #define TWSIC1_READ 0x01000000 /* Set for read op */ | ||
133 | #define TWSIC1_WSTAT 0x02000000 /* Write status */ | ||
134 | #define TWSIC1_RVALID 0x04000000 /* Read data valid */ | ||
135 | #define TWSIC1_ERROR 0x08000000 /* Something screwed up */ | ||
136 | |||
137 | |||
138 | #define REG_UBAR 0xc4 /* Upper base address register */ | ||
139 | |||
140 | /* | ||
141 | * Here's the weird global control registers which are said to live | ||
142 | * way up here. | ||
143 | */ | ||
144 | #define REG_GL_CSR 0x3004 /* Control/status register */ | ||
145 | #define GCSR_SRS 0x00000001 /* SW Reset set */ | ||
146 | #define GCSR_SRC 0x00000002 /* SW Reset clear */ | ||
147 | #define GCSR_MRS 0x00000004 /* Master reset set */ | ||
148 | #define GCSR_MRC 0x00000008 /* HW Reset clear */ | ||
149 | #define GCSR_CCIC_EN 0x00004000 /* CCIC Clock enable */ | ||
150 | #define REG_GL_IMASK 0x300c /* Interrupt mask register */ | ||
151 | #define GIMSK_CCIC_EN 0x00000004 /* CCIC Interrupt enable */ | ||
152 | |||
153 | #define REG_LEN REG_GL_IMASK + 4 | ||
154 | |||
155 | |||
156 | /* | ||
157 | * Useful stuff that probably belongs somewhere global. | ||
158 | */ | ||
159 | #define VGA_WIDTH 640 | ||
160 | #define VGA_HEIGHT 480 | ||
diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c new file mode 100644 index 000000000000..e347c7ebc984 --- /dev/null +++ b/drivers/media/video/cafe_ccic.c | |||
@@ -0,0 +1,2228 @@ | |||
1 | /* | ||
2 | * A driver for the CMOS camera controller in the Marvell 88ALP01 "cafe" | ||
3 | * multifunction chip. Currently works with the Omnivision OV7670 | ||
4 | * sensor. | ||
5 | * | ||
6 | * Copyright 2006 One Laptop Per Child Association, Inc. | ||
7 | * | ||
8 | * Written by Jonathan Corbet, corbet@lwn.net. | ||
9 | * | ||
10 | * This file may be distributed under the terms of the GNU General | ||
11 | * Public License, version 2. | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/moduleparam.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/fs.h> | ||
19 | #include <linux/pci.h> | ||
20 | #include <linux/i2c.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/spinlock.h> | ||
23 | #include <linux/videodev2.h> | ||
24 | #include <media/v4l2-common.h> | ||
25 | #include <linux/device.h> | ||
26 | #include <linux/wait.h> | ||
27 | #include <linux/list.h> | ||
28 | #include <linux/dma-mapping.h> | ||
29 | #include <linux/delay.h> | ||
30 | #include <linux/debugfs.h> | ||
31 | #include <linux/jiffies.h> | ||
32 | #include <linux/vmalloc.h> | ||
33 | |||
34 | #include <asm/uaccess.h> | ||
35 | #include <asm/io.h> | ||
36 | |||
37 | #include "cafe_ccic-regs.h" | ||
38 | |||
39 | #define CAFE_VERSION 0x000001 | ||
40 | |||
41 | |||
42 | /* | ||
43 | * Parameters. | ||
44 | */ | ||
45 | MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>"); | ||
46 | MODULE_DESCRIPTION("Marvell 88ALP01 CMOS Camera Controller driver"); | ||
47 | MODULE_LICENSE("GPL"); | ||
48 | MODULE_SUPPORTED_DEVICE("Video"); | ||
49 | |||
50 | /* | ||
51 | * Internal DMA buffer management. Since the controller cannot do S/G I/O, | ||
52 | * we must have physically contiguous buffers to bring frames into. | ||
53 | * These parameters control how many buffers we use, whether we | ||
54 | * allocate them at load time (better chance of success, but nails down | ||
55 | * memory) or when somebody tries to use the camera (riskier), and, | ||
56 | * for load-time allocation, how big they should be. | ||
57 | * | ||
58 | * The controller can cycle through three buffers. We could use | ||
59 | * more by flipping pointers around, but it probably makes little | ||
60 | * sense. | ||
61 | */ | ||
62 | |||
63 | #define MAX_DMA_BUFS 3 | ||
64 | static int alloc_bufs_at_load = 0; | ||
65 | module_param(alloc_bufs_at_load, bool, 0444); | ||
66 | MODULE_PARM_DESC(alloc_bufs_at_load, | ||
67 | "Non-zero value causes DMA buffers to be allocated at module " | ||
68 | "load time. This increases the chances of successfully getting " | ||
69 | "those buffers, but at the cost of nailing down the memory from " | ||
70 | "the outset."); | ||
71 | |||
72 | static int n_dma_bufs = 3; | ||
73 | module_param(n_dma_bufs, uint, 0644); | ||
74 | MODULE_PARM_DESC(n_dma_bufs, | ||
75 | "The number of DMA buffers to allocate. Can be either two " | ||
76 | "(saves memory, makes timing tighter) or three."); | ||
77 | |||
78 | static int dma_buf_size = VGA_WIDTH * VGA_HEIGHT * 2; /* Worst case */ | ||
79 | module_param(dma_buf_size, uint, 0444); | ||
80 | MODULE_PARM_DESC(dma_buf_size, | ||
81 | "The size of the allocated DMA buffers. If actual operating " | ||
82 | "parameters require larger buffers, an attempt to reallocate " | ||
83 | "will be made."); | ||
84 | |||
85 | static int min_buffers = 1; | ||
86 | module_param(min_buffers, uint, 0644); | ||
87 | MODULE_PARM_DESC(min_buffers, | ||
88 | "The minimum number of streaming I/O buffers we are willing " | ||
89 | "to work with."); | ||
90 | |||
91 | static int max_buffers = 10; | ||
92 | module_param(max_buffers, uint, 0644); | ||
93 | MODULE_PARM_DESC(max_buffers, | ||
94 | "The maximum number of streaming I/O buffers an application " | ||
95 | "will be allowed to allocate. These buffers are big and live " | ||
96 | "in vmalloc space."); | ||
97 | |||
98 | static int flip = 0; | ||
99 | module_param(flip, bool, 0444); | ||
100 | MODULE_PARM_DESC(flip, | ||
101 | "If set, the sensor will be instructed to flip the image " | ||
102 | "vertically."); | ||
103 | |||
104 | |||
105 | enum cafe_state { | ||
106 | S_NOTREADY, /* Not yet initialized */ | ||
107 | S_IDLE, /* Just hanging around */ | ||
108 | S_FLAKED, /* Some sort of problem */ | ||
109 | S_SINGLEREAD, /* In read() */ | ||
110 | S_SPECREAD, /* Speculative read (for future read()) */ | ||
111 | S_STREAMING /* Streaming data */ | ||
112 | }; | ||
113 | |||
114 | /* | ||
115 | * Tracking of streaming I/O buffers. | ||
116 | */ | ||
117 | struct cafe_sio_buffer { | ||
118 | struct list_head list; | ||
119 | struct v4l2_buffer v4lbuf; | ||
120 | char *buffer; /* Where it lives in kernel space */ | ||
121 | int mapcount; | ||
122 | struct cafe_camera *cam; | ||
123 | }; | ||
124 | |||
125 | /* | ||
126 | * A description of one of our devices. | ||
127 | * Locking: controlled by s_mutex. Certain fields, however, require | ||
128 | * the dev_lock spinlock; they are marked as such by comments. | ||
129 | * dev_lock is also required for access to device registers. | ||
130 | */ | ||
131 | struct cafe_camera | ||
132 | { | ||
133 | enum cafe_state state; | ||
134 | unsigned long flags; /* Buffer status, mainly (dev_lock) */ | ||
135 | int users; /* How many open FDs */ | ||
136 | struct file *owner; /* Who has data access (v4l2) */ | ||
137 | |||
138 | /* | ||
139 | * Subsystem structures. | ||
140 | */ | ||
141 | struct pci_dev *pdev; | ||
142 | struct video_device v4ldev; | ||
143 | struct i2c_adapter i2c_adapter; | ||
144 | struct i2c_client *sensor; | ||
145 | |||
146 | unsigned char __iomem *regs; | ||
147 | struct list_head dev_list; /* link to other devices */ | ||
148 | |||
149 | /* DMA buffers */ | ||
150 | unsigned int nbufs; /* How many are alloc'd */ | ||
151 | int next_buf; /* Next to consume (dev_lock) */ | ||
152 | unsigned int dma_buf_size; /* allocated size */ | ||
153 | void *dma_bufs[MAX_DMA_BUFS]; /* Internal buffer addresses */ | ||
154 | dma_addr_t dma_handles[MAX_DMA_BUFS]; /* Buffer bus addresses */ | ||
155 | unsigned int specframes; /* Unconsumed spec frames (dev_lock) */ | ||
156 | unsigned int sequence; /* Frame sequence number */ | ||
157 | unsigned int buf_seq[MAX_DMA_BUFS]; /* Sequence for individual buffers */ | ||
158 | |||
159 | /* Streaming buffers */ | ||
160 | unsigned int n_sbufs; /* How many we have */ | ||
161 | struct cafe_sio_buffer *sb_bufs; /* The array of housekeeping structs */ | ||
162 | struct list_head sb_avail; /* Available for data (we own) (dev_lock) */ | ||
163 | struct list_head sb_full; /* With data (user space owns) (dev_lock) */ | ||
164 | struct tasklet_struct s_tasklet; | ||
165 | |||
166 | /* Current operating parameters */ | ||
167 | enum v4l2_chip_ident sensor_type; /* Currently ov7670 only */ | ||
168 | struct v4l2_pix_format pix_format; | ||
169 | |||
170 | /* Locks */ | ||
171 | struct mutex s_mutex; /* Access to this structure */ | ||
172 | spinlock_t dev_lock; /* Access to device */ | ||
173 | |||
174 | /* Misc */ | ||
175 | wait_queue_head_t smbus_wait; /* Waiting on i2c events */ | ||
176 | wait_queue_head_t iowait; /* Waiting on frame data */ | ||
177 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
178 | struct dentry *dfs_regs; | ||
179 | struct dentry *dfs_cam_regs; | ||
180 | #endif | ||
181 | }; | ||
182 | |||
183 | /* | ||
184 | * Status flags. Always manipulated with bit operations. | ||
185 | */ | ||
186 | #define CF_BUF0_VALID 0 /* Buffers valid - first three */ | ||
187 | #define CF_BUF1_VALID 1 | ||
188 | #define CF_BUF2_VALID 2 | ||
189 | #define CF_DMA_ACTIVE 3 /* A frame is incoming */ | ||
190 | #define CF_CONFIG_NEEDED 4 /* Must configure hardware */ | ||
191 | |||
192 | |||
193 | |||
194 | /* | ||
195 | * Start over with DMA buffers - dev_lock needed. | ||
196 | */ | ||
197 | static void cafe_reset_buffers(struct cafe_camera *cam) | ||
198 | { | ||
199 | int i; | ||
200 | |||
201 | cam->next_buf = -1; | ||
202 | for (i = 0; i < cam->nbufs; i++) | ||
203 | clear_bit(i, &cam->flags); | ||
204 | cam->specframes = 0; | ||
205 | } | ||
206 | |||
207 | static inline int cafe_needs_config(struct cafe_camera *cam) | ||
208 | { | ||
209 | return test_bit(CF_CONFIG_NEEDED, &cam->flags); | ||
210 | } | ||
211 | |||
212 | static void cafe_set_config_needed(struct cafe_camera *cam, int needed) | ||
213 | { | ||
214 | if (needed) | ||
215 | set_bit(CF_CONFIG_NEEDED, &cam->flags); | ||
216 | else | ||
217 | clear_bit(CF_CONFIG_NEEDED, &cam->flags); | ||
218 | } | ||
219 | |||
220 | |||
221 | |||
222 | |||
223 | /* | ||
224 | * Debugging and related. | ||
225 | */ | ||
226 | #define cam_err(cam, fmt, arg...) \ | ||
227 | dev_err(&(cam)->pdev->dev, fmt, ##arg); | ||
228 | #define cam_warn(cam, fmt, arg...) \ | ||
229 | dev_warn(&(cam)->pdev->dev, fmt, ##arg); | ||
230 | #define cam_dbg(cam, fmt, arg...) \ | ||
231 | dev_dbg(&(cam)->pdev->dev, fmt, ##arg); | ||
232 | |||
233 | |||
234 | /* ---------------------------------------------------------------------*/ | ||
235 | /* | ||
236 | * We keep a simple list of known devices to search at open time. | ||
237 | */ | ||
238 | static LIST_HEAD(cafe_dev_list); | ||
239 | static DEFINE_MUTEX(cafe_dev_list_lock); | ||
240 | |||
241 | static void cafe_add_dev(struct cafe_camera *cam) | ||
242 | { | ||
243 | mutex_lock(&cafe_dev_list_lock); | ||
244 | list_add_tail(&cam->dev_list, &cafe_dev_list); | ||
245 | mutex_unlock(&cafe_dev_list_lock); | ||
246 | } | ||
247 | |||
248 | static void cafe_remove_dev(struct cafe_camera *cam) | ||
249 | { | ||
250 | mutex_lock(&cafe_dev_list_lock); | ||
251 | list_del(&cam->dev_list); | ||
252 | mutex_unlock(&cafe_dev_list_lock); | ||
253 | } | ||
254 | |||
255 | static struct cafe_camera *cafe_find_dev(int minor) | ||
256 | { | ||
257 | struct cafe_camera *cam; | ||
258 | |||
259 | mutex_lock(&cafe_dev_list_lock); | ||
260 | list_for_each_entry(cam, &cafe_dev_list, dev_list) { | ||
261 | if (cam->v4ldev.minor == minor) | ||
262 | goto done; | ||
263 | } | ||
264 | cam = NULL; | ||
265 | done: | ||
266 | mutex_unlock(&cafe_dev_list_lock); | ||
267 | return cam; | ||
268 | } | ||
269 | |||
270 | |||
271 | static struct cafe_camera *cafe_find_by_pdev(struct pci_dev *pdev) | ||
272 | { | ||
273 | struct cafe_camera *cam; | ||
274 | |||
275 | mutex_lock(&cafe_dev_list_lock); | ||
276 | list_for_each_entry(cam, &cafe_dev_list, dev_list) { | ||
277 | if (cam->pdev == pdev) | ||
278 | goto done; | ||
279 | } | ||
280 | cam = NULL; | ||
281 | done: | ||
282 | mutex_unlock(&cafe_dev_list_lock); | ||
283 | return cam; | ||
284 | } | ||
285 | |||
286 | |||
287 | /* ------------------------------------------------------------------------ */ | ||
288 | /* | ||
289 | * Device register I/O | ||
290 | */ | ||
291 | static inline void cafe_reg_write(struct cafe_camera *cam, unsigned int reg, | ||
292 | unsigned int val) | ||
293 | { | ||
294 | iowrite32(val, cam->regs + reg); | ||
295 | } | ||
296 | |||
297 | static inline unsigned int cafe_reg_read(struct cafe_camera *cam, | ||
298 | unsigned int reg) | ||
299 | { | ||
300 | return ioread32(cam->regs + reg); | ||
301 | } | ||
302 | |||
303 | |||
304 | static inline void cafe_reg_write_mask(struct cafe_camera *cam, unsigned int reg, | ||
305 | unsigned int val, unsigned int mask) | ||
306 | { | ||
307 | unsigned int v = cafe_reg_read(cam, reg); | ||
308 | |||
309 | v = (v & ~mask) | (val & mask); | ||
310 | cafe_reg_write(cam, reg, v); | ||
311 | } | ||
312 | |||
313 | static inline void cafe_reg_clear_bit(struct cafe_camera *cam, | ||
314 | unsigned int reg, unsigned int val) | ||
315 | { | ||
316 | cafe_reg_write_mask(cam, reg, 0, val); | ||
317 | } | ||
318 | |||
319 | static inline void cafe_reg_set_bit(struct cafe_camera *cam, | ||
320 | unsigned int reg, unsigned int val) | ||
321 | { | ||
322 | cafe_reg_write_mask(cam, reg, val, val); | ||
323 | } | ||
324 | |||
325 | |||
326 | |||
327 | /* -------------------------------------------------------------------- */ | ||
328 | /* | ||
329 | * The I2C/SMBUS interface to the camera itself starts here. The | ||
330 | * controller handles SMBUS itself, presenting a relatively simple register | ||
331 | * interface; all we have to do is to tell it where to route the data. | ||
332 | */ | ||
333 | #define CAFE_SMBUS_TIMEOUT (HZ) /* generous */ | ||
334 | |||
335 | static int cafe_smbus_write_done(struct cafe_camera *cam) | ||
336 | { | ||
337 | unsigned long flags; | ||
338 | int c1; | ||
339 | |||
340 | /* | ||
341 | * We must delay after the interrupt, or the controller gets confused | ||
342 | * and never does give us good status. Fortunately, we don't do this | ||
343 | * often. | ||
344 | */ | ||
345 | udelay(20); | ||
346 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
347 | c1 = cafe_reg_read(cam, REG_TWSIC1); | ||
348 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
349 | return (c1 & (TWSIC1_WSTAT|TWSIC1_ERROR)) != TWSIC1_WSTAT; | ||
350 | } | ||
351 | |||
352 | static int cafe_smbus_write_data(struct cafe_camera *cam, | ||
353 | u16 addr, u8 command, u8 value) | ||
354 | { | ||
355 | unsigned int rval; | ||
356 | unsigned long flags; | ||
357 | |||
358 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
359 | rval = TWSIC0_EN | ((addr << TWSIC0_SID_SHIFT) & TWSIC0_SID); | ||
360 | rval |= TWSIC0_OVMAGIC; /* Make OV sensors work */ | ||
361 | /* | ||
362 | * Marvell sez set clkdiv to all 1's for now. | ||
363 | */ | ||
364 | rval |= TWSIC0_CLKDIV; | ||
365 | cafe_reg_write(cam, REG_TWSIC0, rval); | ||
366 | (void) cafe_reg_read(cam, REG_TWSIC1); /* force write */ | ||
367 | rval = value | ((command << TWSIC1_ADDR_SHIFT) & TWSIC1_ADDR); | ||
368 | cafe_reg_write(cam, REG_TWSIC1, rval); | ||
369 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
370 | msleep(2); /* Required or things flake */ | ||
371 | |||
372 | wait_event_timeout(cam->smbus_wait, cafe_smbus_write_done(cam), | ||
373 | CAFE_SMBUS_TIMEOUT); | ||
374 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
375 | rval = cafe_reg_read(cam, REG_TWSIC1); | ||
376 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
377 | |||
378 | if (rval & TWSIC1_WSTAT) { | ||
379 | cam_err(cam, "SMBUS write (%02x/%02x/%02x) timed out\n", addr, | ||
380 | command, value); | ||
381 | return -EIO; | ||
382 | } | ||
383 | if (rval & TWSIC1_ERROR) { | ||
384 | cam_err(cam, "SMBUS write (%02x/%02x/%02x) error\n", addr, | ||
385 | command, value); | ||
386 | return -EIO; | ||
387 | } | ||
388 | return 0; | ||
389 | } | ||
390 | |||
391 | |||
392 | |||
393 | static int cafe_smbus_read_done(struct cafe_camera *cam) | ||
394 | { | ||
395 | unsigned long flags; | ||
396 | int c1; | ||
397 | |||
398 | /* | ||
399 | * We must delay after the interrupt, or the controller gets confused | ||
400 | * and never does give us good status. Fortunately, we don't do this | ||
401 | * often. | ||
402 | */ | ||
403 | udelay(20); | ||
404 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
405 | c1 = cafe_reg_read(cam, REG_TWSIC1); | ||
406 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
407 | return c1 & (TWSIC1_RVALID|TWSIC1_ERROR); | ||
408 | } | ||
409 | |||
410 | |||
411 | |||
412 | static int cafe_smbus_read_data(struct cafe_camera *cam, | ||
413 | u16 addr, u8 command, u8 *value) | ||
414 | { | ||
415 | unsigned int rval; | ||
416 | unsigned long flags; | ||
417 | |||
418 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
419 | rval = TWSIC0_EN | ((addr << TWSIC0_SID_SHIFT) & TWSIC0_SID); | ||
420 | rval |= TWSIC0_OVMAGIC; /* Make OV sensors work */ | ||
421 | /* | ||
422 | * Marvel sez set clkdiv to all 1's for now. | ||
423 | */ | ||
424 | rval |= TWSIC0_CLKDIV; | ||
425 | cafe_reg_write(cam, REG_TWSIC0, rval); | ||
426 | (void) cafe_reg_read(cam, REG_TWSIC1); /* force write */ | ||
427 | rval = TWSIC1_READ | ((command << TWSIC1_ADDR_SHIFT) & TWSIC1_ADDR); | ||
428 | cafe_reg_write(cam, REG_TWSIC1, rval); | ||
429 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
430 | |||
431 | wait_event_timeout(cam->smbus_wait, | ||
432 | cafe_smbus_read_done(cam), CAFE_SMBUS_TIMEOUT); | ||
433 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
434 | rval = cafe_reg_read(cam, REG_TWSIC1); | ||
435 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
436 | |||
437 | if (rval & TWSIC1_ERROR) { | ||
438 | cam_err(cam, "SMBUS read (%02x/%02x) error\n", addr, command); | ||
439 | return -EIO; | ||
440 | } | ||
441 | if (! (rval & TWSIC1_RVALID)) { | ||
442 | cam_err(cam, "SMBUS read (%02x/%02x) timed out\n", addr, | ||
443 | command); | ||
444 | return -EIO; | ||
445 | } | ||
446 | *value = rval & 0xff; | ||
447 | return 0; | ||
448 | } | ||
449 | |||
450 | /* | ||
451 | * Perform a transfer over SMBUS. This thing is called under | ||
452 | * the i2c bus lock, so we shouldn't race with ourselves... | ||
453 | */ | ||
454 | static int cafe_smbus_xfer(struct i2c_adapter *adapter, u16 addr, | ||
455 | unsigned short flags, char rw, u8 command, | ||
456 | int size, union i2c_smbus_data *data) | ||
457 | { | ||
458 | struct cafe_camera *cam = i2c_get_adapdata(adapter); | ||
459 | int ret = -EINVAL; | ||
460 | |||
461 | /* | ||
462 | * Refuse to talk to anything but OV cam chips. We should | ||
463 | * never even see an attempt to do so, but one never knows. | ||
464 | */ | ||
465 | if (cam->sensor && addr != cam->sensor->addr) { | ||
466 | cam_err(cam, "funky smbus addr %d\n", addr); | ||
467 | return -EINVAL; | ||
468 | } | ||
469 | /* | ||
470 | * This interface would appear to only do byte data ops. OK | ||
471 | * it can do word too, but the cam chip has no use for that. | ||
472 | */ | ||
473 | if (size != I2C_SMBUS_BYTE_DATA) { | ||
474 | cam_err(cam, "funky xfer size %d\n", size); | ||
475 | return -EINVAL; | ||
476 | } | ||
477 | |||
478 | if (rw == I2C_SMBUS_WRITE) | ||
479 | ret = cafe_smbus_write_data(cam, addr, command, data->byte); | ||
480 | else if (rw == I2C_SMBUS_READ) | ||
481 | ret = cafe_smbus_read_data(cam, addr, command, &data->byte); | ||
482 | return ret; | ||
483 | } | ||
484 | |||
485 | |||
486 | static void cafe_smbus_enable_irq(struct cafe_camera *cam) | ||
487 | { | ||
488 | unsigned long flags; | ||
489 | |||
490 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
491 | cafe_reg_set_bit(cam, REG_IRQMASK, TWSIIRQS); | ||
492 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
493 | } | ||
494 | |||
495 | static u32 cafe_smbus_func(struct i2c_adapter *adapter) | ||
496 | { | ||
497 | return I2C_FUNC_SMBUS_READ_BYTE_DATA | | ||
498 | I2C_FUNC_SMBUS_WRITE_BYTE_DATA; | ||
499 | } | ||
500 | |||
501 | static struct i2c_algorithm cafe_smbus_algo = { | ||
502 | .smbus_xfer = cafe_smbus_xfer, | ||
503 | .functionality = cafe_smbus_func | ||
504 | }; | ||
505 | |||
506 | /* Somebody is on the bus */ | ||
507 | static int cafe_cam_init(struct cafe_camera *cam); | ||
508 | static void cafe_ctlr_stop_dma(struct cafe_camera *cam); | ||
509 | static void cafe_ctlr_power_down(struct cafe_camera *cam); | ||
510 | |||
511 | static int cafe_smbus_attach(struct i2c_client *client) | ||
512 | { | ||
513 | struct cafe_camera *cam = i2c_get_adapdata(client->adapter); | ||
514 | |||
515 | /* | ||
516 | * Don't talk to chips we don't recognize. | ||
517 | */ | ||
518 | if (client->driver->id == I2C_DRIVERID_OV7670) { | ||
519 | cam->sensor = client; | ||
520 | return cafe_cam_init(cam); | ||
521 | } | ||
522 | return -EINVAL; | ||
523 | } | ||
524 | |||
525 | static int cafe_smbus_detach(struct i2c_client *client) | ||
526 | { | ||
527 | struct cafe_camera *cam = i2c_get_adapdata(client->adapter); | ||
528 | |||
529 | if (cam->sensor == client) { | ||
530 | cafe_ctlr_stop_dma(cam); | ||
531 | cafe_ctlr_power_down(cam); | ||
532 | cam_err(cam, "lost the sensor!\n"); | ||
533 | cam->sensor = NULL; /* Bummer, no camera */ | ||
534 | cam->state = S_NOTREADY; | ||
535 | } | ||
536 | return 0; | ||
537 | } | ||
538 | |||
539 | static int cafe_smbus_setup(struct cafe_camera *cam) | ||
540 | { | ||
541 | struct i2c_adapter *adap = &cam->i2c_adapter; | ||
542 | int ret; | ||
543 | |||
544 | cafe_smbus_enable_irq(cam); | ||
545 | adap->id = I2C_HW_SMBUS_CAFE; | ||
546 | adap->class = I2C_CLASS_CAM_DIGITAL; | ||
547 | adap->owner = THIS_MODULE; | ||
548 | adap->client_register = cafe_smbus_attach; | ||
549 | adap->client_unregister = cafe_smbus_detach; | ||
550 | adap->algo = &cafe_smbus_algo; | ||
551 | strcpy(adap->name, "cafe_ccic"); | ||
552 | i2c_set_adapdata(adap, cam); | ||
553 | ret = i2c_add_adapter(adap); | ||
554 | if (ret) | ||
555 | printk(KERN_ERR "Unable to register cafe i2c adapter\n"); | ||
556 | return ret; | ||
557 | } | ||
558 | |||
559 | static void cafe_smbus_shutdown(struct cafe_camera *cam) | ||
560 | { | ||
561 | i2c_del_adapter(&cam->i2c_adapter); | ||
562 | } | ||
563 | |||
564 | |||
565 | /* ------------------------------------------------------------------- */ | ||
566 | /* | ||
567 | * Deal with the controller. | ||
568 | */ | ||
569 | |||
570 | /* | ||
571 | * Do everything we think we need to have the interface operating | ||
572 | * according to the desired format. | ||
573 | */ | ||
574 | static void cafe_ctlr_dma(struct cafe_camera *cam) | ||
575 | { | ||
576 | /* | ||
577 | * Store the first two Y buffers (we aren't supporting | ||
578 | * planar formats for now, so no UV bufs). Then either | ||
579 | * set the third if it exists, or tell the controller | ||
580 | * to just use two. | ||
581 | */ | ||
582 | cafe_reg_write(cam, REG_Y0BAR, cam->dma_handles[0]); | ||
583 | cafe_reg_write(cam, REG_Y1BAR, cam->dma_handles[1]); | ||
584 | if (cam->nbufs > 2) { | ||
585 | cafe_reg_write(cam, REG_Y2BAR, cam->dma_handles[2]); | ||
586 | cafe_reg_clear_bit(cam, REG_CTRL1, C1_TWOBUFS); | ||
587 | } | ||
588 | else | ||
589 | cafe_reg_set_bit(cam, REG_CTRL1, C1_TWOBUFS); | ||
590 | cafe_reg_write(cam, REG_UBAR, 0); /* 32 bits only for now */ | ||
591 | } | ||
592 | |||
593 | static void cafe_ctlr_image(struct cafe_camera *cam) | ||
594 | { | ||
595 | int imgsz; | ||
596 | struct v4l2_pix_format *fmt = &cam->pix_format; | ||
597 | |||
598 | imgsz = ((fmt->height << IMGSZ_V_SHIFT) & IMGSZ_V_MASK) | | ||
599 | (fmt->bytesperline & IMGSZ_H_MASK); | ||
600 | cafe_reg_write(cam, REG_IMGSIZE, imgsz); | ||
601 | cafe_reg_write(cam, REG_IMGOFFSET, 0); | ||
602 | /* YPITCH just drops the last two bits */ | ||
603 | cafe_reg_write_mask(cam, REG_IMGPITCH, fmt->bytesperline, | ||
604 | IMGP_YP_MASK); | ||
605 | /* | ||
606 | * Tell the controller about the image format we are using. | ||
607 | */ | ||
608 | switch (cam->pix_format.pixelformat) { | ||
609 | case V4L2_PIX_FMT_YUYV: | ||
610 | cafe_reg_write_mask(cam, REG_CTRL0, | ||
611 | C0_DF_YUV|C0_YUV_PACKED|C0_YUVE_YUYV, | ||
612 | C0_DF_MASK); | ||
613 | break; | ||
614 | |||
615 | case V4L2_PIX_FMT_RGB444: | ||
616 | cafe_reg_write_mask(cam, REG_CTRL0, | ||
617 | C0_DF_RGB|C0_RGBF_444|C0_RGB4_XRGB, | ||
618 | C0_DF_MASK); | ||
619 | /* Alpha value? */ | ||
620 | break; | ||
621 | |||
622 | case V4L2_PIX_FMT_RGB565: | ||
623 | cafe_reg_write_mask(cam, REG_CTRL0, | ||
624 | C0_DF_RGB|C0_RGBF_565|C0_RGB5_BGGR, | ||
625 | C0_DF_MASK); | ||
626 | break; | ||
627 | |||
628 | default: | ||
629 | cam_err(cam, "Unknown format %x\n", cam->pix_format.pixelformat); | ||
630 | break; | ||
631 | } | ||
632 | /* | ||
633 | * Make sure it knows we want to use hsync/vsync. | ||
634 | */ | ||
635 | cafe_reg_write_mask(cam, REG_CTRL0, C0_SIF_HVSYNC, | ||
636 | C0_SIFM_MASK); | ||
637 | } | ||
638 | |||
639 | |||
640 | /* | ||
641 | * Configure the controller for operation; caller holds the | ||
642 | * device mutex. | ||
643 | */ | ||
644 | static int cafe_ctlr_configure(struct cafe_camera *cam) | ||
645 | { | ||
646 | unsigned long flags; | ||
647 | |||
648 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
649 | cafe_ctlr_dma(cam); | ||
650 | cafe_ctlr_image(cam); | ||
651 | cafe_set_config_needed(cam, 0); | ||
652 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
653 | return 0; | ||
654 | } | ||
655 | |||
656 | static void cafe_ctlr_irq_enable(struct cafe_camera *cam) | ||
657 | { | ||
658 | /* | ||
659 | * Clear any pending interrupts, since we do not | ||
660 | * expect to have I/O active prior to enabling. | ||
661 | */ | ||
662 | cafe_reg_write(cam, REG_IRQSTAT, FRAMEIRQS); | ||
663 | cafe_reg_set_bit(cam, REG_IRQMASK, FRAMEIRQS); | ||
664 | } | ||
665 | |||
666 | static void cafe_ctlr_irq_disable(struct cafe_camera *cam) | ||
667 | { | ||
668 | cafe_reg_clear_bit(cam, REG_IRQMASK, FRAMEIRQS); | ||
669 | } | ||
670 | |||
671 | /* | ||
672 | * Make the controller start grabbing images. Everything must | ||
673 | * be set up before doing this. | ||
674 | */ | ||
675 | static void cafe_ctlr_start(struct cafe_camera *cam) | ||
676 | { | ||
677 | /* set_bit performs a read, so no other barrier should be | ||
678 | needed here */ | ||
679 | cafe_reg_set_bit(cam, REG_CTRL0, C0_ENABLE); | ||
680 | } | ||
681 | |||
682 | static void cafe_ctlr_stop(struct cafe_camera *cam) | ||
683 | { | ||
684 | cafe_reg_clear_bit(cam, REG_CTRL0, C0_ENABLE); | ||
685 | } | ||
686 | |||
687 | static void cafe_ctlr_init(struct cafe_camera *cam) | ||
688 | { | ||
689 | unsigned long flags; | ||
690 | |||
691 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
692 | /* | ||
693 | * Added magic to bring up the hardware on the B-Test board | ||
694 | */ | ||
695 | cafe_reg_write(cam, 0x3038, 0x8); | ||
696 | cafe_reg_write(cam, 0x315c, 0x80008); | ||
697 | /* | ||
698 | * Go through the dance needed to wake the device up. | ||
699 | * Note that these registers are global and shared | ||
700 | * with the NAND and SD devices. Interaction between the | ||
701 | * three still needs to be examined. | ||
702 | */ | ||
703 | cafe_reg_write(cam, REG_GL_CSR, GCSR_SRS|GCSR_MRS); /* Needed? */ | ||
704 | cafe_reg_write(cam, REG_GL_CSR, GCSR_SRC|GCSR_MRC); | ||
705 | cafe_reg_write(cam, REG_GL_CSR, GCSR_SRC|GCSR_MRS); | ||
706 | mdelay(5); /* FIXME revisit this */ | ||
707 | cafe_reg_write(cam, REG_GL_CSR, GCSR_CCIC_EN|GCSR_SRC|GCSR_MRC); | ||
708 | cafe_reg_set_bit(cam, REG_GL_IMASK, GIMSK_CCIC_EN); | ||
709 | /* | ||
710 | * Make sure it's not powered down. | ||
711 | */ | ||
712 | cafe_reg_clear_bit(cam, REG_CTRL1, C1_PWRDWN); | ||
713 | /* | ||
714 | * Turn off the enable bit. It sure should be off anyway, | ||
715 | * but it's good to be sure. | ||
716 | */ | ||
717 | cafe_reg_clear_bit(cam, REG_CTRL0, C0_ENABLE); | ||
718 | /* | ||
719 | * Mask all interrupts. | ||
720 | */ | ||
721 | cafe_reg_write(cam, REG_IRQMASK, 0); | ||
722 | /* | ||
723 | * Clock the sensor appropriately. Controller clock should | ||
724 | * be 48MHz, sensor "typical" value is half that. | ||
725 | */ | ||
726 | cafe_reg_write_mask(cam, REG_CLKCTRL, 2, CLK_DIV_MASK); | ||
727 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
728 | } | ||
729 | |||
730 | |||
731 | /* | ||
732 | * Stop the controller, and don't return until we're really sure that no | ||
733 | * further DMA is going on. | ||
734 | */ | ||
735 | static void cafe_ctlr_stop_dma(struct cafe_camera *cam) | ||
736 | { | ||
737 | unsigned long flags; | ||
738 | |||
739 | /* | ||
740 | * Theory: stop the camera controller (whether it is operating | ||
741 | * or not). Delay briefly just in case we race with the SOF | ||
742 | * interrupt, then wait until no DMA is active. | ||
743 | */ | ||
744 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
745 | cafe_ctlr_stop(cam); | ||
746 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
747 | mdelay(1); | ||
748 | wait_event_timeout(cam->iowait, | ||
749 | !test_bit(CF_DMA_ACTIVE, &cam->flags), HZ); | ||
750 | if (test_bit(CF_DMA_ACTIVE, &cam->flags)) | ||
751 | cam_err(cam, "Timeout waiting for DMA to end\n"); | ||
752 | /* This would be bad news - what now? */ | ||
753 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
754 | cam->state = S_IDLE; | ||
755 | cafe_ctlr_irq_disable(cam); | ||
756 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
757 | } | ||
758 | |||
759 | /* | ||
760 | * Power up and down. | ||
761 | */ | ||
762 | static void cafe_ctlr_power_up(struct cafe_camera *cam) | ||
763 | { | ||
764 | unsigned long flags; | ||
765 | |||
766 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
767 | cafe_reg_clear_bit(cam, REG_CTRL1, C1_PWRDWN); | ||
768 | /* | ||
769 | * Put the sensor into operational mode (assumes OLPC-style | ||
770 | * wiring). Control 0 is reset - set to 1 to operate. | ||
771 | * Control 1 is power down, set to 0 to operate. | ||
772 | */ | ||
773 | cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN); /* pwr up, reset */ | ||
774 | mdelay(1); /* Marvell says 1ms will do it */ | ||
775 | cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C0); | ||
776 | mdelay(1); /* Enough? */ | ||
777 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
778 | } | ||
779 | |||
780 | static void cafe_ctlr_power_down(struct cafe_camera *cam) | ||
781 | { | ||
782 | unsigned long flags; | ||
783 | |||
784 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
785 | cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C1); | ||
786 | cafe_reg_set_bit(cam, REG_CTRL1, C1_PWRDWN); | ||
787 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
788 | } | ||
789 | |||
790 | /* -------------------------------------------------------------------- */ | ||
791 | /* | ||
792 | * Communications with the sensor. | ||
793 | */ | ||
794 | |||
795 | static int __cafe_cam_cmd(struct cafe_camera *cam, int cmd, void *arg) | ||
796 | { | ||
797 | struct i2c_client *sc = cam->sensor; | ||
798 | int ret; | ||
799 | |||
800 | if (sc == NULL || sc->driver == NULL || sc->driver->command == NULL) | ||
801 | return -EINVAL; | ||
802 | ret = sc->driver->command(sc, cmd, arg); | ||
803 | if (ret == -EPERM) /* Unsupported command */ | ||
804 | return 0; | ||
805 | return ret; | ||
806 | } | ||
807 | |||
808 | static int __cafe_cam_reset(struct cafe_camera *cam) | ||
809 | { | ||
810 | int zero = 0; | ||
811 | return __cafe_cam_cmd(cam, VIDIOC_INT_RESET, &zero); | ||
812 | } | ||
813 | |||
814 | /* | ||
815 | * We have found the sensor on the i2c. Let's try to have a | ||
816 | * conversation. | ||
817 | */ | ||
818 | static int cafe_cam_init(struct cafe_camera *cam) | ||
819 | { | ||
820 | int ret; | ||
821 | |||
822 | mutex_lock(&cam->s_mutex); | ||
823 | if (cam->state != S_NOTREADY) | ||
824 | cam_warn(cam, "Cam init with device in funky state %d", | ||
825 | cam->state); | ||
826 | ret = __cafe_cam_reset(cam); | ||
827 | if (ret) | ||
828 | goto out; | ||
829 | ret = __cafe_cam_cmd(cam, VIDIOC_INT_G_CHIP_IDENT, &cam->sensor_type); | ||
830 | if (ret) | ||
831 | goto out; | ||
832 | // if (cam->sensor->addr != OV7xx0_SID) { | ||
833 | if (cam->sensor_type != V4L2_IDENT_OV7670) { | ||
834 | cam_err(cam, "Unsupported sensor type %d", cam->sensor->addr); | ||
835 | ret = -EINVAL; | ||
836 | goto out; | ||
837 | } | ||
838 | /* Get/set parameters? */ | ||
839 | ret = 0; | ||
840 | cam->state = S_IDLE; | ||
841 | out: | ||
842 | mutex_unlock(&cam->s_mutex); | ||
843 | return ret; | ||
844 | } | ||
845 | |||
846 | /* | ||
847 | * Configure the sensor to match the parameters we have. Caller should | ||
848 | * hold s_mutex | ||
849 | */ | ||
850 | static int cafe_cam_set_flip(struct cafe_camera *cam) | ||
851 | { | ||
852 | struct v4l2_control ctrl; | ||
853 | |||
854 | memset(&ctrl, 0, sizeof(ctrl)); | ||
855 | ctrl.id = V4L2_CID_VFLIP; | ||
856 | ctrl.value = flip; | ||
857 | return __cafe_cam_cmd(cam, VIDIOC_S_CTRL, &ctrl); | ||
858 | } | ||
859 | |||
860 | |||
861 | static int cafe_cam_configure(struct cafe_camera *cam) | ||
862 | { | ||
863 | struct v4l2_format fmt; | ||
864 | int ret, zero = 0; | ||
865 | |||
866 | if (cam->state != S_IDLE) | ||
867 | return -EINVAL; | ||
868 | fmt.fmt.pix = cam->pix_format; | ||
869 | ret = __cafe_cam_cmd(cam, VIDIOC_INT_INIT, &zero); | ||
870 | if (ret == 0) | ||
871 | ret = __cafe_cam_cmd(cam, VIDIOC_S_FMT, &fmt); | ||
872 | /* | ||
873 | * OV7670 does weird things if flip is set *before* format... | ||
874 | */ | ||
875 | ret += cafe_cam_set_flip(cam); | ||
876 | return ret; | ||
877 | } | ||
878 | |||
879 | /* -------------------------------------------------------------------- */ | ||
880 | /* | ||
881 | * DMA buffer management. These functions need s_mutex held. | ||
882 | */ | ||
883 | |||
884 | /* FIXME: this is inefficient as hell, since dma_alloc_coherent just | ||
885 | * does a get_free_pages() call, and we waste a good chunk of an orderN | ||
886 | * allocation. Should try to allocate the whole set in one chunk. | ||
887 | */ | ||
888 | static int cafe_alloc_dma_bufs(struct cafe_camera *cam, int loadtime) | ||
889 | { | ||
890 | int i; | ||
891 | |||
892 | cafe_set_config_needed(cam, 1); | ||
893 | if (loadtime) | ||
894 | cam->dma_buf_size = dma_buf_size; | ||
895 | else | ||
896 | cam->dma_buf_size = cam->pix_format.sizeimage; | ||
897 | if (n_dma_bufs > 3) | ||
898 | n_dma_bufs = 3; | ||
899 | |||
900 | cam->nbufs = 0; | ||
901 | for (i = 0; i < n_dma_bufs; i++) { | ||
902 | cam->dma_bufs[i] = dma_alloc_coherent(&cam->pdev->dev, | ||
903 | cam->dma_buf_size, cam->dma_handles + i, | ||
904 | GFP_KERNEL); | ||
905 | if (cam->dma_bufs[i] == NULL) { | ||
906 | cam_warn(cam, "Failed to allocate DMA buffer\n"); | ||
907 | break; | ||
908 | } | ||
909 | /* For debug, remove eventually */ | ||
910 | memset(cam->dma_bufs[i], 0xcc, cam->dma_buf_size); | ||
911 | (cam->nbufs)++; | ||
912 | } | ||
913 | |||
914 | switch (cam->nbufs) { | ||
915 | case 1: | ||
916 | dma_free_coherent(&cam->pdev->dev, cam->dma_buf_size, | ||
917 | cam->dma_bufs[0], cam->dma_handles[0]); | ||
918 | cam->nbufs = 0; | ||
919 | case 0: | ||
920 | cam_err(cam, "Insufficient DMA buffers, cannot operate\n"); | ||
921 | return -ENOMEM; | ||
922 | |||
923 | case 2: | ||
924 | if (n_dma_bufs > 2) | ||
925 | cam_warn(cam, "Will limp along with only 2 buffers\n"); | ||
926 | break; | ||
927 | } | ||
928 | return 0; | ||
929 | } | ||
930 | |||
931 | static void cafe_free_dma_bufs(struct cafe_camera *cam) | ||
932 | { | ||
933 | int i; | ||
934 | |||
935 | for (i = 0; i < cam->nbufs; i++) { | ||
936 | dma_free_coherent(&cam->pdev->dev, cam->dma_buf_size, | ||
937 | cam->dma_bufs[i], cam->dma_handles[i]); | ||
938 | cam->dma_bufs[i] = NULL; | ||
939 | } | ||
940 | cam->nbufs = 0; | ||
941 | } | ||
942 | |||
943 | |||
944 | |||
945 | |||
946 | |||
947 | /* ----------------------------------------------------------------------- */ | ||
948 | /* | ||
949 | * Here starts the V4L2 interface code. | ||
950 | */ | ||
951 | |||
952 | /* | ||
953 | * Read an image from the device. | ||
954 | */ | ||
955 | static ssize_t cafe_deliver_buffer(struct cafe_camera *cam, | ||
956 | char __user *buffer, size_t len, loff_t *pos) | ||
957 | { | ||
958 | int bufno; | ||
959 | unsigned long flags; | ||
960 | |||
961 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
962 | if (cam->next_buf < 0) { | ||
963 | cam_err(cam, "deliver_buffer: No next buffer\n"); | ||
964 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
965 | return -EIO; | ||
966 | } | ||
967 | bufno = cam->next_buf; | ||
968 | clear_bit(bufno, &cam->flags); | ||
969 | if (++(cam->next_buf) >= cam->nbufs) | ||
970 | cam->next_buf = 0; | ||
971 | if (! test_bit(cam->next_buf, &cam->flags)) | ||
972 | cam->next_buf = -1; | ||
973 | cam->specframes = 0; | ||
974 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
975 | |||
976 | if (len > cam->pix_format.sizeimage) | ||
977 | len = cam->pix_format.sizeimage; | ||
978 | if (copy_to_user(buffer, cam->dma_bufs[bufno], len)) | ||
979 | return -EFAULT; | ||
980 | (*pos) += len; | ||
981 | return len; | ||
982 | } | ||
983 | |||
984 | /* | ||
985 | * Get everything ready, and start grabbing frames. | ||
986 | */ | ||
987 | static int cafe_read_setup(struct cafe_camera *cam, enum cafe_state state) | ||
988 | { | ||
989 | int ret; | ||
990 | unsigned long flags; | ||
991 | |||
992 | /* | ||
993 | * Configuration. If we still don't have DMA buffers, | ||
994 | * make one last, desperate attempt. | ||
995 | */ | ||
996 | if (cam->nbufs == 0) | ||
997 | if (cafe_alloc_dma_bufs(cam, 0)) | ||
998 | return -ENOMEM; | ||
999 | |||
1000 | if (cafe_needs_config(cam)) { | ||
1001 | cafe_cam_configure(cam); | ||
1002 | ret = cafe_ctlr_configure(cam); | ||
1003 | if (ret) | ||
1004 | return ret; | ||
1005 | } | ||
1006 | |||
1007 | /* | ||
1008 | * Turn it loose. | ||
1009 | */ | ||
1010 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
1011 | cafe_reset_buffers(cam); | ||
1012 | cafe_ctlr_irq_enable(cam); | ||
1013 | cam->state = state; | ||
1014 | cafe_ctlr_start(cam); | ||
1015 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
1016 | return 0; | ||
1017 | } | ||
1018 | |||
1019 | |||
1020 | static ssize_t cafe_v4l_read(struct file *filp, | ||
1021 | char __user *buffer, size_t len, loff_t *pos) | ||
1022 | { | ||
1023 | struct cafe_camera *cam = filp->private_data; | ||
1024 | int ret; | ||
1025 | |||
1026 | /* | ||
1027 | * Perhaps we're in speculative read mode and already | ||
1028 | * have data? | ||
1029 | */ | ||
1030 | mutex_lock(&cam->s_mutex); | ||
1031 | if (cam->state == S_SPECREAD) { | ||
1032 | if (cam->next_buf >= 0) { | ||
1033 | ret = cafe_deliver_buffer(cam, buffer, len, pos); | ||
1034 | if (ret != 0) | ||
1035 | goto out_unlock; | ||
1036 | } | ||
1037 | } else if (cam->state == S_FLAKED || cam->state == S_NOTREADY) { | ||
1038 | ret = -EIO; | ||
1039 | goto out_unlock; | ||
1040 | } else if (cam->state != S_IDLE) { | ||
1041 | ret = -EBUSY; | ||
1042 | goto out_unlock; | ||
1043 | } | ||
1044 | |||
1045 | /* | ||
1046 | * v4l2: multiple processes can open the device, but only | ||
1047 | * one gets to grab data from it. | ||
1048 | */ | ||
1049 | if (cam->owner && cam->owner != filp) { | ||
1050 | ret = -EBUSY; | ||
1051 | goto out_unlock; | ||
1052 | } | ||
1053 | cam->owner = filp; | ||
1054 | |||
1055 | /* | ||
1056 | * Do setup if need be. | ||
1057 | */ | ||
1058 | if (cam->state != S_SPECREAD) { | ||
1059 | ret = cafe_read_setup(cam, S_SINGLEREAD); | ||
1060 | if (ret) | ||
1061 | goto out_unlock; | ||
1062 | } | ||
1063 | /* | ||
1064 | * Wait for something to happen. This should probably | ||
1065 | * be interruptible (FIXME). | ||
1066 | */ | ||
1067 | wait_event_timeout(cam->iowait, cam->next_buf >= 0, HZ); | ||
1068 | if (cam->next_buf < 0) { | ||
1069 | cam_err(cam, "read() operation timed out\n"); | ||
1070 | cafe_ctlr_stop_dma(cam); | ||
1071 | ret = -EIO; | ||
1072 | goto out_unlock; | ||
1073 | } | ||
1074 | /* | ||
1075 | * Give them their data and we should be done. | ||
1076 | */ | ||
1077 | ret = cafe_deliver_buffer(cam, buffer, len, pos); | ||
1078 | |||
1079 | out_unlock: | ||
1080 | mutex_unlock(&cam->s_mutex); | ||
1081 | return ret; | ||
1082 | } | ||
1083 | |||
1084 | |||
1085 | |||
1086 | |||
1087 | |||
1088 | |||
1089 | |||
1090 | |||
1091 | /* | ||
1092 | * Streaming I/O support. | ||
1093 | */ | ||
1094 | |||
1095 | |||
1096 | |||
1097 | static int cafe_vidioc_streamon(struct file *filp, void *priv, | ||
1098 | enum v4l2_buf_type type) | ||
1099 | { | ||
1100 | struct cafe_camera *cam = filp->private_data; | ||
1101 | int ret = -EINVAL; | ||
1102 | |||
1103 | if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1104 | goto out; | ||
1105 | mutex_lock(&cam->s_mutex); | ||
1106 | if (cam->state != S_IDLE || cam->n_sbufs == 0) | ||
1107 | goto out_unlock; | ||
1108 | |||
1109 | cam->sequence = 0; | ||
1110 | ret = cafe_read_setup(cam, S_STREAMING); | ||
1111 | |||
1112 | out_unlock: | ||
1113 | mutex_unlock(&cam->s_mutex); | ||
1114 | out: | ||
1115 | return ret; | ||
1116 | } | ||
1117 | |||
1118 | |||
1119 | static int cafe_vidioc_streamoff(struct file *filp, void *priv, | ||
1120 | enum v4l2_buf_type type) | ||
1121 | { | ||
1122 | struct cafe_camera *cam = filp->private_data; | ||
1123 | int ret = -EINVAL; | ||
1124 | |||
1125 | if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1126 | goto out; | ||
1127 | mutex_lock(&cam->s_mutex); | ||
1128 | if (cam->state != S_STREAMING) | ||
1129 | goto out_unlock; | ||
1130 | |||
1131 | cafe_ctlr_stop_dma(cam); | ||
1132 | ret = 0; | ||
1133 | |||
1134 | out_unlock: | ||
1135 | mutex_unlock(&cam->s_mutex); | ||
1136 | out: | ||
1137 | return ret; | ||
1138 | } | ||
1139 | |||
1140 | |||
1141 | |||
1142 | static int cafe_setup_siobuf(struct cafe_camera *cam, int index) | ||
1143 | { | ||
1144 | struct cafe_sio_buffer *buf = cam->sb_bufs + index; | ||
1145 | |||
1146 | INIT_LIST_HEAD(&buf->list); | ||
1147 | buf->v4lbuf.length = PAGE_ALIGN(cam->pix_format.sizeimage); | ||
1148 | buf->buffer = vmalloc_user(buf->v4lbuf.length); | ||
1149 | if (buf->buffer == NULL) | ||
1150 | return -ENOMEM; | ||
1151 | buf->mapcount = 0; | ||
1152 | buf->cam = cam; | ||
1153 | |||
1154 | buf->v4lbuf.index = index; | ||
1155 | buf->v4lbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1156 | buf->v4lbuf.field = V4L2_FIELD_NONE; | ||
1157 | buf->v4lbuf.memory = V4L2_MEMORY_MMAP; | ||
1158 | /* | ||
1159 | * Offset: must be 32-bit even on a 64-bit system. video-buf | ||
1160 | * just uses the length times the index, but the spec warns | ||
1161 | * against doing just that - vma merging problems. So we | ||
1162 | * leave a gap between each pair of buffers. | ||
1163 | */ | ||
1164 | buf->v4lbuf.m.offset = 2*index*buf->v4lbuf.length; | ||
1165 | return 0; | ||
1166 | } | ||
1167 | |||
1168 | static int cafe_free_sio_buffers(struct cafe_camera *cam) | ||
1169 | { | ||
1170 | int i; | ||
1171 | |||
1172 | /* | ||
1173 | * If any buffers are mapped, we cannot free them at all. | ||
1174 | */ | ||
1175 | for (i = 0; i < cam->n_sbufs; i++) | ||
1176 | if (cam->sb_bufs[i].mapcount > 0) | ||
1177 | return -EBUSY; | ||
1178 | /* | ||
1179 | * OK, let's do it. | ||
1180 | */ | ||
1181 | for (i = 0; i < cam->n_sbufs; i++) | ||
1182 | vfree(cam->sb_bufs[i].buffer); | ||
1183 | cam->n_sbufs = 0; | ||
1184 | kfree(cam->sb_bufs); | ||
1185 | cam->sb_bufs = NULL; | ||
1186 | INIT_LIST_HEAD(&cam->sb_avail); | ||
1187 | INIT_LIST_HEAD(&cam->sb_full); | ||
1188 | return 0; | ||
1189 | } | ||
1190 | |||
1191 | |||
1192 | |||
1193 | static int cafe_vidioc_reqbufs(struct file *filp, void *priv, | ||
1194 | struct v4l2_requestbuffers *req) | ||
1195 | { | ||
1196 | struct cafe_camera *cam = filp->private_data; | ||
1197 | int ret; | ||
1198 | |||
1199 | /* | ||
1200 | * Make sure it's something we can do. User pointers could be | ||
1201 | * implemented without great pain, but that's not been done yet. | ||
1202 | */ | ||
1203 | if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1204 | return -EINVAL; | ||
1205 | if (req->memory != V4L2_MEMORY_MMAP) | ||
1206 | return -EINVAL; | ||
1207 | /* | ||
1208 | * If they ask for zero buffers, they really want us to stop streaming | ||
1209 | * (if it's happening) and free everything. Should we check owner? | ||
1210 | */ | ||
1211 | mutex_lock(&cam->s_mutex); | ||
1212 | if (req->count == 0) { | ||
1213 | if (cam->state == S_STREAMING) | ||
1214 | cafe_ctlr_stop_dma(cam); | ||
1215 | ret = cafe_free_sio_buffers (cam); | ||
1216 | goto out; | ||
1217 | } | ||
1218 | /* | ||
1219 | * Device needs to be idle and working. We *could* try to do the | ||
1220 | * right thing in S_SPECREAD by shutting things down, but it | ||
1221 | * probably doesn't matter. | ||
1222 | */ | ||
1223 | if (cam->state != S_IDLE || (cam->owner && cam->owner != filp)) { | ||
1224 | ret = -EBUSY; | ||
1225 | goto out; | ||
1226 | } | ||
1227 | cam->owner = filp; | ||
1228 | |||
1229 | if (req->count < min_buffers) | ||
1230 | req->count = min_buffers; | ||
1231 | else if (req->count > max_buffers) | ||
1232 | req->count = max_buffers; | ||
1233 | if (cam->n_sbufs > 0) { | ||
1234 | ret = cafe_free_sio_buffers(cam); | ||
1235 | if (ret) | ||
1236 | goto out; | ||
1237 | } | ||
1238 | |||
1239 | cam->sb_bufs = kzalloc(req->count*sizeof(struct cafe_sio_buffer), | ||
1240 | GFP_KERNEL); | ||
1241 | if (cam->sb_bufs == NULL) { | ||
1242 | ret = -ENOMEM; | ||
1243 | goto out; | ||
1244 | } | ||
1245 | for (cam->n_sbufs = 0; cam->n_sbufs < req->count; (cam->n_sbufs++)) { | ||
1246 | ret = cafe_setup_siobuf(cam, cam->n_sbufs); | ||
1247 | if (ret) | ||
1248 | break; | ||
1249 | } | ||
1250 | |||
1251 | if (cam->n_sbufs == 0) /* no luck at all - ret already set */ | ||
1252 | kfree(cam->sb_bufs); | ||
1253 | else | ||
1254 | ret = 0; | ||
1255 | req->count = cam->n_sbufs; /* In case of partial success */ | ||
1256 | |||
1257 | out: | ||
1258 | mutex_unlock(&cam->s_mutex); | ||
1259 | return ret; | ||
1260 | } | ||
1261 | |||
1262 | |||
1263 | static int cafe_vidioc_querybuf(struct file *filp, void *priv, | ||
1264 | struct v4l2_buffer *buf) | ||
1265 | { | ||
1266 | struct cafe_camera *cam = filp->private_data; | ||
1267 | int ret = -EINVAL; | ||
1268 | |||
1269 | mutex_lock(&cam->s_mutex); | ||
1270 | if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1271 | goto out; | ||
1272 | if (buf->index < 0 || buf->index >= cam->n_sbufs) | ||
1273 | goto out; | ||
1274 | *buf = cam->sb_bufs[buf->index].v4lbuf; | ||
1275 | ret = 0; | ||
1276 | out: | ||
1277 | mutex_unlock(&cam->s_mutex); | ||
1278 | return ret; | ||
1279 | } | ||
1280 | |||
1281 | static int cafe_vidioc_qbuf(struct file *filp, void *priv, | ||
1282 | struct v4l2_buffer *buf) | ||
1283 | { | ||
1284 | struct cafe_camera *cam = filp->private_data; | ||
1285 | struct cafe_sio_buffer *sbuf; | ||
1286 | int ret = -EINVAL; | ||
1287 | unsigned long flags; | ||
1288 | |||
1289 | mutex_lock(&cam->s_mutex); | ||
1290 | if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1291 | goto out; | ||
1292 | if (buf->index < 0 || buf->index >= cam->n_sbufs) | ||
1293 | goto out; | ||
1294 | sbuf = cam->sb_bufs + buf->index; | ||
1295 | if (sbuf->v4lbuf.flags & V4L2_BUF_FLAG_QUEUED) { | ||
1296 | ret = 0; /* Already queued?? */ | ||
1297 | goto out; | ||
1298 | } | ||
1299 | if (sbuf->v4lbuf.flags & V4L2_BUF_FLAG_DONE) { | ||
1300 | /* Spec doesn't say anything, seems appropriate tho */ | ||
1301 | ret = -EBUSY; | ||
1302 | goto out; | ||
1303 | } | ||
1304 | sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_QUEUED; | ||
1305 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
1306 | list_add(&sbuf->list, &cam->sb_avail); | ||
1307 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
1308 | ret = 0; | ||
1309 | out: | ||
1310 | mutex_unlock(&cam->s_mutex); | ||
1311 | return ret; | ||
1312 | } | ||
1313 | |||
1314 | static int cafe_vidioc_dqbuf(struct file *filp, void *priv, | ||
1315 | struct v4l2_buffer *buf) | ||
1316 | { | ||
1317 | struct cafe_camera *cam = filp->private_data; | ||
1318 | struct cafe_sio_buffer *sbuf; | ||
1319 | int ret = -EINVAL; | ||
1320 | unsigned long flags; | ||
1321 | |||
1322 | mutex_lock(&cam->s_mutex); | ||
1323 | if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1324 | goto out_unlock; | ||
1325 | if (cam->state != S_STREAMING) | ||
1326 | goto out_unlock; | ||
1327 | if (list_empty(&cam->sb_full) && filp->f_flags & O_NONBLOCK) { | ||
1328 | ret = -EAGAIN; | ||
1329 | goto out_unlock; | ||
1330 | } | ||
1331 | |||
1332 | while (list_empty(&cam->sb_full) && cam->state == S_STREAMING) { | ||
1333 | mutex_unlock(&cam->s_mutex); | ||
1334 | if (wait_event_interruptible(cam->iowait, | ||
1335 | !list_empty(&cam->sb_full))) { | ||
1336 | ret = -ERESTARTSYS; | ||
1337 | goto out; | ||
1338 | } | ||
1339 | mutex_lock(&cam->s_mutex); | ||
1340 | } | ||
1341 | |||
1342 | if (cam->state != S_STREAMING) | ||
1343 | ret = -EINTR; | ||
1344 | else { | ||
1345 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
1346 | /* Should probably recheck !list_empty() here */ | ||
1347 | sbuf = list_entry(cam->sb_full.next, | ||
1348 | struct cafe_sio_buffer, list); | ||
1349 | list_del_init(&sbuf->list); | ||
1350 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
1351 | sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_DONE; | ||
1352 | *buf = sbuf->v4lbuf; | ||
1353 | ret = 0; | ||
1354 | } | ||
1355 | |||
1356 | out_unlock: | ||
1357 | mutex_unlock(&cam->s_mutex); | ||
1358 | out: | ||
1359 | return ret; | ||
1360 | } | ||
1361 | |||
1362 | |||
1363 | |||
1364 | static void cafe_v4l_vm_open(struct vm_area_struct *vma) | ||
1365 | { | ||
1366 | struct cafe_sio_buffer *sbuf = vma->vm_private_data; | ||
1367 | /* | ||
1368 | * Locking: done under mmap_sem, so we don't need to | ||
1369 | * go back to the camera lock here. | ||
1370 | */ | ||
1371 | sbuf->mapcount++; | ||
1372 | } | ||
1373 | |||
1374 | |||
1375 | static void cafe_v4l_vm_close(struct vm_area_struct *vma) | ||
1376 | { | ||
1377 | struct cafe_sio_buffer *sbuf = vma->vm_private_data; | ||
1378 | |||
1379 | mutex_lock(&sbuf->cam->s_mutex); | ||
1380 | sbuf->mapcount--; | ||
1381 | /* Docs say we should stop I/O too... */ | ||
1382 | if (sbuf->mapcount == 0) | ||
1383 | sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_MAPPED; | ||
1384 | mutex_unlock(&sbuf->cam->s_mutex); | ||
1385 | } | ||
1386 | |||
1387 | static struct vm_operations_struct cafe_v4l_vm_ops = { | ||
1388 | .open = cafe_v4l_vm_open, | ||
1389 | .close = cafe_v4l_vm_close | ||
1390 | }; | ||
1391 | |||
1392 | |||
1393 | static int cafe_v4l_mmap(struct file *filp, struct vm_area_struct *vma) | ||
1394 | { | ||
1395 | struct cafe_camera *cam = filp->private_data; | ||
1396 | unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; | ||
1397 | int ret = -EINVAL; | ||
1398 | int i; | ||
1399 | struct cafe_sio_buffer *sbuf = NULL; | ||
1400 | |||
1401 | if (! (vma->vm_flags & VM_WRITE) || ! (vma->vm_flags & VM_SHARED)) | ||
1402 | return -EINVAL; | ||
1403 | /* | ||
1404 | * Find the buffer they are looking for. | ||
1405 | */ | ||
1406 | mutex_lock(&cam->s_mutex); | ||
1407 | for (i = 0; i < cam->n_sbufs; i++) | ||
1408 | if (cam->sb_bufs[i].v4lbuf.m.offset == offset) { | ||
1409 | sbuf = cam->sb_bufs + i; | ||
1410 | break; | ||
1411 | } | ||
1412 | if (sbuf == NULL) | ||
1413 | goto out; | ||
1414 | |||
1415 | ret = remap_vmalloc_range(vma, sbuf->buffer, 0); | ||
1416 | if (ret) | ||
1417 | goto out; | ||
1418 | vma->vm_flags |= VM_DONTEXPAND; | ||
1419 | vma->vm_private_data = sbuf; | ||
1420 | vma->vm_ops = &cafe_v4l_vm_ops; | ||
1421 | sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_MAPPED; | ||
1422 | cafe_v4l_vm_open(vma); | ||
1423 | ret = 0; | ||
1424 | out: | ||
1425 | mutex_unlock(&cam->s_mutex); | ||
1426 | return ret; | ||
1427 | } | ||
1428 | |||
1429 | |||
1430 | |||
1431 | static int cafe_v4l_open(struct inode *inode, struct file *filp) | ||
1432 | { | ||
1433 | struct cafe_camera *cam; | ||
1434 | |||
1435 | cam = cafe_find_dev(iminor(inode)); | ||
1436 | if (cam == NULL) | ||
1437 | return -ENODEV; | ||
1438 | filp->private_data = cam; | ||
1439 | |||
1440 | mutex_lock(&cam->s_mutex); | ||
1441 | if (cam->users == 0) { | ||
1442 | cafe_ctlr_power_up(cam); | ||
1443 | __cafe_cam_reset(cam); | ||
1444 | cafe_set_config_needed(cam, 1); | ||
1445 | /* FIXME make sure this is complete */ | ||
1446 | } | ||
1447 | (cam->users)++; | ||
1448 | mutex_unlock(&cam->s_mutex); | ||
1449 | return 0; | ||
1450 | } | ||
1451 | |||
1452 | |||
1453 | static int cafe_v4l_release(struct inode *inode, struct file *filp) | ||
1454 | { | ||
1455 | struct cafe_camera *cam = filp->private_data; | ||
1456 | |||
1457 | mutex_lock(&cam->s_mutex); | ||
1458 | (cam->users)--; | ||
1459 | if (filp == cam->owner) { | ||
1460 | cafe_ctlr_stop_dma(cam); | ||
1461 | cafe_free_sio_buffers(cam); | ||
1462 | cam->owner = NULL; | ||
1463 | } | ||
1464 | if (cam->users == 0) { | ||
1465 | cafe_ctlr_power_down(cam); | ||
1466 | if (! alloc_bufs_at_load) | ||
1467 | cafe_free_dma_bufs(cam); | ||
1468 | } | ||
1469 | mutex_unlock(&cam->s_mutex); | ||
1470 | return 0; | ||
1471 | } | ||
1472 | |||
1473 | |||
1474 | |||
1475 | static unsigned int cafe_v4l_poll(struct file *filp, | ||
1476 | struct poll_table_struct *pt) | ||
1477 | { | ||
1478 | struct cafe_camera *cam = filp->private_data; | ||
1479 | |||
1480 | poll_wait(filp, &cam->iowait, pt); | ||
1481 | if (cam->next_buf >= 0) | ||
1482 | return POLLIN | POLLRDNORM; | ||
1483 | return 0; | ||
1484 | } | ||
1485 | |||
1486 | |||
1487 | |||
1488 | static int cafe_vidioc_queryctrl(struct file *filp, void *priv, | ||
1489 | struct v4l2_queryctrl *qc) | ||
1490 | { | ||
1491 | struct cafe_camera *cam = filp->private_data; | ||
1492 | int ret; | ||
1493 | |||
1494 | mutex_lock(&cam->s_mutex); | ||
1495 | ret = __cafe_cam_cmd(cam, VIDIOC_QUERYCTRL, qc); | ||
1496 | mutex_unlock(&cam->s_mutex); | ||
1497 | return ret; | ||
1498 | } | ||
1499 | |||
1500 | |||
1501 | static int cafe_vidioc_g_ctrl(struct file *filp, void *priv, | ||
1502 | struct v4l2_control *ctrl) | ||
1503 | { | ||
1504 | struct cafe_camera *cam = filp->private_data; | ||
1505 | int ret; | ||
1506 | |||
1507 | mutex_lock(&cam->s_mutex); | ||
1508 | ret = __cafe_cam_cmd(cam, VIDIOC_G_CTRL, ctrl); | ||
1509 | mutex_unlock(&cam->s_mutex); | ||
1510 | return ret; | ||
1511 | } | ||
1512 | |||
1513 | |||
1514 | static int cafe_vidioc_s_ctrl(struct file *filp, void *priv, | ||
1515 | struct v4l2_control *ctrl) | ||
1516 | { | ||
1517 | struct cafe_camera *cam = filp->private_data; | ||
1518 | int ret; | ||
1519 | |||
1520 | mutex_lock(&cam->s_mutex); | ||
1521 | ret = __cafe_cam_cmd(cam, VIDIOC_S_CTRL, ctrl); | ||
1522 | mutex_unlock(&cam->s_mutex); | ||
1523 | return ret; | ||
1524 | } | ||
1525 | |||
1526 | |||
1527 | |||
1528 | |||
1529 | |||
1530 | static int cafe_vidioc_querycap(struct file *file, void *priv, | ||
1531 | struct v4l2_capability *cap) | ||
1532 | { | ||
1533 | strcpy(cap->driver, "cafe_ccic"); | ||
1534 | strcpy(cap->card, "cafe_ccic"); | ||
1535 | cap->version = CAFE_VERSION; | ||
1536 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | | ||
1537 | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; | ||
1538 | return 0; | ||
1539 | } | ||
1540 | |||
1541 | |||
1542 | /* | ||
1543 | * The default format we use until somebody says otherwise. | ||
1544 | */ | ||
1545 | static struct v4l2_pix_format cafe_def_pix_format = { | ||
1546 | .width = VGA_WIDTH, | ||
1547 | .height = VGA_HEIGHT, | ||
1548 | .pixelformat = V4L2_PIX_FMT_YUYV, | ||
1549 | .field = V4L2_FIELD_NONE, | ||
1550 | .bytesperline = VGA_WIDTH*2, | ||
1551 | .sizeimage = VGA_WIDTH*VGA_HEIGHT*2, | ||
1552 | }; | ||
1553 | |||
1554 | static int cafe_vidioc_enum_fmt_cap(struct file *filp, | ||
1555 | void *priv, struct v4l2_fmtdesc *fmt) | ||
1556 | { | ||
1557 | struct cafe_camera *cam = priv; | ||
1558 | int ret; | ||
1559 | |||
1560 | if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1561 | return -EINVAL; | ||
1562 | mutex_lock(&cam->s_mutex); | ||
1563 | ret = __cafe_cam_cmd(cam, VIDIOC_ENUM_FMT, fmt); | ||
1564 | mutex_unlock(&cam->s_mutex); | ||
1565 | return ret; | ||
1566 | } | ||
1567 | |||
1568 | |||
1569 | static int cafe_vidioc_try_fmt_cap (struct file *filp, void *priv, | ||
1570 | struct v4l2_format *fmt) | ||
1571 | { | ||
1572 | struct cafe_camera *cam = priv; | ||
1573 | int ret; | ||
1574 | |||
1575 | mutex_lock(&cam->s_mutex); | ||
1576 | ret = __cafe_cam_cmd(cam, VIDIOC_TRY_FMT, fmt); | ||
1577 | mutex_unlock(&cam->s_mutex); | ||
1578 | return ret; | ||
1579 | } | ||
1580 | |||
1581 | static int cafe_vidioc_s_fmt_cap(struct file *filp, void *priv, | ||
1582 | struct v4l2_format *fmt) | ||
1583 | { | ||
1584 | struct cafe_camera *cam = priv; | ||
1585 | int ret; | ||
1586 | |||
1587 | /* | ||
1588 | * Can't do anything if the device is not idle | ||
1589 | * Also can't if there are streaming buffers in place. | ||
1590 | */ | ||
1591 | if (cam->state != S_IDLE || cam->n_sbufs > 0) | ||
1592 | return -EBUSY; | ||
1593 | /* | ||
1594 | * See if the formatting works in principle. | ||
1595 | */ | ||
1596 | ret = cafe_vidioc_try_fmt_cap(filp, priv, fmt); | ||
1597 | if (ret) | ||
1598 | return ret; | ||
1599 | /* | ||
1600 | * Now we start to change things for real, so let's do it | ||
1601 | * under lock. | ||
1602 | */ | ||
1603 | mutex_lock(&cam->s_mutex); | ||
1604 | cam->pix_format = fmt->fmt.pix; | ||
1605 | /* | ||
1606 | * Make sure we have appropriate DMA buffers. | ||
1607 | */ | ||
1608 | ret = -ENOMEM; | ||
1609 | if (cam->nbufs > 0 && cam->dma_buf_size < cam->pix_format.sizeimage) | ||
1610 | cafe_free_dma_bufs(cam); | ||
1611 | if (cam->nbufs == 0) { | ||
1612 | if (cafe_alloc_dma_bufs(cam, 0)) | ||
1613 | goto out; | ||
1614 | } | ||
1615 | /* | ||
1616 | * It looks like this might work, so let's program the sensor. | ||
1617 | */ | ||
1618 | ret = cafe_cam_configure(cam); | ||
1619 | if (! ret) | ||
1620 | ret = cafe_ctlr_configure(cam); | ||
1621 | out: | ||
1622 | mutex_unlock(&cam->s_mutex); | ||
1623 | return ret; | ||
1624 | } | ||
1625 | |||
1626 | /* | ||
1627 | * Return our stored notion of how the camera is/should be configured. | ||
1628 | * The V4l2 spec wants us to be smarter, and actually get this from | ||
1629 | * the camera (and not mess with it at open time). Someday. | ||
1630 | */ | ||
1631 | static int cafe_vidioc_g_fmt_cap(struct file *filp, void *priv, | ||
1632 | struct v4l2_format *f) | ||
1633 | { | ||
1634 | struct cafe_camera *cam = priv; | ||
1635 | |||
1636 | f->fmt.pix = cam->pix_format; | ||
1637 | return 0; | ||
1638 | } | ||
1639 | |||
1640 | /* | ||
1641 | * We only have one input - the sensor - so minimize the nonsense here. | ||
1642 | */ | ||
1643 | static int cafe_vidioc_enum_input(struct file *filp, void *priv, | ||
1644 | struct v4l2_input *input) | ||
1645 | { | ||
1646 | if (input->index != 0) | ||
1647 | return -EINVAL; | ||
1648 | |||
1649 | input->type = V4L2_INPUT_TYPE_CAMERA; | ||
1650 | input->std = V4L2_STD_ALL; /* Not sure what should go here */ | ||
1651 | strcpy(input->name, "Camera"); | ||
1652 | return 0; | ||
1653 | } | ||
1654 | |||
1655 | static int cafe_vidioc_g_input(struct file *filp, void *priv, unsigned int *i) | ||
1656 | { | ||
1657 | *i = 0; | ||
1658 | return 0; | ||
1659 | } | ||
1660 | |||
1661 | static int cafe_vidioc_s_input(struct file *filp, void *priv, unsigned int i) | ||
1662 | { | ||
1663 | if (i != 0) | ||
1664 | return -EINVAL; | ||
1665 | return 0; | ||
1666 | } | ||
1667 | |||
1668 | /* from vivi.c */ | ||
1669 | static int cafe_vidioc_s_std(struct file *filp, void *priv, v4l2_std_id *a) | ||
1670 | { | ||
1671 | return 0; | ||
1672 | } | ||
1673 | |||
1674 | /* | ||
1675 | * G/S_PARM. Most of this is done by the sensor, but we are | ||
1676 | * the level which controls the number of read buffers. | ||
1677 | */ | ||
1678 | static int cafe_vidioc_g_parm(struct file *filp, void *priv, | ||
1679 | struct v4l2_streamparm *parms) | ||
1680 | { | ||
1681 | struct cafe_camera *cam = priv; | ||
1682 | int ret; | ||
1683 | |||
1684 | mutex_lock(&cam->s_mutex); | ||
1685 | ret = __cafe_cam_cmd(cam, VIDIOC_G_PARM, parms); | ||
1686 | mutex_unlock(&cam->s_mutex); | ||
1687 | parms->parm.capture.readbuffers = n_dma_bufs; | ||
1688 | return ret; | ||
1689 | } | ||
1690 | |||
1691 | static int cafe_vidioc_s_parm(struct file *filp, void *priv, | ||
1692 | struct v4l2_streamparm *parms) | ||
1693 | { | ||
1694 | struct cafe_camera *cam = priv; | ||
1695 | int ret; | ||
1696 | |||
1697 | mutex_lock(&cam->s_mutex); | ||
1698 | ret = __cafe_cam_cmd(cam, VIDIOC_S_PARM, parms); | ||
1699 | mutex_unlock(&cam->s_mutex); | ||
1700 | parms->parm.capture.readbuffers = n_dma_bufs; | ||
1701 | return ret; | ||
1702 | } | ||
1703 | |||
1704 | |||
1705 | static void cafe_v4l_dev_release(struct video_device *vd) | ||
1706 | { | ||
1707 | struct cafe_camera *cam = container_of(vd, struct cafe_camera, v4ldev); | ||
1708 | |||
1709 | kfree(cam); | ||
1710 | } | ||
1711 | |||
1712 | |||
1713 | /* | ||
1714 | * This template device holds all of those v4l2 methods; we | ||
1715 | * clone it for specific real devices. | ||
1716 | */ | ||
1717 | |||
1718 | static struct file_operations cafe_v4l_fops = { | ||
1719 | .owner = THIS_MODULE, | ||
1720 | .open = cafe_v4l_open, | ||
1721 | .release = cafe_v4l_release, | ||
1722 | .read = cafe_v4l_read, | ||
1723 | .poll = cafe_v4l_poll, | ||
1724 | .mmap = cafe_v4l_mmap, | ||
1725 | .ioctl = video_ioctl2, | ||
1726 | .llseek = no_llseek, | ||
1727 | }; | ||
1728 | |||
1729 | static struct video_device cafe_v4l_template = { | ||
1730 | .name = "cafe", | ||
1731 | .type = VFL_TYPE_GRABBER, | ||
1732 | .type2 = VID_TYPE_CAPTURE, | ||
1733 | .minor = -1, /* Get one dynamically */ | ||
1734 | .tvnorms = V4L2_STD_NTSC_M, | ||
1735 | .current_norm = V4L2_STD_NTSC_M, /* make mplayer happy */ | ||
1736 | |||
1737 | .fops = &cafe_v4l_fops, | ||
1738 | .release = cafe_v4l_dev_release, | ||
1739 | |||
1740 | .vidioc_querycap = cafe_vidioc_querycap, | ||
1741 | .vidioc_enum_fmt_cap = cafe_vidioc_enum_fmt_cap, | ||
1742 | .vidioc_try_fmt_cap = cafe_vidioc_try_fmt_cap, | ||
1743 | .vidioc_s_fmt_cap = cafe_vidioc_s_fmt_cap, | ||
1744 | .vidioc_g_fmt_cap = cafe_vidioc_g_fmt_cap, | ||
1745 | .vidioc_enum_input = cafe_vidioc_enum_input, | ||
1746 | .vidioc_g_input = cafe_vidioc_g_input, | ||
1747 | .vidioc_s_input = cafe_vidioc_s_input, | ||
1748 | .vidioc_s_std = cafe_vidioc_s_std, | ||
1749 | .vidioc_reqbufs = cafe_vidioc_reqbufs, | ||
1750 | .vidioc_querybuf = cafe_vidioc_querybuf, | ||
1751 | .vidioc_qbuf = cafe_vidioc_qbuf, | ||
1752 | .vidioc_dqbuf = cafe_vidioc_dqbuf, | ||
1753 | .vidioc_streamon = cafe_vidioc_streamon, | ||
1754 | .vidioc_streamoff = cafe_vidioc_streamoff, | ||
1755 | .vidioc_queryctrl = cafe_vidioc_queryctrl, | ||
1756 | .vidioc_g_ctrl = cafe_vidioc_g_ctrl, | ||
1757 | .vidioc_s_ctrl = cafe_vidioc_s_ctrl, | ||
1758 | .vidioc_g_parm = cafe_vidioc_g_parm, | ||
1759 | .vidioc_s_parm = cafe_vidioc_s_parm, | ||
1760 | }; | ||
1761 | |||
1762 | |||
1763 | |||
1764 | |||
1765 | |||
1766 | |||
1767 | |||
1768 | /* ---------------------------------------------------------------------- */ | ||
1769 | /* | ||
1770 | * Interrupt handler stuff | ||
1771 | */ | ||
1772 | |||
1773 | |||
1774 | |||
1775 | static void cafe_frame_tasklet(unsigned long data) | ||
1776 | { | ||
1777 | struct cafe_camera *cam = (struct cafe_camera *) data; | ||
1778 | int i; | ||
1779 | unsigned long flags; | ||
1780 | struct cafe_sio_buffer *sbuf; | ||
1781 | |||
1782 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
1783 | for (i = 0; i < cam->nbufs; i++) { | ||
1784 | int bufno = cam->next_buf; | ||
1785 | if (bufno < 0) { /* "will never happen" */ | ||
1786 | cam_err(cam, "No valid bufs in tasklet!\n"); | ||
1787 | break; | ||
1788 | } | ||
1789 | if (++(cam->next_buf) >= cam->nbufs) | ||
1790 | cam->next_buf = 0; | ||
1791 | if (! test_bit(bufno, &cam->flags)) | ||
1792 | continue; | ||
1793 | if (list_empty(&cam->sb_avail)) | ||
1794 | break; /* Leave it valid, hope for better later */ | ||
1795 | clear_bit(bufno, &cam->flags); | ||
1796 | /* | ||
1797 | * We could perhaps drop the spinlock during this | ||
1798 | * big copy. Something to consider. | ||
1799 | */ | ||
1800 | sbuf = list_entry(cam->sb_avail.next, | ||
1801 | struct cafe_sio_buffer, list); | ||
1802 | memcpy(sbuf->buffer, cam->dma_bufs[bufno], | ||
1803 | cam->pix_format.sizeimage); | ||
1804 | sbuf->v4lbuf.bytesused = cam->pix_format.sizeimage; | ||
1805 | sbuf->v4lbuf.sequence = cam->buf_seq[bufno]; | ||
1806 | sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_QUEUED; | ||
1807 | sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_DONE; | ||
1808 | list_move_tail(&sbuf->list, &cam->sb_full); | ||
1809 | } | ||
1810 | if (! list_empty(&cam->sb_full)) | ||
1811 | wake_up(&cam->iowait); | ||
1812 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
1813 | } | ||
1814 | |||
1815 | |||
1816 | |||
1817 | static void cafe_frame_complete(struct cafe_camera *cam, int frame) | ||
1818 | { | ||
1819 | /* | ||
1820 | * Basic frame housekeeping. | ||
1821 | */ | ||
1822 | if (test_bit(frame, &cam->flags) && printk_ratelimit()) | ||
1823 | cam_err(cam, "Frame overrun on %d, frames lost\n", frame); | ||
1824 | set_bit(frame, &cam->flags); | ||
1825 | clear_bit(CF_DMA_ACTIVE, &cam->flags); | ||
1826 | if (cam->next_buf < 0) | ||
1827 | cam->next_buf = frame; | ||
1828 | cam->buf_seq[frame] = ++(cam->sequence); | ||
1829 | |||
1830 | switch (cam->state) { | ||
1831 | /* | ||
1832 | * If in single read mode, try going speculative. | ||
1833 | */ | ||
1834 | case S_SINGLEREAD: | ||
1835 | cam->state = S_SPECREAD; | ||
1836 | cam->specframes = 0; | ||
1837 | wake_up(&cam->iowait); | ||
1838 | break; | ||
1839 | |||
1840 | /* | ||
1841 | * If we are already doing speculative reads, and nobody is | ||
1842 | * reading them, just stop. | ||
1843 | */ | ||
1844 | case S_SPECREAD: | ||
1845 | if (++(cam->specframes) >= cam->nbufs) { | ||
1846 | cafe_ctlr_stop(cam); | ||
1847 | cafe_ctlr_irq_disable(cam); | ||
1848 | cam->state = S_IDLE; | ||
1849 | } | ||
1850 | wake_up(&cam->iowait); | ||
1851 | break; | ||
1852 | /* | ||
1853 | * For the streaming case, we defer the real work to the | ||
1854 | * camera tasklet. | ||
1855 | * | ||
1856 | * FIXME: if the application is not consuming the buffers, | ||
1857 | * we should eventually put things on hold and restart in | ||
1858 | * vidioc_dqbuf(). | ||
1859 | */ | ||
1860 | case S_STREAMING: | ||
1861 | tasklet_schedule(&cam->s_tasklet); | ||
1862 | break; | ||
1863 | |||
1864 | default: | ||
1865 | cam_err(cam, "Frame interrupt in non-operational state\n"); | ||
1866 | break; | ||
1867 | } | ||
1868 | } | ||
1869 | |||
1870 | |||
1871 | |||
1872 | |||
1873 | static void cafe_frame_irq(struct cafe_camera *cam, unsigned int irqs) | ||
1874 | { | ||
1875 | unsigned int frame; | ||
1876 | |||
1877 | cafe_reg_write(cam, REG_IRQSTAT, FRAMEIRQS); /* Clear'em all */ | ||
1878 | /* | ||
1879 | * Handle any frame completions. There really should | ||
1880 | * not be more than one of these, or we have fallen | ||
1881 | * far behind. | ||
1882 | */ | ||
1883 | for (frame = 0; frame < cam->nbufs; frame++) | ||
1884 | if (irqs & (IRQ_EOF0 << frame)) | ||
1885 | cafe_frame_complete(cam, frame); | ||
1886 | /* | ||
1887 | * If a frame starts, note that we have DMA active. This | ||
1888 | * code assumes that we won't get multiple frame interrupts | ||
1889 | * at once; may want to rethink that. | ||
1890 | */ | ||
1891 | if (irqs & (IRQ_SOF0 | IRQ_SOF1 | IRQ_SOF2)) | ||
1892 | set_bit(CF_DMA_ACTIVE, &cam->flags); | ||
1893 | } | ||
1894 | |||
1895 | |||
1896 | |||
1897 | static irqreturn_t cafe_irq(int irq, void *data) | ||
1898 | { | ||
1899 | struct cafe_camera *cam = data; | ||
1900 | unsigned int irqs; | ||
1901 | |||
1902 | spin_lock(&cam->dev_lock); | ||
1903 | irqs = cafe_reg_read(cam, REG_IRQSTAT); | ||
1904 | if ((irqs & ALLIRQS) == 0) { | ||
1905 | spin_unlock(&cam->dev_lock); | ||
1906 | return IRQ_NONE; | ||
1907 | } | ||
1908 | if (irqs & FRAMEIRQS) | ||
1909 | cafe_frame_irq(cam, irqs); | ||
1910 | if (irqs & TWSIIRQS) { | ||
1911 | cafe_reg_write(cam, REG_IRQSTAT, TWSIIRQS); | ||
1912 | wake_up(&cam->smbus_wait); | ||
1913 | } | ||
1914 | spin_unlock(&cam->dev_lock); | ||
1915 | return IRQ_HANDLED; | ||
1916 | } | ||
1917 | |||
1918 | |||
1919 | /* -------------------------------------------------------------------------- */ | ||
1920 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
1921 | /* | ||
1922 | * Debugfs stuff. | ||
1923 | */ | ||
1924 | |||
1925 | static char cafe_debug_buf[1024]; | ||
1926 | static struct dentry *cafe_dfs_root; | ||
1927 | |||
1928 | static void cafe_dfs_setup(void) | ||
1929 | { | ||
1930 | cafe_dfs_root = debugfs_create_dir("cafe_ccic", NULL); | ||
1931 | if (IS_ERR(cafe_dfs_root)) { | ||
1932 | cafe_dfs_root = NULL; /* Never mind */ | ||
1933 | printk(KERN_NOTICE "cafe_ccic unable to set up debugfs\n"); | ||
1934 | } | ||
1935 | } | ||
1936 | |||
1937 | static void cafe_dfs_shutdown(void) | ||
1938 | { | ||
1939 | if (cafe_dfs_root) | ||
1940 | debugfs_remove(cafe_dfs_root); | ||
1941 | } | ||
1942 | |||
1943 | static int cafe_dfs_open(struct inode *inode, struct file *file) | ||
1944 | { | ||
1945 | file->private_data = inode->i_private; | ||
1946 | return 0; | ||
1947 | } | ||
1948 | |||
1949 | static ssize_t cafe_dfs_read_regs(struct file *file, | ||
1950 | char __user *buf, size_t count, loff_t *ppos) | ||
1951 | { | ||
1952 | struct cafe_camera *cam = file->private_data; | ||
1953 | char *s = cafe_debug_buf; | ||
1954 | int offset; | ||
1955 | |||
1956 | for (offset = 0; offset < 0x44; offset += 4) | ||
1957 | s += sprintf(s, "%02x: %08x\n", offset, | ||
1958 | cafe_reg_read(cam, offset)); | ||
1959 | for (offset = 0x88; offset <= 0x90; offset += 4) | ||
1960 | s += sprintf(s, "%02x: %08x\n", offset, | ||
1961 | cafe_reg_read(cam, offset)); | ||
1962 | for (offset = 0xb4; offset <= 0xbc; offset += 4) | ||
1963 | s += sprintf(s, "%02x: %08x\n", offset, | ||
1964 | cafe_reg_read(cam, offset)); | ||
1965 | for (offset = 0x3000; offset <= 0x300c; offset += 4) | ||
1966 | s += sprintf(s, "%04x: %08x\n", offset, | ||
1967 | cafe_reg_read(cam, offset)); | ||
1968 | return simple_read_from_buffer(buf, count, ppos, cafe_debug_buf, | ||
1969 | s - cafe_debug_buf); | ||
1970 | } | ||
1971 | |||
1972 | static struct file_operations cafe_dfs_reg_ops = { | ||
1973 | .owner = THIS_MODULE, | ||
1974 | .read = cafe_dfs_read_regs, | ||
1975 | .open = cafe_dfs_open | ||
1976 | }; | ||
1977 | |||
1978 | static ssize_t cafe_dfs_read_cam(struct file *file, | ||
1979 | char __user *buf, size_t count, loff_t *ppos) | ||
1980 | { | ||
1981 | struct cafe_camera *cam = file->private_data; | ||
1982 | char *s = cafe_debug_buf; | ||
1983 | int offset; | ||
1984 | |||
1985 | if (! cam->sensor) | ||
1986 | return -EINVAL; | ||
1987 | for (offset = 0x0; offset < 0x8a; offset++) | ||
1988 | { | ||
1989 | u8 v; | ||
1990 | |||
1991 | cafe_smbus_read_data(cam, cam->sensor->addr, offset, &v); | ||
1992 | s += sprintf(s, "%02x: %02x\n", offset, v); | ||
1993 | } | ||
1994 | return simple_read_from_buffer(buf, count, ppos, cafe_debug_buf, | ||
1995 | s - cafe_debug_buf); | ||
1996 | } | ||
1997 | |||
1998 | static struct file_operations cafe_dfs_cam_ops = { | ||
1999 | .owner = THIS_MODULE, | ||
2000 | .read = cafe_dfs_read_cam, | ||
2001 | .open = cafe_dfs_open | ||
2002 | }; | ||
2003 | |||
2004 | |||
2005 | |||
2006 | static void cafe_dfs_cam_setup(struct cafe_camera *cam) | ||
2007 | { | ||
2008 | char fname[40]; | ||
2009 | |||
2010 | if (!cafe_dfs_root) | ||
2011 | return; | ||
2012 | sprintf(fname, "regs-%d", cam->v4ldev.minor); | ||
2013 | cam->dfs_regs = debugfs_create_file(fname, 0444, cafe_dfs_root, | ||
2014 | cam, &cafe_dfs_reg_ops); | ||
2015 | sprintf(fname, "cam-%d", cam->v4ldev.minor); | ||
2016 | cam->dfs_cam_regs = debugfs_create_file(fname, 0444, cafe_dfs_root, | ||
2017 | cam, &cafe_dfs_cam_ops); | ||
2018 | } | ||
2019 | |||
2020 | |||
2021 | static void cafe_dfs_cam_shutdown(struct cafe_camera *cam) | ||
2022 | { | ||
2023 | if (! IS_ERR(cam->dfs_regs)) | ||
2024 | debugfs_remove(cam->dfs_regs); | ||
2025 | if (! IS_ERR(cam->dfs_cam_regs)) | ||
2026 | debugfs_remove(cam->dfs_cam_regs); | ||
2027 | } | ||
2028 | |||
2029 | #else | ||
2030 | |||
2031 | #define cafe_dfs_setup() | ||
2032 | #define cafe_dfs_shutdown() | ||
2033 | #define cafe_dfs_cam_setup(cam) | ||
2034 | #define cafe_dfs_cam_shutdown(cam) | ||
2035 | #endif /* CONFIG_VIDEO_ADV_DEBUG */ | ||
2036 | |||
2037 | |||
2038 | |||
2039 | |||
2040 | /* ------------------------------------------------------------------------*/ | ||
2041 | /* | ||
2042 | * PCI interface stuff. | ||
2043 | */ | ||
2044 | |||
2045 | static int cafe_pci_probe(struct pci_dev *pdev, | ||
2046 | const struct pci_device_id *id) | ||
2047 | { | ||
2048 | int ret; | ||
2049 | u16 classword; | ||
2050 | struct cafe_camera *cam; | ||
2051 | /* | ||
2052 | * Make sure we have a camera here - we'll get calls for | ||
2053 | * the other cafe devices as well. | ||
2054 | */ | ||
2055 | pci_read_config_word(pdev, PCI_CLASS_DEVICE, &classword); | ||
2056 | if (classword != PCI_CLASS_MULTIMEDIA_VIDEO) | ||
2057 | return -ENODEV; | ||
2058 | /* | ||
2059 | * Start putting together one of our big camera structures. | ||
2060 | */ | ||
2061 | ret = -ENOMEM; | ||
2062 | cam = kzalloc(sizeof(struct cafe_camera), GFP_KERNEL); | ||
2063 | if (cam == NULL) | ||
2064 | goto out; | ||
2065 | mutex_init(&cam->s_mutex); | ||
2066 | mutex_lock(&cam->s_mutex); | ||
2067 | spin_lock_init(&cam->dev_lock); | ||
2068 | cam->state = S_NOTREADY; | ||
2069 | cafe_set_config_needed(cam, 1); | ||
2070 | init_waitqueue_head(&cam->smbus_wait); | ||
2071 | init_waitqueue_head(&cam->iowait); | ||
2072 | cam->pdev = pdev; | ||
2073 | cam->pix_format = cafe_def_pix_format; | ||
2074 | INIT_LIST_HEAD(&cam->dev_list); | ||
2075 | INIT_LIST_HEAD(&cam->sb_avail); | ||
2076 | INIT_LIST_HEAD(&cam->sb_full); | ||
2077 | tasklet_init(&cam->s_tasklet, cafe_frame_tasklet, (unsigned long) cam); | ||
2078 | /* | ||
2079 | * Get set up on the PCI bus. | ||
2080 | */ | ||
2081 | ret = pci_enable_device(pdev); | ||
2082 | if (ret) | ||
2083 | goto out_free; | ||
2084 | pci_set_master(pdev); | ||
2085 | |||
2086 | ret = -EIO; | ||
2087 | cam->regs = pci_iomap(pdev, 0, 0); | ||
2088 | if (! cam->regs) { | ||
2089 | printk(KERN_ERR "Unable to ioremap cafe-ccic regs\n"); | ||
2090 | goto out_free; | ||
2091 | } | ||
2092 | ret = request_irq(pdev->irq, cafe_irq, IRQF_SHARED, "cafe-ccic", cam); | ||
2093 | if (ret) | ||
2094 | goto out_iounmap; | ||
2095 | cafe_ctlr_init(cam); | ||
2096 | cafe_ctlr_power_up(cam); | ||
2097 | /* | ||
2098 | * Set up I2C/SMBUS communications | ||
2099 | */ | ||
2100 | mutex_unlock(&cam->s_mutex); /* attach can deadlock */ | ||
2101 | ret = cafe_smbus_setup(cam); | ||
2102 | if (ret) | ||
2103 | goto out_freeirq; | ||
2104 | /* | ||
2105 | * Get the v4l2 setup done. | ||
2106 | */ | ||
2107 | mutex_lock(&cam->s_mutex); | ||
2108 | cam->v4ldev = cafe_v4l_template; | ||
2109 | cam->v4ldev.debug = 0; | ||
2110 | // cam->v4ldev.debug = V4L2_DEBUG_IOCTL_ARG; | ||
2111 | ret = video_register_device(&cam->v4ldev, VFL_TYPE_GRABBER, -1); | ||
2112 | if (ret) | ||
2113 | goto out_smbus; | ||
2114 | /* | ||
2115 | * If so requested, try to get our DMA buffers now. | ||
2116 | */ | ||
2117 | if (alloc_bufs_at_load) { | ||
2118 | if (cafe_alloc_dma_bufs(cam, 1)) | ||
2119 | cam_warn(cam, "Unable to alloc DMA buffers at load" | ||
2120 | " will try again later."); | ||
2121 | } | ||
2122 | |||
2123 | cafe_dfs_cam_setup(cam); | ||
2124 | mutex_unlock(&cam->s_mutex); | ||
2125 | cafe_add_dev(cam); | ||
2126 | return 0; | ||
2127 | |||
2128 | out_smbus: | ||
2129 | cafe_smbus_shutdown(cam); | ||
2130 | out_freeirq: | ||
2131 | cafe_ctlr_power_down(cam); | ||
2132 | free_irq(pdev->irq, cam); | ||
2133 | out_iounmap: | ||
2134 | pci_iounmap(pdev, cam->regs); | ||
2135 | out_free: | ||
2136 | kfree(cam); | ||
2137 | out: | ||
2138 | return ret; | ||
2139 | } | ||
2140 | |||
2141 | |||
2142 | /* | ||
2143 | * Shut down an initialized device | ||
2144 | */ | ||
2145 | static void cafe_shutdown(struct cafe_camera *cam) | ||
2146 | { | ||
2147 | /* FIXME: Make sure we take care of everything here */ | ||
2148 | cafe_dfs_cam_shutdown(cam); | ||
2149 | if (cam->n_sbufs > 0) | ||
2150 | /* What if they are still mapped? Shouldn't be, but... */ | ||
2151 | cafe_free_sio_buffers(cam); | ||
2152 | cafe_remove_dev(cam); | ||
2153 | cafe_ctlr_stop_dma(cam); | ||
2154 | cafe_ctlr_power_down(cam); | ||
2155 | cafe_smbus_shutdown(cam); | ||
2156 | cafe_free_dma_bufs(cam); | ||
2157 | free_irq(cam->pdev->irq, cam); | ||
2158 | pci_iounmap(cam->pdev, cam->regs); | ||
2159 | video_unregister_device(&cam->v4ldev); | ||
2160 | /* kfree(cam); done in v4l_release () */ | ||
2161 | } | ||
2162 | |||
2163 | |||
2164 | static void cafe_pci_remove(struct pci_dev *pdev) | ||
2165 | { | ||
2166 | struct cafe_camera *cam = cafe_find_by_pdev(pdev); | ||
2167 | |||
2168 | if (cam == NULL) { | ||
2169 | cam_warn(cam, "pci_remove on unknown pdev %p\n", pdev); | ||
2170 | return; | ||
2171 | } | ||
2172 | mutex_lock(&cam->s_mutex); | ||
2173 | if (cam->users > 0) | ||
2174 | cam_warn(cam, "Removing a device with users!\n"); | ||
2175 | cafe_shutdown(cam); | ||
2176 | /* No unlock - it no longer exists */ | ||
2177 | } | ||
2178 | |||
2179 | |||
2180 | |||
2181 | |||
2182 | static struct pci_device_id cafe_ids[] = { | ||
2183 | { PCI_DEVICE(0x1148, 0x4340) }, /* Temporary ID on devel board */ | ||
2184 | { PCI_DEVICE(0x11ab, 0x4100) }, /* Eventual real ID */ | ||
2185 | { PCI_DEVICE(0x11ab, 0x4102) }, /* Really eventual real ID */ | ||
2186 | { 0, } | ||
2187 | }; | ||
2188 | |||
2189 | MODULE_DEVICE_TABLE(pci, cafe_ids); | ||
2190 | |||
2191 | static struct pci_driver cafe_pci_driver = { | ||
2192 | .name = "cafe1000-ccic", | ||
2193 | .id_table = cafe_ids, | ||
2194 | .probe = cafe_pci_probe, | ||
2195 | .remove = cafe_pci_remove, | ||
2196 | }; | ||
2197 | |||
2198 | |||
2199 | |||
2200 | |||
2201 | static int __init cafe_init(void) | ||
2202 | { | ||
2203 | int ret; | ||
2204 | |||
2205 | printk(KERN_NOTICE "Marvell M88ALP01 'CAFE' Camera Controller version %d\n", | ||
2206 | CAFE_VERSION); | ||
2207 | cafe_dfs_setup(); | ||
2208 | ret = pci_register_driver(&cafe_pci_driver); | ||
2209 | if (ret) { | ||
2210 | printk(KERN_ERR "Unable to register cafe_ccic driver\n"); | ||
2211 | goto out; | ||
2212 | } | ||
2213 | request_module("ov7670"); /* FIXME want something more general */ | ||
2214 | ret = 0; | ||
2215 | |||
2216 | out: | ||
2217 | return ret; | ||
2218 | } | ||
2219 | |||
2220 | |||
2221 | static void __exit cafe_exit(void) | ||
2222 | { | ||
2223 | pci_unregister_driver(&cafe_pci_driver); | ||
2224 | cafe_dfs_shutdown(); | ||
2225 | } | ||
2226 | |||
2227 | module_init(cafe_init); | ||
2228 | module_exit(cafe_exit); | ||
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index 0f9d96963618..b2a66ba625f9 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig | |||
@@ -53,6 +53,7 @@ config VIDEO_CX88_DVB | |||
53 | select DVB_OR51132 if !DVB_FE_CUSTOMISE | 53 | select DVB_OR51132 if !DVB_FE_CUSTOMISE |
54 | select DVB_CX22702 if !DVB_FE_CUSTOMISE | 54 | select DVB_CX22702 if !DVB_FE_CUSTOMISE |
55 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE | 55 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE |
56 | select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE | ||
56 | select DVB_NXT200X if !DVB_FE_CUSTOMISE | 57 | select DVB_NXT200X if !DVB_FE_CUSTOMISE |
57 | select DVB_CX24123 if !DVB_FE_CUSTOMISE | 58 | select DVB_CX24123 if !DVB_FE_CUSTOMISE |
58 | select DVB_ISL6421 if !DVB_FE_CUSTOMISE | 59 | select DVB_ISL6421 if !DVB_FE_CUSTOMISE |
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index 46738321adaf..0cf0360588e6 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c | |||
@@ -50,7 +50,6 @@ MODULE_PARM_DESC(debug,"enable debug messages [blackbird]"); | |||
50 | #define dprintk(level,fmt, arg...) if (debug >= level) \ | 50 | #define dprintk(level,fmt, arg...) if (debug >= level) \ |
51 | printk(KERN_DEBUG "%s/2-bb: " fmt, dev->core->name , ## arg) | 51 | printk(KERN_DEBUG "%s/2-bb: " fmt, dev->core->name , ## arg) |
52 | 52 | ||
53 | static LIST_HEAD(cx8802_devlist); | ||
54 | 53 | ||
55 | /* ------------------------------------------------------------------ */ | 54 | /* ------------------------------------------------------------------ */ |
56 | 55 | ||
@@ -882,7 +881,7 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file, | |||
882 | BLACKBIRD_MPEG_CAPTURE, | 881 | BLACKBIRD_MPEG_CAPTURE, |
883 | BLACKBIRD_RAW_BITS_NONE); | 882 | BLACKBIRD_RAW_BITS_NONE); |
884 | 883 | ||
885 | cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, mpeg_do_ioctl); | 884 | cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, cx88_ioctl_hook); |
886 | 885 | ||
887 | blackbird_initialize_codec(dev); | 886 | blackbird_initialize_codec(dev); |
888 | cx88_set_scale(dev->core, dev->width, dev->height, | 887 | cx88_set_scale(dev->core, dev->width, dev->height, |
@@ -914,11 +913,15 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file, | |||
914 | } | 913 | } |
915 | 914 | ||
916 | default: | 915 | default: |
917 | return cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, mpeg_do_ioctl); | 916 | return cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, cx88_ioctl_hook); |
918 | } | 917 | } |
919 | return 0; | 918 | return 0; |
920 | } | 919 | } |
921 | 920 | ||
921 | int (*cx88_ioctl_hook)(struct inode *inode, struct file *file, | ||
922 | unsigned int cmd, void *arg); | ||
923 | unsigned int (*cx88_ioctl_translator)(unsigned int cmd); | ||
924 | |||
922 | static unsigned int mpeg_translate_ioctl(unsigned int cmd) | 925 | static unsigned int mpeg_translate_ioctl(unsigned int cmd) |
923 | { | 926 | { |
924 | return cmd; | 927 | return cmd; |
@@ -927,33 +930,49 @@ static unsigned int mpeg_translate_ioctl(unsigned int cmd) | |||
927 | static int mpeg_ioctl(struct inode *inode, struct file *file, | 930 | static int mpeg_ioctl(struct inode *inode, struct file *file, |
928 | unsigned int cmd, unsigned long arg) | 931 | unsigned int cmd, unsigned long arg) |
929 | { | 932 | { |
930 | cmd = mpeg_translate_ioctl( cmd ); | 933 | cmd = cx88_ioctl_translator( cmd ); |
931 | return video_usercopy(inode, file, cmd, arg, mpeg_do_ioctl); | 934 | return video_usercopy(inode, file, cmd, arg, cx88_ioctl_hook); |
932 | } | 935 | } |
933 | 936 | ||
934 | static int mpeg_open(struct inode *inode, struct file *file) | 937 | static int mpeg_open(struct inode *inode, struct file *file) |
935 | { | 938 | { |
936 | int minor = iminor(inode); | 939 | int minor = iminor(inode); |
937 | struct cx8802_dev *h,*dev = NULL; | 940 | struct cx8802_dev *dev = NULL; |
938 | struct cx8802_fh *fh; | 941 | struct cx8802_fh *fh; |
939 | struct list_head *list; | 942 | struct cx8802_driver *drv = NULL; |
943 | int err; | ||
940 | 944 | ||
941 | list_for_each(list,&cx8802_devlist) { | 945 | dev = cx8802_get_device(inode); |
942 | h = list_entry(list, struct cx8802_dev, devlist); | 946 | |
943 | if (h->mpeg_dev->minor == minor) | 947 | dprintk( 1, "%s\n", __FUNCTION__); |
944 | dev = h; | 948 | |
945 | } | 949 | if (dev == NULL) |
946 | if (NULL == dev) | ||
947 | return -ENODEV; | 950 | return -ENODEV; |
948 | 951 | ||
949 | if (blackbird_initialize_codec(dev) < 0) | 952 | /* Make sure we can acquire the hardware */ |
953 | drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); | ||
954 | if (drv) { | ||
955 | err = drv->request_acquire(drv); | ||
956 | if(err != 0) { | ||
957 | dprintk(1,"%s: Unable to acquire hardware, %d\n", __FUNCTION__, err); | ||
958 | return err; | ||
959 | } | ||
960 | } | ||
961 | |||
962 | if (blackbird_initialize_codec(dev) < 0) { | ||
963 | if (drv) | ||
964 | drv->request_release(drv); | ||
950 | return -EINVAL; | 965 | return -EINVAL; |
966 | } | ||
951 | dprintk(1,"open minor=%d\n",minor); | 967 | dprintk(1,"open minor=%d\n",minor); |
952 | 968 | ||
953 | /* allocate + initialize per filehandle data */ | 969 | /* allocate + initialize per filehandle data */ |
954 | fh = kzalloc(sizeof(*fh),GFP_KERNEL); | 970 | fh = kzalloc(sizeof(*fh),GFP_KERNEL); |
955 | if (NULL == fh) | 971 | if (NULL == fh) { |
972 | if (drv) | ||
973 | drv->request_release(drv); | ||
956 | return -ENOMEM; | 974 | return -ENOMEM; |
975 | } | ||
957 | file->private_data = fh; | 976 | file->private_data = fh; |
958 | fh->dev = dev; | 977 | fh->dev = dev; |
959 | 978 | ||
@@ -974,6 +993,8 @@ static int mpeg_open(struct inode *inode, struct file *file) | |||
974 | static int mpeg_release(struct inode *inode, struct file *file) | 993 | static int mpeg_release(struct inode *inode, struct file *file) |
975 | { | 994 | { |
976 | struct cx8802_fh *fh = file->private_data; | 995 | struct cx8802_fh *fh = file->private_data; |
996 | struct cx8802_dev *dev = NULL; | ||
997 | struct cx8802_driver *drv = NULL; | ||
977 | 998 | ||
978 | /* blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, BLACKBIRD_END_NOW, 0, 0x13); */ | 999 | /* blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, BLACKBIRD_END_NOW, 0, 0x13); */ |
979 | blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, | 1000 | blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, |
@@ -992,6 +1013,16 @@ static int mpeg_release(struct inode *inode, struct file *file) | |||
992 | videobuf_mmap_free(&fh->mpegq); | 1013 | videobuf_mmap_free(&fh->mpegq); |
993 | file->private_data = NULL; | 1014 | file->private_data = NULL; |
994 | kfree(fh); | 1015 | kfree(fh); |
1016 | |||
1017 | /* Make sure we release the hardware */ | ||
1018 | dev = cx8802_get_device(inode); | ||
1019 | if (dev == NULL) | ||
1020 | return -ENODEV; | ||
1021 | |||
1022 | drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); | ||
1023 | if (drv) | ||
1024 | drv->request_release(drv); | ||
1025 | |||
995 | return 0; | 1026 | return 0; |
996 | } | 1027 | } |
997 | 1028 | ||
@@ -1043,6 +1074,44 @@ static struct video_device cx8802_mpeg_template = | |||
1043 | 1074 | ||
1044 | /* ------------------------------------------------------------------ */ | 1075 | /* ------------------------------------------------------------------ */ |
1045 | 1076 | ||
1077 | /* The CX8802 MPEG API will call this when we can use the hardware */ | ||
1078 | static int cx8802_blackbird_advise_acquire(struct cx8802_driver *drv) | ||
1079 | { | ||
1080 | struct cx88_core *core = drv->core; | ||
1081 | int err = 0; | ||
1082 | |||
1083 | switch (core->board) { | ||
1084 | case CX88_BOARD_HAUPPAUGE_HVR1300: | ||
1085 | /* By default, core setup will leave the cx22702 out of reset, on the bus. | ||
1086 | * We left the hardware on power up with the cx22702 active. | ||
1087 | * We're being given access to re-arrange the GPIOs. | ||
1088 | * Take the bus off the cx22702 and put the cx23416 on it. | ||
1089 | */ | ||
1090 | cx_clear(MO_GP0_IO, 0x00000080); /* cx22702 in reset */ | ||
1091 | cx_set(MO_GP0_IO, 0x00000004); /* Disable the cx22702 */ | ||
1092 | break; | ||
1093 | default: | ||
1094 | err = -ENODEV; | ||
1095 | } | ||
1096 | return err; | ||
1097 | } | ||
1098 | |||
1099 | /* The CX8802 MPEG API will call this when we need to release the hardware */ | ||
1100 | static int cx8802_blackbird_advise_release(struct cx8802_driver *drv) | ||
1101 | { | ||
1102 | struct cx88_core *core = drv->core; | ||
1103 | int err = 0; | ||
1104 | |||
1105 | switch (core->board) { | ||
1106 | case CX88_BOARD_HAUPPAUGE_HVR1300: | ||
1107 | /* Exit leaving the cx23416 on the bus */ | ||
1108 | break; | ||
1109 | default: | ||
1110 | err = -ENODEV; | ||
1111 | } | ||
1112 | return err; | ||
1113 | } | ||
1114 | |||
1046 | static void blackbird_unregister_video(struct cx8802_dev *dev) | 1115 | static void blackbird_unregister_video(struct cx8802_dev *dev) |
1047 | { | 1116 | { |
1048 | if (dev->mpeg_dev) { | 1117 | if (dev->mpeg_dev) { |
@@ -1073,28 +1142,23 @@ static int blackbird_register_video(struct cx8802_dev *dev) | |||
1073 | 1142 | ||
1074 | /* ----------------------------------------------------------- */ | 1143 | /* ----------------------------------------------------------- */ |
1075 | 1144 | ||
1076 | static int __devinit blackbird_probe(struct pci_dev *pci_dev, | 1145 | static int cx8802_blackbird_probe(struct cx8802_driver *drv) |
1077 | const struct pci_device_id *pci_id) | ||
1078 | { | 1146 | { |
1079 | struct cx8802_dev *dev; | 1147 | struct cx88_core *core = drv->core; |
1080 | struct cx88_core *core; | 1148 | struct cx8802_dev *dev = core->dvbdev; |
1081 | int err; | 1149 | int err; |
1082 | 1150 | ||
1083 | /* general setup */ | 1151 | dprintk( 1, "%s\n", __FUNCTION__); |
1084 | core = cx88_core_get(pci_dev); | 1152 | dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", |
1085 | if (NULL == core) | 1153 | core->board, |
1086 | return -EINVAL; | 1154 | core->name, |
1155 | core->pci_bus, | ||
1156 | core->pci_slot); | ||
1087 | 1157 | ||
1088 | err = -ENODEV; | 1158 | err = -ENODEV; |
1089 | if (!(cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD)) | 1159 | if (!(cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD)) |
1090 | goto fail_core; | 1160 | goto fail_core; |
1091 | 1161 | ||
1092 | err = -ENOMEM; | ||
1093 | dev = kzalloc(sizeof(*dev),GFP_KERNEL); | ||
1094 | if (NULL == dev) | ||
1095 | goto fail_core; | ||
1096 | dev->pci = pci_dev; | ||
1097 | dev->core = core; | ||
1098 | dev->width = 720; | 1162 | dev->width = 720; |
1099 | dev->height = 576; | 1163 | dev->height = 576; |
1100 | cx2341x_fill_defaults(&dev->params); | 1164 | cx2341x_fill_defaults(&dev->params); |
@@ -1106,64 +1170,36 @@ static int __devinit blackbird_probe(struct pci_dev *pci_dev, | |||
1106 | dev->height = 576; | 1170 | dev->height = 576; |
1107 | } | 1171 | } |
1108 | 1172 | ||
1109 | err = cx8802_init_common(dev); | ||
1110 | if (0 != err) | ||
1111 | goto fail_free; | ||
1112 | |||
1113 | /* blackbird stuff */ | 1173 | /* blackbird stuff */ |
1114 | printk("%s/2: cx23416 based mpeg encoder (blackbird reference design)\n", | 1174 | printk("%s/2: cx23416 based mpeg encoder (blackbird reference design)\n", |
1115 | core->name); | 1175 | core->name); |
1116 | host_setup(dev->core); | 1176 | host_setup(dev->core); |
1117 | 1177 | ||
1118 | list_add_tail(&dev->devlist,&cx8802_devlist); | ||
1119 | blackbird_register_video(dev); | 1178 | blackbird_register_video(dev); |
1120 | 1179 | ||
1121 | /* initial device configuration: needed ? */ | 1180 | /* initial device configuration: needed ? */ |
1122 | 1181 | ||
1123 | return 0; | 1182 | return 0; |
1124 | 1183 | ||
1125 | fail_free: | ||
1126 | kfree(dev); | ||
1127 | fail_core: | 1184 | fail_core: |
1128 | cx88_core_put(core,pci_dev); | ||
1129 | return err; | 1185 | return err; |
1130 | } | 1186 | } |
1131 | 1187 | ||
1132 | static void __devexit blackbird_remove(struct pci_dev *pci_dev) | 1188 | static int cx8802_blackbird_remove(struct cx8802_driver *drv) |
1133 | { | 1189 | { |
1134 | struct cx8802_dev *dev = pci_get_drvdata(pci_dev); | ||
1135 | |||
1136 | /* blackbird */ | 1190 | /* blackbird */ |
1137 | blackbird_unregister_video(dev); | 1191 | blackbird_unregister_video(drv->core->dvbdev); |
1138 | list_del(&dev->devlist); | ||
1139 | 1192 | ||
1140 | /* common */ | 1193 | return 0; |
1141 | cx8802_fini_common(dev); | ||
1142 | cx88_core_put(dev->core,dev->pci); | ||
1143 | kfree(dev); | ||
1144 | } | 1194 | } |
1145 | 1195 | ||
1146 | static struct pci_device_id cx8802_pci_tbl[] = { | 1196 | static struct cx8802_driver cx8802_blackbird_driver = { |
1147 | { | 1197 | .type_id = CX88_MPEG_BLACKBIRD, |
1148 | .vendor = 0x14f1, | 1198 | .hw_access = CX8802_DRVCTL_SHARED, |
1149 | .device = 0x8802, | 1199 | .probe = cx8802_blackbird_probe, |
1150 | .subvendor = PCI_ANY_ID, | 1200 | .remove = cx8802_blackbird_remove, |
1151 | .subdevice = PCI_ANY_ID, | 1201 | .advise_acquire = cx8802_blackbird_advise_acquire, |
1152 | },{ | 1202 | .advise_release = cx8802_blackbird_advise_release, |
1153 | /* --- end of list --- */ | ||
1154 | } | ||
1155 | }; | ||
1156 | MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl); | ||
1157 | |||
1158 | static struct pci_driver blackbird_pci_driver = { | ||
1159 | .name = "cx88-blackbird", | ||
1160 | .id_table = cx8802_pci_tbl, | ||
1161 | .probe = blackbird_probe, | ||
1162 | .remove = __devexit_p(blackbird_remove), | ||
1163 | #ifdef CONFIG_PM | ||
1164 | .suspend = cx8802_suspend_common, | ||
1165 | .resume = cx8802_resume_common, | ||
1166 | #endif | ||
1167 | }; | 1203 | }; |
1168 | 1204 | ||
1169 | static int blackbird_init(void) | 1205 | static int blackbird_init(void) |
@@ -1176,17 +1212,22 @@ static int blackbird_init(void) | |||
1176 | printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", | 1212 | printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", |
1177 | SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); | 1213 | SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); |
1178 | #endif | 1214 | #endif |
1179 | return pci_register_driver(&blackbird_pci_driver); | 1215 | cx88_ioctl_hook = mpeg_do_ioctl; |
1216 | cx88_ioctl_translator = mpeg_translate_ioctl; | ||
1217 | return cx8802_register_driver(&cx8802_blackbird_driver); | ||
1180 | } | 1218 | } |
1181 | 1219 | ||
1182 | static void blackbird_fini(void) | 1220 | static void blackbird_fini(void) |
1183 | { | 1221 | { |
1184 | pci_unregister_driver(&blackbird_pci_driver); | 1222 | cx8802_unregister_driver(&cx8802_blackbird_driver); |
1185 | } | 1223 | } |
1186 | 1224 | ||
1187 | module_init(blackbird_init); | 1225 | module_init(blackbird_init); |
1188 | module_exit(blackbird_fini); | 1226 | module_exit(blackbird_fini); |
1189 | 1227 | ||
1228 | EXPORT_SYMBOL(cx88_ioctl_hook); | ||
1229 | EXPORT_SYMBOL(cx88_ioctl_translator); | ||
1230 | |||
1190 | /* ----------------------------------------------------------- */ | 1231 | /* ----------------------------------------------------------- */ |
1191 | /* | 1232 | /* |
1192 | * Local variables: | 1233 | * Local variables: |
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index f764a57c56be..c791708b1336 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c | |||
@@ -281,18 +281,22 @@ struct cx88_board cx88_boards[] = { | |||
281 | .type = CX88_VMUX_TELEVISION, | 281 | .type = CX88_VMUX_TELEVISION, |
282 | .vmux = 0, | 282 | .vmux = 0, |
283 | .gpio0 = 0x0000bde2, | 283 | .gpio0 = 0x0000bde2, |
284 | .extadc = 1, | ||
284 | },{ | 285 | },{ |
285 | .type = CX88_VMUX_COMPOSITE1, | 286 | .type = CX88_VMUX_COMPOSITE1, |
286 | .vmux = 1, | 287 | .vmux = 1, |
287 | .gpio0 = 0x0000bde6, | 288 | .gpio0 = 0x0000bde6, |
289 | .extadc = 1, | ||
288 | },{ | 290 | },{ |
289 | .type = CX88_VMUX_SVIDEO, | 291 | .type = CX88_VMUX_SVIDEO, |
290 | .vmux = 2, | 292 | .vmux = 2, |
291 | .gpio0 = 0x0000bde6, | 293 | .gpio0 = 0x0000bde6, |
294 | .extadc = 1, | ||
292 | }}, | 295 | }}, |
293 | .radio = { | 296 | .radio = { |
294 | .type = CX88_RADIO, | 297 | .type = CX88_RADIO, |
295 | .gpio0 = 0x0000bd62, | 298 | .gpio0 = 0x0000bd62, |
299 | .extadc = 1, | ||
296 | }, | 300 | }, |
297 | .mpeg = CX88_MPEG_BLACKBIRD, | 301 | .mpeg = CX88_MPEG_BLACKBIRD, |
298 | }, | 302 | }, |
@@ -353,6 +357,7 @@ struct cx88_board cx88_boards[] = { | |||
353 | .type = CX88_VMUX_SVIDEO, | 357 | .type = CX88_VMUX_SVIDEO, |
354 | .vmux = 2, | 358 | .vmux = 2, |
355 | .gpio0 = 0x0000fde6, // 0x0000fda6 L,R RCA audio in? | 359 | .gpio0 = 0x0000fde6, // 0x0000fda6 L,R RCA audio in? |
360 | .extadc = 1, | ||
356 | }}, | 361 | }}, |
357 | .radio = { | 362 | .radio = { |
358 | .type = CX88_RADIO, | 363 | .type = CX88_RADIO, |
@@ -523,6 +528,7 @@ struct cx88_board cx88_boards[] = { | |||
523 | .input = {{ | 528 | .input = {{ |
524 | .type = CX88_VMUX_TELEVISION, | 529 | .type = CX88_VMUX_TELEVISION, |
525 | .vmux = 0, | 530 | .vmux = 0, |
531 | .extadc = 1, | ||
526 | }}, | 532 | }}, |
527 | .mpeg = CX88_MPEG_BLACKBIRD, | 533 | .mpeg = CX88_MPEG_BLACKBIRD, |
528 | }, | 534 | }, |
@@ -646,18 +652,22 @@ struct cx88_board cx88_boards[] = { | |||
646 | .type = CX88_VMUX_TELEVISION, | 652 | .type = CX88_VMUX_TELEVISION, |
647 | .vmux = 0, | 653 | .vmux = 0, |
648 | .gpio0 = 0x00009d80, | 654 | .gpio0 = 0x00009d80, |
655 | .extadc = 1, | ||
649 | },{ | 656 | },{ |
650 | .type = CX88_VMUX_COMPOSITE1, | 657 | .type = CX88_VMUX_COMPOSITE1, |
651 | .vmux = 1, | 658 | .vmux = 1, |
652 | .gpio0 = 0x00009d76, | 659 | .gpio0 = 0x00009d76, |
660 | .extadc = 1, | ||
653 | },{ | 661 | },{ |
654 | .type = CX88_VMUX_SVIDEO, | 662 | .type = CX88_VMUX_SVIDEO, |
655 | .vmux = 2, | 663 | .vmux = 2, |
656 | .gpio0 = 0x00009d76, | 664 | .gpio0 = 0x00009d76, |
665 | .extadc = 1, | ||
657 | }}, | 666 | }}, |
658 | .radio = { | 667 | .radio = { |
659 | .type = CX88_RADIO, | 668 | .type = CX88_RADIO, |
660 | .gpio0 = 0x00009d00, | 669 | .gpio0 = 0x00009d00, |
670 | .extadc = 1, | ||
661 | }, | 671 | }, |
662 | .mpeg = CX88_MPEG_BLACKBIRD, | 672 | .mpeg = CX88_MPEG_BLACKBIRD, |
663 | }, | 673 | }, |
@@ -786,25 +796,29 @@ struct cx88_board cx88_boards[] = { | |||
786 | .tuner_addr = ADDR_UNSET, | 796 | .tuner_addr = ADDR_UNSET, |
787 | .radio_addr = ADDR_UNSET, | 797 | .radio_addr = ADDR_UNSET, |
788 | .tda9887_conf = TDA9887_PRESENT, | 798 | .tda9887_conf = TDA9887_PRESENT, |
789 | .mpeg = CX88_MPEG_BLACKBIRD, | ||
790 | .input = {{ | 799 | .input = {{ |
791 | .type = CX88_VMUX_COMPOSITE1, | 800 | .type = CX88_VMUX_COMPOSITE1, |
792 | .vmux = 0, | 801 | .vmux = 0, |
793 | .gpio0 = 0x0000cd73, | 802 | .gpio0 = 0x0000cd73, |
803 | .extadc = 1, | ||
794 | },{ | 804 | },{ |
795 | .type = CX88_VMUX_SVIDEO, | 805 | .type = CX88_VMUX_SVIDEO, |
796 | .vmux = 1, | 806 | .vmux = 1, |
797 | .gpio0 = 0x0000cd73, | 807 | .gpio0 = 0x0000cd73, |
808 | .extadc = 1, | ||
798 | },{ | 809 | },{ |
799 | .type = CX88_VMUX_TELEVISION, | 810 | .type = CX88_VMUX_TELEVISION, |
800 | .vmux = 3, | 811 | .vmux = 3, |
801 | .gpio0 = 0x0000cdb3, | 812 | .gpio0 = 0x0000cdb3, |
813 | .extadc = 1, | ||
802 | }}, | 814 | }}, |
803 | .radio = { | 815 | .radio = { |
804 | .type = CX88_RADIO, | 816 | .type = CX88_RADIO, |
805 | .vmux = 2, | 817 | .vmux = 2, |
806 | .gpio0 = 0x0000cdf3, | 818 | .gpio0 = 0x0000cdf3, |
819 | .extadc = 1, | ||
807 | }, | 820 | }, |
821 | .mpeg = CX88_MPEG_BLACKBIRD, | ||
808 | }, | 822 | }, |
809 | [CX88_BOARD_KWORLD_VSTREAM_EXPERT_DVD] = { | 823 | [CX88_BOARD_KWORLD_VSTREAM_EXPERT_DVD] = { |
810 | /* Alexander Wold <awold@bigfoot.com> */ | 824 | /* Alexander Wold <awold@bigfoot.com> */ |
@@ -1050,7 +1064,6 @@ struct cx88_board cx88_boards[] = { | |||
1050 | .mpeg = CX88_MPEG_DVB, | 1064 | .mpeg = CX88_MPEG_DVB, |
1051 | }, | 1065 | }, |
1052 | [CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT] = { | 1066 | [CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT] = { |
1053 | /* FIXME: Audio not working for s-video / composite inputs. */ | ||
1054 | .name = "KWorld HardwareMpegTV XPert", | 1067 | .name = "KWorld HardwareMpegTV XPert", |
1055 | .tuner_type = TUNER_PHILIPS_TDA8290, | 1068 | .tuner_type = TUNER_PHILIPS_TDA8290, |
1056 | .radio_type = UNSET, | 1069 | .radio_type = UNSET, |
@@ -1065,10 +1078,12 @@ struct cx88_board cx88_boards[] = { | |||
1065 | .type = CX88_VMUX_COMPOSITE1, | 1078 | .type = CX88_VMUX_COMPOSITE1, |
1066 | .vmux = 1, | 1079 | .vmux = 1, |
1067 | .gpio0 = 0x3de6, | 1080 | .gpio0 = 0x3de6, |
1081 | .extadc = 1, | ||
1068 | },{ | 1082 | },{ |
1069 | .type = CX88_VMUX_SVIDEO, | 1083 | .type = CX88_VMUX_SVIDEO, |
1070 | .vmux = 2, | 1084 | .vmux = 2, |
1071 | .gpio0 = 0x3de6, | 1085 | .gpio0 = 0x3de6, |
1086 | .extadc = 1, | ||
1072 | }}, | 1087 | }}, |
1073 | .radio = { | 1088 | .radio = { |
1074 | .type = CX88_RADIO, | 1089 | .type = CX88_RADIO, |
@@ -1252,35 +1267,35 @@ struct cx88_board cx88_boards[] = { | |||
1252 | .gpio0 = 0x070b, | 1267 | .gpio0 = 0x070b, |
1253 | }}, | 1268 | }}, |
1254 | }, | 1269 | }, |
1255 | [CX88_BOARD_TE_DTV_250_OEM_SWANN] = { | 1270 | [CX88_BOARD_TE_DTV_250_OEM_SWANN] = { |
1256 | .name = "Shenzhen Tungsten Ages Tech TE-DTV-250 / Swann OEM", | 1271 | .name = "Shenzhen Tungsten Ages Tech TE-DTV-250 / Swann OEM", |
1257 | .tuner_type = TUNER_LG_PAL_NEW_TAPC, | 1272 | .tuner_type = TUNER_LG_PAL_NEW_TAPC, |
1258 | .radio_type = UNSET, | 1273 | .radio_type = UNSET, |
1259 | .tuner_addr = ADDR_UNSET, | 1274 | .tuner_addr = ADDR_UNSET, |
1260 | .radio_addr = ADDR_UNSET, | 1275 | .radio_addr = ADDR_UNSET, |
1261 | .input = {{ | 1276 | .input = {{ |
1262 | .type = CX88_VMUX_TELEVISION, | 1277 | .type = CX88_VMUX_TELEVISION, |
1263 | .vmux = 0, | 1278 | .vmux = 0, |
1264 | .gpio0 = 0x003fffff, | 1279 | .gpio0 = 0x003fffff, |
1265 | .gpio1 = 0x00e00000, | 1280 | .gpio1 = 0x00e00000, |
1266 | .gpio2 = 0x003fffff, | 1281 | .gpio2 = 0x003fffff, |
1267 | .gpio3 = 0x02000000, | 1282 | .gpio3 = 0x02000000, |
1268 | },{ | 1283 | },{ |
1269 | .type = CX88_VMUX_COMPOSITE1, | 1284 | .type = CX88_VMUX_COMPOSITE1, |
1270 | .vmux = 1, | 1285 | .vmux = 1, |
1271 | .gpio0 = 0x003fffff, | 1286 | .gpio0 = 0x003fffff, |
1272 | .gpio1 = 0x00e00000, | 1287 | .gpio1 = 0x00e00000, |
1273 | .gpio2 = 0x003fffff, | 1288 | .gpio2 = 0x003fffff, |
1274 | .gpio3 = 0x02000000, | 1289 | .gpio3 = 0x02000000, |
1275 | },{ | 1290 | },{ |
1276 | .type = CX88_VMUX_SVIDEO, | 1291 | .type = CX88_VMUX_SVIDEO, |
1277 | .vmux = 2, | 1292 | .vmux = 2, |
1278 | .gpio0 = 0x003fffff, | 1293 | .gpio0 = 0x003fffff, |
1279 | .gpio1 = 0x00e00000, | 1294 | .gpio1 = 0x00e00000, |
1280 | .gpio2 = 0x003fffff, | 1295 | .gpio2 = 0x003fffff, |
1281 | .gpio3 = 0x02000000, | 1296 | .gpio3 = 0x02000000, |
1282 | }}, | 1297 | }}, |
1283 | }, | 1298 | }, |
1284 | [CX88_BOARD_HAUPPAUGE_HVR1300] = { | 1299 | [CX88_BOARD_HAUPPAUGE_HVR1300] = { |
1285 | .name = "Hauppauge WinTV-HVR1300 DVB-T/Hybrid MPEG Encoder", | 1300 | .name = "Hauppauge WinTV-HVR1300 DVB-T/Hybrid MPEG Encoder", |
1286 | .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, | 1301 | .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, |
@@ -1293,17 +1308,20 @@ struct cx88_board cx88_boards[] = { | |||
1293 | .type = CX88_VMUX_TELEVISION, | 1308 | .type = CX88_VMUX_TELEVISION, |
1294 | .vmux = 0, | 1309 | .vmux = 0, |
1295 | .gpio0 = 0xe780, | 1310 | .gpio0 = 0xe780, |
1311 | .extadc = 1, | ||
1296 | },{ | 1312 | },{ |
1297 | .type = CX88_VMUX_COMPOSITE1, | 1313 | .type = CX88_VMUX_COMPOSITE1, |
1298 | .vmux = 1, | 1314 | .vmux = 1, |
1299 | .gpio0 = 0xe780, | 1315 | .gpio0 = 0xe780, |
1316 | .extadc = 1, | ||
1300 | },{ | 1317 | },{ |
1301 | .type = CX88_VMUX_SVIDEO, | 1318 | .type = CX88_VMUX_SVIDEO, |
1302 | .vmux = 2, | 1319 | .vmux = 2, |
1303 | .gpio0 = 0xe780, | 1320 | .gpio0 = 0xe780, |
1321 | .extadc = 1, | ||
1304 | }}, | 1322 | }}, |
1305 | /* fixme: Add radio support */ | 1323 | /* fixme: Add radio support */ |
1306 | .mpeg = CX88_MPEG_DVB, | 1324 | .mpeg = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD, |
1307 | }, | 1325 | }, |
1308 | }; | 1326 | }; |
1309 | const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); | 1327 | const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); |
@@ -1513,6 +1531,10 @@ struct cx88_subid cx88_subids[] = { | |||
1513 | },{ | 1531 | },{ |
1514 | .subvendor = 0x17de, | 1532 | .subvendor = 0x17de, |
1515 | .subdevice = 0x0840, | 1533 | .subdevice = 0x0840, |
1534 | .card = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT, | ||
1535 | },{ | ||
1536 | .subvendor = 0x1421, | ||
1537 | .subdevice = 0x0305, | ||
1516 | .card = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT, | 1538 | .card = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT, |
1517 | },{ | 1539 | },{ |
1518 | .subvendor = 0x18ac, | 1540 | .subvendor = 0x18ac, |
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 0ef13e7efa2e..8b203354fccd 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c | |||
@@ -42,7 +42,7 @@ | |||
42 | #include "cx22702.h" | 42 | #include "cx22702.h" |
43 | #include "or51132.h" | 43 | #include "or51132.h" |
44 | #include "lgdt330x.h" | 44 | #include "lgdt330x.h" |
45 | #include "lg_h06xf.h" | 45 | #include "lgh06xf.h" |
46 | #include "nxt200x.h" | 46 | #include "nxt200x.h" |
47 | #include "cx24123.h" | 47 | #include "cx24123.h" |
48 | #include "isl6421.h" | 48 | #include "isl6421.h" |
@@ -57,7 +57,7 @@ module_param(debug, int, 0644); | |||
57 | MODULE_PARM_DESC(debug,"enable debug messages [dvb]"); | 57 | MODULE_PARM_DESC(debug,"enable debug messages [dvb]"); |
58 | 58 | ||
59 | #define dprintk(level,fmt, arg...) if (debug >= level) \ | 59 | #define dprintk(level,fmt, arg...) if (debug >= level) \ |
60 | printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->core->name , ## arg) | 60 | printk(KERN_DEBUG "%s/2-dvb: " fmt, core->name, ## arg) |
61 | 61 | ||
62 | /* ------------------------------------------------------------------ */ | 62 | /* ------------------------------------------------------------------ */ |
63 | 63 | ||
@@ -74,8 +74,8 @@ static int dvb_buf_setup(struct videobuf_queue *q, | |||
74 | return 0; | 74 | return 0; |
75 | } | 75 | } |
76 | 76 | ||
77 | static int dvb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | 77 | static int dvb_buf_prepare(struct videobuf_queue *q, |
78 | enum v4l2_field field) | 78 | struct videobuf_buffer *vb, enum v4l2_field field) |
79 | { | 79 | { |
80 | struct cx8802_dev *dev = q->priv_data; | 80 | struct cx8802_dev *dev = q->priv_data; |
81 | return cx8802_buf_prepare(q, dev, (struct cx88_buffer*)vb,field); | 81 | return cx8802_buf_prepare(q, dev, (struct cx88_buffer*)vb,field); |
@@ -87,7 +87,8 @@ static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) | |||
87 | cx8802_buf_queue(dev, (struct cx88_buffer*)vb); | 87 | cx8802_buf_queue(dev, (struct cx88_buffer*)vb); |
88 | } | 88 | } |
89 | 89 | ||
90 | static void dvb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb) | 90 | static void dvb_buf_release(struct videobuf_queue *q, |
91 | struct videobuf_buffer *vb) | ||
91 | { | 92 | { |
92 | cx88_free_buffer(q, (struct cx88_buffer*)vb); | 93 | cx88_free_buffer(q, (struct cx88_buffer*)vb); |
93 | } | 94 | } |
@@ -100,6 +101,26 @@ static struct videobuf_queue_ops dvb_qops = { | |||
100 | }; | 101 | }; |
101 | 102 | ||
102 | /* ------------------------------------------------------------------ */ | 103 | /* ------------------------------------------------------------------ */ |
104 | |||
105 | static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, int acquire) | ||
106 | { | ||
107 | struct cx8802_dev *dev= fe->dvb->priv; | ||
108 | struct cx8802_driver *drv = NULL; | ||
109 | int ret = 0; | ||
110 | |||
111 | drv = cx8802_get_driver(dev, CX88_MPEG_DVB); | ||
112 | if (drv) { | ||
113 | if (acquire) | ||
114 | ret = drv->request_acquire(drv); | ||
115 | else | ||
116 | ret = drv->request_release(drv); | ||
117 | } | ||
118 | |||
119 | return ret; | ||
120 | } | ||
121 | |||
122 | /* ------------------------------------------------------------------ */ | ||
123 | |||
103 | static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe) | 124 | static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe) |
104 | { | 125 | { |
105 | static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x39 }; | 126 | static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x39 }; |
@@ -268,35 +289,6 @@ static struct mt352_config dntv_live_dvbt_pro_config = { | |||
268 | }; | 289 | }; |
269 | #endif | 290 | #endif |
270 | 291 | ||
271 | static int dvico_hybrid_tuner_set_params(struct dvb_frontend *fe, | ||
272 | struct dvb_frontend_parameters *params) | ||
273 | { | ||
274 | u8 pllbuf[4]; | ||
275 | struct cx8802_dev *dev= fe->dvb->priv; | ||
276 | struct i2c_msg msg = | ||
277 | { .addr = dev->core->pll_addr, .flags = 0, | ||
278 | .buf = pllbuf, .len = 4 }; | ||
279 | int err; | ||
280 | |||
281 | dvb_pll_configure(dev->core->pll_desc, pllbuf, | ||
282 | params->frequency, | ||
283 | params->u.ofdm.bandwidth); | ||
284 | |||
285 | if (fe->ops.i2c_gate_ctrl) | ||
286 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
287 | if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) { | ||
288 | printk(KERN_WARNING "cx88-dvb: %s error " | ||
289 | "(addr %02x <- %02x, err = %i)\n", | ||
290 | __FUNCTION__, pllbuf[0], pllbuf[1], err); | ||
291 | if (err < 0) | ||
292 | return err; | ||
293 | else | ||
294 | return -EREMOTEIO; | ||
295 | } | ||
296 | |||
297 | return 0; | ||
298 | } | ||
299 | |||
300 | static struct zl10353_config dvico_fusionhdtv_hybrid = { | 292 | static struct zl10353_config dvico_fusionhdtv_hybrid = { |
301 | .demod_address = 0x0f, | 293 | .demod_address = 0x0f, |
302 | .no_tuner = 1, | 294 | .no_tuner = 1, |
@@ -311,28 +303,12 @@ static struct cx22702_config connexant_refboard_config = { | |||
311 | .output_mode = CX22702_SERIAL_OUTPUT, | 303 | .output_mode = CX22702_SERIAL_OUTPUT, |
312 | }; | 304 | }; |
313 | 305 | ||
314 | static struct cx22702_config hauppauge_novat_config = { | 306 | static struct cx22702_config hauppauge_hvr_config = { |
315 | .demod_address = 0x43, | ||
316 | .output_mode = CX22702_SERIAL_OUTPUT, | ||
317 | }; | ||
318 | |||
319 | static struct cx22702_config hauppauge_hvr1100_config = { | ||
320 | .demod_address = 0x63, | 307 | .demod_address = 0x63, |
321 | .output_mode = CX22702_SERIAL_OUTPUT, | 308 | .output_mode = CX22702_SERIAL_OUTPUT, |
322 | }; | 309 | }; |
323 | 310 | ||
324 | static struct cx22702_config hauppauge_hvr1300_config = { | 311 | static int or51132_set_ts_param(struct dvb_frontend* fe, int is_punctured) |
325 | .demod_address = 0x63, | ||
326 | .output_mode = CX22702_SERIAL_OUTPUT, | ||
327 | }; | ||
328 | |||
329 | static struct cx22702_config hauppauge_hvr3000_config = { | ||
330 | .demod_address = 0x63, | ||
331 | .output_mode = CX22702_SERIAL_OUTPUT, | ||
332 | }; | ||
333 | |||
334 | static int or51132_set_ts_param(struct dvb_frontend* fe, | ||
335 | int is_punctured) | ||
336 | { | 312 | { |
337 | struct cx8802_dev *dev= fe->dvb->priv; | 313 | struct cx8802_dev *dev= fe->dvb->priv; |
338 | dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00; | 314 | dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00; |
@@ -344,50 +320,6 @@ static struct or51132_config pchdtv_hd3000 = { | |||
344 | .set_ts_params = or51132_set_ts_param, | 320 | .set_ts_params = or51132_set_ts_param, |
345 | }; | 321 | }; |
346 | 322 | ||
347 | static int lgdt3302_tuner_set_params(struct dvb_frontend* fe, | ||
348 | struct dvb_frontend_parameters* params) | ||
349 | { | ||
350 | /* FIXME make this routine use the tuner-simple code. | ||
351 | * It could probably be shared with a number of ATSC | ||
352 | * frontends. Many share the same tuner with analog TV. */ | ||
353 | |||
354 | struct cx8802_dev *dev= fe->dvb->priv; | ||
355 | struct cx88_core *core = dev->core; | ||
356 | u8 buf[4]; | ||
357 | struct i2c_msg msg = | ||
358 | { .addr = dev->core->pll_addr, .flags = 0, .buf = buf, .len = 4 }; | ||
359 | int err; | ||
360 | |||
361 | dvb_pll_configure(core->pll_desc, buf, params->frequency, 0); | ||
362 | dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
363 | __FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]); | ||
364 | |||
365 | if (fe->ops.i2c_gate_ctrl) | ||
366 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
367 | if ((err = i2c_transfer(&core->i2c_adap, &msg, 1)) != 1) { | ||
368 | printk(KERN_WARNING "cx88-dvb: %s error " | ||
369 | "(addr %02x <- %02x, err = %i)\n", | ||
370 | __FUNCTION__, buf[0], buf[1], err); | ||
371 | if (err < 0) | ||
372 | return err; | ||
373 | else | ||
374 | return -EREMOTEIO; | ||
375 | } | ||
376 | return 0; | ||
377 | } | ||
378 | |||
379 | static int lgdt3303_tuner_set_params(struct dvb_frontend* fe, | ||
380 | struct dvb_frontend_parameters* params) | ||
381 | { | ||
382 | struct cx8802_dev *dev= fe->dvb->priv; | ||
383 | struct cx88_core *core = dev->core; | ||
384 | |||
385 | /* Put the analog decoder in standby to keep it quiet */ | ||
386 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); | ||
387 | |||
388 | return lg_h06xf_pll_set(fe, &core->i2c_adap, params); | ||
389 | } | ||
390 | |||
391 | static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index) | 323 | static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index) |
392 | { | 324 | { |
393 | struct cx8802_dev *dev= fe->dvb->priv; | 325 | struct cx8802_dev *dev= fe->dvb->priv; |
@@ -432,8 +364,7 @@ static struct lgdt330x_config pchdtv_hd5500 = { | |||
432 | .set_ts_params = lgdt330x_set_ts_param, | 364 | .set_ts_params = lgdt330x_set_ts_param, |
433 | }; | 365 | }; |
434 | 366 | ||
435 | static int nxt200x_set_ts_param(struct dvb_frontend* fe, | 367 | static int nxt200x_set_ts_param(struct dvb_frontend* fe, int is_punctured) |
436 | int is_punctured) | ||
437 | { | 368 | { |
438 | struct cx8802_dev *dev= fe->dvb->priv; | 369 | struct cx8802_dev *dev= fe->dvb->priv; |
439 | dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00; | 370 | dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00; |
@@ -469,11 +400,10 @@ static int kworld_dvbs_100_set_voltage(struct dvb_frontend* fe, | |||
469 | struct cx8802_dev *dev= fe->dvb->priv; | 400 | struct cx8802_dev *dev= fe->dvb->priv; |
470 | struct cx88_core *core = dev->core; | 401 | struct cx88_core *core = dev->core; |
471 | 402 | ||
472 | if (voltage == SEC_VOLTAGE_OFF) { | 403 | if (voltage == SEC_VOLTAGE_OFF) |
473 | cx_write(MO_GP0_IO, 0x000006fb); | 404 | cx_write(MO_GP0_IO, 0x000006fb); |
474 | } else { | 405 | else |
475 | cx_write(MO_GP0_IO, 0x000006f9); | 406 | cx_write(MO_GP0_IO, 0x000006f9); |
476 | } | ||
477 | 407 | ||
478 | if (core->prev_set_voltage) | 408 | if (core->prev_set_voltage) |
479 | return core->prev_set_voltage(fe, voltage); | 409 | return core->prev_set_voltage(fe, voltage); |
@@ -522,7 +452,7 @@ static int dvb_register(struct cx8802_dev *dev) | |||
522 | switch (dev->core->board) { | 452 | switch (dev->core->board) { |
523 | case CX88_BOARD_HAUPPAUGE_DVB_T1: | 453 | case CX88_BOARD_HAUPPAUGE_DVB_T1: |
524 | dev->dvb.frontend = dvb_attach(cx22702_attach, | 454 | dev->dvb.frontend = dvb_attach(cx22702_attach, |
525 | &hauppauge_novat_config, | 455 | &connexant_refboard_config, |
526 | &dev->core->i2c_adap); | 456 | &dev->core->i2c_adap); |
527 | if (dev->dvb.frontend != NULL) { | 457 | if (dev->dvb.frontend != NULL) { |
528 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, | 458 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, |
@@ -547,32 +477,11 @@ static int dvb_register(struct cx8802_dev *dev) | |||
547 | case CX88_BOARD_HAUPPAUGE_HVR1100: | 477 | case CX88_BOARD_HAUPPAUGE_HVR1100: |
548 | case CX88_BOARD_HAUPPAUGE_HVR1100LP: | 478 | case CX88_BOARD_HAUPPAUGE_HVR1100LP: |
549 | dev->dvb.frontend = dvb_attach(cx22702_attach, | 479 | dev->dvb.frontend = dvb_attach(cx22702_attach, |
550 | &hauppauge_hvr1100_config, | 480 | &hauppauge_hvr_config, |
551 | &dev->core->i2c_adap); | ||
552 | if (dev->dvb.frontend != NULL) { | ||
553 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, | ||
554 | &dev->core->i2c_adap, | ||
555 | &dvb_pll_fmd1216me); | ||
556 | } | ||
557 | break; | ||
558 | case CX88_BOARD_HAUPPAUGE_HVR1300: | ||
559 | dev->dvb.frontend = dvb_attach(cx22702_attach, | ||
560 | &hauppauge_hvr1300_config, | ||
561 | &dev->core->i2c_adap); | ||
562 | if (dev->dvb.frontend != NULL) { | ||
563 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, | ||
564 | &dev->core->i2c_adap, | ||
565 | &dvb_pll_fmd1216me); | ||
566 | } | ||
567 | break; | ||
568 | case CX88_BOARD_HAUPPAUGE_HVR3000: | ||
569 | dev->dvb.frontend = dvb_attach(cx22702_attach, | ||
570 | &hauppauge_hvr3000_config, | ||
571 | &dev->core->i2c_adap); | 481 | &dev->core->i2c_adap); |
572 | if (dev->dvb.frontend != NULL) { | 482 | if (dev->dvb.frontend != NULL) { |
573 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, | 483 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, |
574 | &dev->core->i2c_adap, | 484 | &dev->core->i2c_adap, &dvb_pll_fmd1216me); |
575 | &dvb_pll_fmd1216me); | ||
576 | } | 485 | } |
577 | break; | 486 | break; |
578 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: | 487 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: |
@@ -647,18 +556,17 @@ static int dvb_register(struct cx8802_dev *dev) | |||
647 | #endif | 556 | #endif |
648 | break; | 557 | break; |
649 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: | 558 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: |
650 | dev->core->pll_addr = 0x61; | ||
651 | dev->core->pll_desc = &dvb_pll_thomson_fe6600; | ||
652 | dev->dvb.frontend = dvb_attach(zl10353_attach, | 559 | dev->dvb.frontend = dvb_attach(zl10353_attach, |
653 | &dvico_fusionhdtv_hybrid, | 560 | &dvico_fusionhdtv_hybrid, |
654 | &dev->core->i2c_adap); | 561 | &dev->core->i2c_adap); |
655 | if (dev->dvb.frontend != NULL) { | 562 | if (dev->dvb.frontend != NULL) { |
656 | dev->dvb.frontend->ops.tuner_ops.set_params = dvico_hybrid_tuner_set_params; | 563 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, |
564 | &dev->core->i2c_adap, | ||
565 | &dvb_pll_thomson_fe6600); | ||
657 | } | 566 | } |
658 | break; | 567 | break; |
659 | case CX88_BOARD_PCHDTV_HD3000: | 568 | case CX88_BOARD_PCHDTV_HD3000: |
660 | dev->dvb.frontend = dvb_attach(or51132_attach, | 569 | dev->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000, |
661 | &pchdtv_hd3000, | ||
662 | &dev->core->i2c_adap); | 570 | &dev->core->i2c_adap); |
663 | if (dev->dvb.frontend != NULL) { | 571 | if (dev->dvb.frontend != NULL) { |
664 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, | 572 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, |
@@ -679,13 +587,13 @@ static int dvb_register(struct cx8802_dev *dev) | |||
679 | 587 | ||
680 | /* Select RF connector callback */ | 588 | /* Select RF connector callback */ |
681 | fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set; | 589 | fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set; |
682 | dev->core->pll_addr = 0x61; | ||
683 | dev->core->pll_desc = &dvb_pll_microtune_4042; | ||
684 | dev->dvb.frontend = dvb_attach(lgdt330x_attach, | 590 | dev->dvb.frontend = dvb_attach(lgdt330x_attach, |
685 | &fusionhdtv_3_gold, | 591 | &fusionhdtv_3_gold, |
686 | &dev->core->i2c_adap); | 592 | &dev->core->i2c_adap); |
687 | if (dev->dvb.frontend != NULL) { | 593 | if (dev->dvb.frontend != NULL) { |
688 | dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3302_tuner_set_params; | 594 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, |
595 | &dev->core->i2c_adap, | ||
596 | &dvb_pll_microtune_4042); | ||
689 | } | 597 | } |
690 | } | 598 | } |
691 | break; | 599 | break; |
@@ -699,13 +607,13 @@ static int dvb_register(struct cx8802_dev *dev) | |||
699 | mdelay(100); | 607 | mdelay(100); |
700 | cx_set(MO_GP0_IO, 9); | 608 | cx_set(MO_GP0_IO, 9); |
701 | mdelay(200); | 609 | mdelay(200); |
702 | dev->core->pll_addr = 0x61; | ||
703 | dev->core->pll_desc = &dvb_pll_thomson_dtt761x; | ||
704 | dev->dvb.frontend = dvb_attach(lgdt330x_attach, | 610 | dev->dvb.frontend = dvb_attach(lgdt330x_attach, |
705 | &fusionhdtv_3_gold, | 611 | &fusionhdtv_3_gold, |
706 | &dev->core->i2c_adap); | 612 | &dev->core->i2c_adap); |
707 | if (dev->dvb.frontend != NULL) { | 613 | if (dev->dvb.frontend != NULL) { |
708 | dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3302_tuner_set_params; | 614 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, |
615 | &dev->core->i2c_adap, | ||
616 | &dvb_pll_thomson_dtt761x); | ||
709 | } | 617 | } |
710 | } | 618 | } |
711 | break; | 619 | break; |
@@ -723,7 +631,8 @@ static int dvb_register(struct cx8802_dev *dev) | |||
723 | &fusionhdtv_5_gold, | 631 | &fusionhdtv_5_gold, |
724 | &dev->core->i2c_adap); | 632 | &dev->core->i2c_adap); |
725 | if (dev->dvb.frontend != NULL) { | 633 | if (dev->dvb.frontend != NULL) { |
726 | dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3303_tuner_set_params; | 634 | dvb_attach(lgh06xf_attach, dev->dvb.frontend, |
635 | &dev->core->i2c_adap); | ||
727 | } | 636 | } |
728 | } | 637 | } |
729 | break; | 638 | break; |
@@ -741,7 +650,8 @@ static int dvb_register(struct cx8802_dev *dev) | |||
741 | &pchdtv_hd5500, | 650 | &pchdtv_hd5500, |
742 | &dev->core->i2c_adap); | 651 | &dev->core->i2c_adap); |
743 | if (dev->dvb.frontend != NULL) { | 652 | if (dev->dvb.frontend != NULL) { |
744 | dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3303_tuner_set_params; | 653 | dvb_attach(lgh06xf_attach, dev->dvb.frontend, |
654 | &dev->core->i2c_adap); | ||
745 | } | 655 | } |
746 | } | 656 | } |
747 | break; | 657 | break; |
@@ -782,6 +692,24 @@ static int dvb_register(struct cx8802_dev *dev) | |||
782 | dev->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage; | 692 | dev->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage; |
783 | } | 693 | } |
784 | break; | 694 | break; |
695 | case CX88_BOARD_HAUPPAUGE_HVR1300: | ||
696 | dev->dvb.frontend = dvb_attach(cx22702_attach, | ||
697 | &hauppauge_hvr_config, | ||
698 | &dev->core->i2c_adap); | ||
699 | if (dev->dvb.frontend != NULL) { | ||
700 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, | ||
701 | &dev->core->i2c_adap, &dvb_pll_fmd1216me); | ||
702 | } | ||
703 | break; | ||
704 | case CX88_BOARD_HAUPPAUGE_HVR3000: | ||
705 | dev->dvb.frontend = dvb_attach(cx22702_attach, | ||
706 | &hauppauge_hvr_config, | ||
707 | &dev->core->i2c_adap); | ||
708 | if (dev->dvb.frontend != NULL) { | ||
709 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, | ||
710 | &dev->core->i2c_adap, &dvb_pll_fmd1216me); | ||
711 | } | ||
712 | break; | ||
785 | default: | 713 | default: |
786 | printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n", | 714 | printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n", |
787 | dev->core->name); | 715 | dev->core->name); |
@@ -796,6 +724,8 @@ static int dvb_register(struct cx8802_dev *dev) | |||
796 | dev->dvb.frontend->ops.info.frequency_min = dev->core->pll_desc->min; | 724 | dev->dvb.frontend->ops.info.frequency_min = dev->core->pll_desc->min; |
797 | dev->dvb.frontend->ops.info.frequency_max = dev->core->pll_desc->max; | 725 | dev->dvb.frontend->ops.info.frequency_max = dev->core->pll_desc->max; |
798 | } | 726 | } |
727 | /* Ensure all frontends negotiate bus access */ | ||
728 | dev->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; | ||
799 | 729 | ||
800 | /* Put the analog decoder in standby to keep it quiet */ | 730 | /* Put the analog decoder in standby to keep it quiet */ |
801 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); | 731 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); |
@@ -806,37 +736,67 @@ static int dvb_register(struct cx8802_dev *dev) | |||
806 | 736 | ||
807 | /* ----------------------------------------------------------- */ | 737 | /* ----------------------------------------------------------- */ |
808 | 738 | ||
809 | static int __devinit dvb_probe(struct pci_dev *pci_dev, | 739 | /* CX8802 MPEG -> mini driver - We have been given the hardware */ |
810 | const struct pci_device_id *pci_id) | 740 | static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv) |
811 | { | 741 | { |
812 | struct cx8802_dev *dev; | 742 | struct cx88_core *core = drv->core; |
813 | struct cx88_core *core; | 743 | int err = 0; |
744 | dprintk( 1, "%s\n", __FUNCTION__); | ||
745 | |||
746 | switch (core->board) { | ||
747 | case CX88_BOARD_HAUPPAUGE_HVR1300: | ||
748 | /* We arrive here with either the cx23416 or the cx22702 | ||
749 | * on the bus. Take the bus from the cx23416 and enable the | ||
750 | * cx22702 demod | ||
751 | */ | ||
752 | cx_set(MO_GP0_IO, 0x00000080); /* cx22702 out of reset and enable */ | ||
753 | cx_clear(MO_GP0_IO, 0x00000004); | ||
754 | udelay(1000); | ||
755 | break; | ||
756 | default: | ||
757 | err = -ENODEV; | ||
758 | } | ||
759 | return err; | ||
760 | } | ||
761 | |||
762 | /* CX8802 MPEG -> mini driver - We no longer have the hardware */ | ||
763 | static int cx8802_dvb_advise_release(struct cx8802_driver *drv) | ||
764 | { | ||
765 | struct cx88_core *core = drv->core; | ||
766 | int err = 0; | ||
767 | dprintk( 1, "%s\n", __FUNCTION__); | ||
768 | |||
769 | switch (core->board) { | ||
770 | case CX88_BOARD_HAUPPAUGE_HVR1300: | ||
771 | /* Do Nothing, leave the cx22702 on the bus. */ | ||
772 | break; | ||
773 | default: | ||
774 | err = -ENODEV; | ||
775 | } | ||
776 | return err; | ||
777 | } | ||
778 | |||
779 | static int cx8802_dvb_probe(struct cx8802_driver *drv) | ||
780 | { | ||
781 | struct cx88_core *core = drv->core; | ||
782 | struct cx8802_dev *dev = drv->core->dvbdev; | ||
814 | int err; | 783 | int err; |
815 | 784 | ||
816 | /* general setup */ | 785 | dprintk( 1, "%s\n", __FUNCTION__); |
817 | core = cx88_core_get(pci_dev); | 786 | dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", |
818 | if (NULL == core) | 787 | core->board, |
819 | return -EINVAL; | 788 | core->name, |
789 | core->pci_bus, | ||
790 | core->pci_slot); | ||
820 | 791 | ||
821 | err = -ENODEV; | 792 | err = -ENODEV; |
822 | if (!(cx88_boards[core->board].mpeg & CX88_MPEG_DVB)) | 793 | if (!(cx88_boards[core->board].mpeg & CX88_MPEG_DVB)) |
823 | goto fail_core; | 794 | goto fail_core; |
824 | 795 | ||
825 | err = -ENOMEM; | ||
826 | dev = kzalloc(sizeof(*dev),GFP_KERNEL); | ||
827 | if (NULL == dev) | ||
828 | goto fail_core; | ||
829 | dev->pci = pci_dev; | ||
830 | dev->core = core; | ||
831 | |||
832 | err = cx8802_init_common(dev); | ||
833 | if (0 != err) | ||
834 | goto fail_free; | ||
835 | |||
836 | #ifdef HAVE_VP3054_I2C | 796 | #ifdef HAVE_VP3054_I2C |
837 | err = vp3054_i2c_probe(dev); | 797 | err = vp3054_i2c_probe(dev); |
838 | if (0 != err) | 798 | if (0 != err) |
839 | goto fail_free; | 799 | goto fail_core; |
840 | #endif | 800 | #endif |
841 | 801 | ||
842 | /* dvb stuff */ | 802 | /* dvb stuff */ |
@@ -848,28 +808,16 @@ static int __devinit dvb_probe(struct pci_dev *pci_dev, | |||
848 | sizeof(struct cx88_buffer), | 808 | sizeof(struct cx88_buffer), |
849 | dev); | 809 | dev); |
850 | err = dvb_register(dev); | 810 | err = dvb_register(dev); |
851 | if (0 != err) | 811 | if (err != 0) |
852 | goto fail_fini; | 812 | printk("%s dvb_register failed err = %d\n", __FUNCTION__, err); |
853 | 813 | ||
854 | /* Maintain a reference to cx88-video can query the 8802 device. */ | ||
855 | core->dvbdev = dev; | ||
856 | return 0; | ||
857 | |||
858 | fail_fini: | ||
859 | cx8802_fini_common(dev); | ||
860 | fail_free: | ||
861 | kfree(dev); | ||
862 | fail_core: | 814 | fail_core: |
863 | cx88_core_put(core,pci_dev); | ||
864 | return err; | 815 | return err; |
865 | } | 816 | } |
866 | 817 | ||
867 | static void __devexit dvb_remove(struct pci_dev *pci_dev) | 818 | static int cx8802_dvb_remove(struct cx8802_driver *drv) |
868 | { | 819 | { |
869 | struct cx8802_dev *dev = pci_get_drvdata(pci_dev); | 820 | struct cx8802_dev *dev = drv->core->dvbdev; |
870 | |||
871 | /* Destroy any 8802 reference. */ | ||
872 | dev->core->dvbdev = NULL; | ||
873 | 821 | ||
874 | /* dvb */ | 822 | /* dvb */ |
875 | videobuf_dvb_unregister(&dev->dvb); | 823 | videobuf_dvb_unregister(&dev->dvb); |
@@ -878,33 +826,16 @@ static void __devexit dvb_remove(struct pci_dev *pci_dev) | |||
878 | vp3054_i2c_remove(dev); | 826 | vp3054_i2c_remove(dev); |
879 | #endif | 827 | #endif |
880 | 828 | ||
881 | /* common */ | 829 | return 0; |
882 | cx8802_fini_common(dev); | ||
883 | cx88_core_put(dev->core,dev->pci); | ||
884 | kfree(dev); | ||
885 | } | 830 | } |
886 | 831 | ||
887 | static struct pci_device_id cx8802_pci_tbl[] = { | 832 | static struct cx8802_driver cx8802_dvb_driver = { |
888 | { | 833 | .type_id = CX88_MPEG_DVB, |
889 | .vendor = 0x14f1, | 834 | .hw_access = CX8802_DRVCTL_SHARED, |
890 | .device = 0x8802, | 835 | .probe = cx8802_dvb_probe, |
891 | .subvendor = PCI_ANY_ID, | 836 | .remove = cx8802_dvb_remove, |
892 | .subdevice = PCI_ANY_ID, | 837 | .advise_acquire = cx8802_dvb_advise_acquire, |
893 | },{ | 838 | .advise_release = cx8802_dvb_advise_release, |
894 | /* --- end of list --- */ | ||
895 | } | ||
896 | }; | ||
897 | MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl); | ||
898 | |||
899 | static struct pci_driver dvb_pci_driver = { | ||
900 | .name = "cx88-dvb", | ||
901 | .id_table = cx8802_pci_tbl, | ||
902 | .probe = dvb_probe, | ||
903 | .remove = __devexit_p(dvb_remove), | ||
904 | #ifdef CONFIG_PM | ||
905 | .suspend = cx8802_suspend_common, | ||
906 | .resume = cx8802_resume_common, | ||
907 | #endif | ||
908 | }; | 839 | }; |
909 | 840 | ||
910 | static int dvb_init(void) | 841 | static int dvb_init(void) |
@@ -917,12 +848,12 @@ static int dvb_init(void) | |||
917 | printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", | 848 | printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", |
918 | SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); | 849 | SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); |
919 | #endif | 850 | #endif |
920 | return pci_register_driver(&dvb_pci_driver); | 851 | return cx8802_register_driver(&cx8802_dvb_driver); |
921 | } | 852 | } |
922 | 853 | ||
923 | static void dvb_fini(void) | 854 | static void dvb_fini(void) |
924 | { | 855 | { |
925 | pci_unregister_driver(&dvb_pci_driver); | 856 | cx8802_unregister_driver(&cx8802_dvb_driver); |
926 | } | 857 | } |
927 | 858 | ||
928 | module_init(dvb_init); | 859 | module_init(dvb_init); |
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index e60a0a52e4b2..8136673fe9e8 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c | |||
@@ -155,6 +155,35 @@ static void cx88_ir_work(struct work_struct *work) | |||
155 | mod_timer(&ir->timer, timeout); | 155 | mod_timer(&ir->timer, timeout); |
156 | } | 156 | } |
157 | 157 | ||
158 | static void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir) | ||
159 | { | ||
160 | if (ir->polling) { | ||
161 | INIT_WORK(&ir->work, cx88_ir_work); | ||
162 | init_timer(&ir->timer); | ||
163 | ir->timer.function = ir_timer; | ||
164 | ir->timer.data = (unsigned long)ir; | ||
165 | schedule_work(&ir->work); | ||
166 | } | ||
167 | if (ir->sampling) { | ||
168 | core->pci_irqmask |= (1 << 18); /* IR_SMP_INT */ | ||
169 | cx_write(MO_DDS_IO, 0xa80a80); /* 4 kHz sample rate */ | ||
170 | cx_write(MO_DDSCFG_IO, 0x5); /* enable */ | ||
171 | } | ||
172 | } | ||
173 | |||
174 | static void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir) | ||
175 | { | ||
176 | if (ir->sampling) { | ||
177 | cx_write(MO_DDSCFG_IO, 0x0); | ||
178 | core->pci_irqmask &= ~(1 << 18); | ||
179 | } | ||
180 | |||
181 | if (ir->polling) { | ||
182 | del_timer_sync(&ir->timer); | ||
183 | flush_scheduled_work(); | ||
184 | } | ||
185 | } | ||
186 | |||
158 | /* ---------------------------------------------------------------------- */ | 187 | /* ---------------------------------------------------------------------- */ |
159 | 188 | ||
160 | int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | 189 | int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) |
@@ -163,14 +192,12 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
163 | struct input_dev *input_dev; | 192 | struct input_dev *input_dev; |
164 | IR_KEYTAB_TYPE *ir_codes = NULL; | 193 | IR_KEYTAB_TYPE *ir_codes = NULL; |
165 | int ir_type = IR_TYPE_OTHER; | 194 | int ir_type = IR_TYPE_OTHER; |
195 | int err = -ENOMEM; | ||
166 | 196 | ||
167 | ir = kzalloc(sizeof(*ir), GFP_KERNEL); | 197 | ir = kzalloc(sizeof(*ir), GFP_KERNEL); |
168 | input_dev = input_allocate_device(); | 198 | input_dev = input_allocate_device(); |
169 | if (!ir || !input_dev) { | 199 | if (!ir || !input_dev) |
170 | kfree(ir); | 200 | goto err_out_free; |
171 | input_free_device(input_dev); | ||
172 | return -ENOMEM; | ||
173 | } | ||
174 | 201 | ||
175 | ir->input = input_dev; | 202 | ir->input = input_dev; |
176 | 203 | ||
@@ -280,9 +307,8 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
280 | } | 307 | } |
281 | 308 | ||
282 | if (NULL == ir_codes) { | 309 | if (NULL == ir_codes) { |
283 | kfree(ir); | 310 | err = -ENODEV; |
284 | input_free_device(input_dev); | 311 | goto err_out_free; |
285 | return -ENODEV; | ||
286 | } | 312 | } |
287 | 313 | ||
288 | /* init input device */ | 314 | /* init input device */ |
@@ -307,23 +333,22 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
307 | ir->core = core; | 333 | ir->core = core; |
308 | core->ir = ir; | 334 | core->ir = ir; |
309 | 335 | ||
310 | if (ir->polling) { | 336 | cx88_ir_start(core, ir); |
311 | INIT_WORK(&ir->work, cx88_ir_work); | ||
312 | init_timer(&ir->timer); | ||
313 | ir->timer.function = ir_timer; | ||
314 | ir->timer.data = (unsigned long)ir; | ||
315 | schedule_work(&ir->work); | ||
316 | } | ||
317 | if (ir->sampling) { | ||
318 | core->pci_irqmask |= (1 << 18); /* IR_SMP_INT */ | ||
319 | cx_write(MO_DDS_IO, 0xa80a80); /* 4 kHz sample rate */ | ||
320 | cx_write(MO_DDSCFG_IO, 0x5); /* enable */ | ||
321 | } | ||
322 | 337 | ||
323 | /* all done */ | 338 | /* all done */ |
324 | input_register_device(ir->input); | 339 | err = input_register_device(ir->input); |
340 | if (err) | ||
341 | goto err_out_stop; | ||
325 | 342 | ||
326 | return 0; | 343 | return 0; |
344 | |||
345 | err_out_stop: | ||
346 | cx88_ir_stop(core, ir); | ||
347 | core->ir = NULL; | ||
348 | err_out_free: | ||
349 | input_free_device(input_dev); | ||
350 | kfree(ir); | ||
351 | return err; | ||
327 | } | 352 | } |
328 | 353 | ||
329 | int cx88_ir_fini(struct cx88_core *core) | 354 | int cx88_ir_fini(struct cx88_core *core) |
@@ -334,15 +359,7 @@ int cx88_ir_fini(struct cx88_core *core) | |||
334 | if (NULL == ir) | 359 | if (NULL == ir) |
335 | return 0; | 360 | return 0; |
336 | 361 | ||
337 | if (ir->sampling) { | 362 | cx88_ir_stop(core, ir); |
338 | cx_write(MO_DDSCFG_IO, 0x0); | ||
339 | core->pci_irqmask &= ~(1 << 18); | ||
340 | } | ||
341 | if (ir->polling) { | ||
342 | del_timer(&ir->timer); | ||
343 | flush_scheduled_work(); | ||
344 | } | ||
345 | |||
346 | input_unregister_device(ir->input); | 363 | input_unregister_device(ir->input); |
347 | kfree(ir); | 364 | kfree(ir); |
348 | 365 | ||
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index 6b23a4e6f66d..1fe1a833c7c7 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c | |||
@@ -44,8 +44,12 @@ module_param(debug,int,0644); | |||
44 | MODULE_PARM_DESC(debug,"enable debug messages [mpeg]"); | 44 | MODULE_PARM_DESC(debug,"enable debug messages [mpeg]"); |
45 | 45 | ||
46 | #define dprintk(level,fmt, arg...) if (debug >= level) \ | 46 | #define dprintk(level,fmt, arg...) if (debug >= level) \ |
47 | printk(KERN_DEBUG "%s/2: " fmt, dev->core->name , ## arg) | 47 | printk(KERN_DEBUG "%s/2-mpeg: " fmt, dev->core->name, ## arg) |
48 | 48 | ||
49 | #define mpeg_dbg(level,fmt, arg...) if (debug >= level) \ | ||
50 | printk(KERN_DEBUG "%s/2-mpeg: " fmt, core->name, ## arg) | ||
51 | |||
52 | static LIST_HEAD(cx8802_devlist); | ||
49 | /* ------------------------------------------------------------------ */ | 53 | /* ------------------------------------------------------------------ */ |
50 | 54 | ||
51 | static int cx8802_start_dma(struct cx8802_dev *dev, | 55 | static int cx8802_start_dma(struct cx8802_dev *dev, |
@@ -65,17 +69,13 @@ static int cx8802_start_dma(struct cx8802_dev *dev, | |||
65 | 69 | ||
66 | /* FIXME: this needs a review. | 70 | /* FIXME: this needs a review. |
67 | * also: move to cx88-blackbird + cx88-dvb source files? */ | 71 | * also: move to cx88-blackbird + cx88-dvb source files? */ |
68 | if (cx88_boards[core->board].mpeg == (CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD) ) { | ||
69 | /* Report a warning until the mini driver patch is applied, | ||
70 | * else the following conditions will set the dma registers incorrectly. | ||
71 | * This will be removed in the next major patch and changes to the conditions | ||
72 | * will be made. | ||
73 | */ | ||
74 | printk(KERN_INFO "%s() board->(CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD) is invalid\n", __FUNCTION__); | ||
75 | return -EINVAL; | ||
76 | } | ||
77 | 72 | ||
78 | if (cx88_boards[core->board].mpeg & CX88_MPEG_DVB) { | 73 | dprintk( 1, "core->active_type_id = 0x%08x\n", core->active_type_id); |
74 | |||
75 | if ( (core->active_type_id == CX88_MPEG_DVB) && | ||
76 | (cx88_boards[core->board].mpeg & CX88_MPEG_DVB) ) { | ||
77 | |||
78 | dprintk( 1, "cx8802_start_dma doing .dvb\n"); | ||
79 | /* negedge driven & software reset */ | 79 | /* negedge driven & software reset */ |
80 | cx_write(TS_GEN_CNTRL, 0x0040 | dev->ts_gen_cntrl); | 80 | cx_write(TS_GEN_CNTRL, 0x0040 | dev->ts_gen_cntrl); |
81 | udelay(100); | 81 | udelay(100); |
@@ -93,15 +93,17 @@ static int cx8802_start_dma(struct cx8802_dev *dev, | |||
93 | cx_write(MO_PINMUX_IO, 0x88); /* Enable MPEG parallel IO and video signal pins */ | 93 | cx_write(MO_PINMUX_IO, 0x88); /* Enable MPEG parallel IO and video signal pins */ |
94 | udelay(100); | 94 | udelay(100); |
95 | break; | 95 | break; |
96 | case CX88_BOARD_HAUPPAUGE_HVR1300: | ||
97 | break; | ||
96 | default: | 98 | default: |
97 | cx_write(TS_SOP_STAT, 0x00); | 99 | cx_write(TS_SOP_STAT, 0x00); |
98 | break; | 100 | break; |
99 | } | 101 | } |
100 | cx_write(TS_GEN_CNTRL, dev->ts_gen_cntrl); | 102 | cx_write(TS_GEN_CNTRL, dev->ts_gen_cntrl); |
101 | udelay(100); | 103 | udelay(100); |
102 | } | 104 | } else if ( (core->active_type_id == CX88_MPEG_BLACKBIRD) && |
103 | 105 | (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) ) { | |
104 | if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) { | 106 | dprintk( 1, "cx8802_start_dma doing .blackbird\n"); |
105 | cx_write(MO_PINMUX_IO, 0x88); /* enable MPEG parallel IO */ | 107 | cx_write(MO_PINMUX_IO, 0x88); /* enable MPEG parallel IO */ |
106 | 108 | ||
107 | cx_write(TS_GEN_CNTRL, 0x46); /* punctured clock TS & posedge driven & software reset */ | 109 | cx_write(TS_GEN_CNTRL, 0x46); /* punctured clock TS & posedge driven & software reset */ |
@@ -112,6 +114,10 @@ static int cx8802_start_dma(struct cx8802_dev *dev, | |||
112 | 114 | ||
113 | cx_write(TS_GEN_CNTRL, 0x06); /* punctured clock TS & posedge driven */ | 115 | cx_write(TS_GEN_CNTRL, 0x06); /* punctured clock TS & posedge driven */ |
114 | udelay(100); | 116 | udelay(100); |
117 | } else { | ||
118 | printk( "%s() Failed. Unsupported value in .mpeg (0x%08x)\n", __FUNCTION__, | ||
119 | cx88_boards[core->board].mpeg ); | ||
120 | return -EINVAL; | ||
115 | } | 121 | } |
116 | 122 | ||
117 | /* reset counter */ | 123 | /* reset counter */ |
@@ -542,8 +548,315 @@ int cx8802_resume_common(struct pci_dev *pci_dev) | |||
542 | return 0; | 548 | return 0; |
543 | } | 549 | } |
544 | 550 | ||
551 | struct cx8802_dev * cx8802_get_device(struct inode *inode) | ||
552 | { | ||
553 | int minor = iminor(inode); | ||
554 | struct cx8802_dev *h = NULL; | ||
555 | struct list_head *list; | ||
556 | |||
557 | list_for_each(list,&cx8802_devlist) { | ||
558 | h = list_entry(list, struct cx8802_dev, devlist); | ||
559 | if (h->mpeg_dev->minor == minor) | ||
560 | return h; | ||
561 | } | ||
562 | |||
563 | return NULL; | ||
564 | } | ||
565 | |||
566 | struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype) | ||
567 | { | ||
568 | struct cx8802_dev *h = NULL; | ||
569 | struct cx8802_driver *d = NULL; | ||
570 | struct list_head *list; | ||
571 | struct list_head *list2; | ||
572 | |||
573 | list_for_each(list,&cx8802_devlist) { | ||
574 | h = list_entry(list, struct cx8802_dev, devlist); | ||
575 | if (h != dev) | ||
576 | continue; | ||
577 | |||
578 | list_for_each(list2, &h->drvlist.devlist) { | ||
579 | d = list_entry(list2, struct cx8802_driver, devlist); | ||
580 | |||
581 | /* only unregister the correct driver type */ | ||
582 | if (d->type_id == btype) { | ||
583 | return d; | ||
584 | } | ||
585 | } | ||
586 | } | ||
587 | |||
588 | return NULL; | ||
589 | } | ||
590 | |||
591 | /* Driver asked for hardware access. */ | ||
592 | int cx8802_request_acquire(struct cx8802_driver *drv) | ||
593 | { | ||
594 | struct cx88_core *core = drv->core; | ||
595 | |||
596 | /* Fail a request for hardware if the device is busy. */ | ||
597 | if (core->active_type_id != CX88_BOARD_NONE) | ||
598 | return -EBUSY; | ||
599 | |||
600 | if (drv->advise_acquire) | ||
601 | { | ||
602 | core->active_type_id = drv->type_id; | ||
603 | drv->advise_acquire(drv); | ||
604 | |||
605 | mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO)); | ||
606 | } | ||
607 | |||
608 | return 0; | ||
609 | } | ||
610 | |||
611 | /* Driver asked to release hardware. */ | ||
612 | int cx8802_request_release(struct cx8802_driver *drv) | ||
613 | { | ||
614 | struct cx88_core *core = drv->core; | ||
615 | |||
616 | if (drv->advise_release) | ||
617 | { | ||
618 | drv->advise_release(drv); | ||
619 | core->active_type_id = CX88_BOARD_NONE; | ||
620 | mpeg_dbg(1,"%s() Post release GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO)); | ||
621 | } | ||
622 | |||
623 | return 0; | ||
624 | } | ||
625 | |||
626 | static int cx8802_check_driver(struct cx8802_driver *drv) | ||
627 | { | ||
628 | if (drv == NULL) | ||
629 | return -ENODEV; | ||
630 | |||
631 | if ((drv->type_id != CX88_MPEG_DVB) && | ||
632 | (drv->type_id != CX88_MPEG_BLACKBIRD)) | ||
633 | return -EINVAL; | ||
634 | |||
635 | if ((drv->hw_access != CX8802_DRVCTL_SHARED) && | ||
636 | (drv->hw_access != CX8802_DRVCTL_EXCLUSIVE)) | ||
637 | return -EINVAL; | ||
638 | |||
639 | if ((drv->probe == NULL) || | ||
640 | (drv->remove == NULL) || | ||
641 | (drv->advise_acquire == NULL) || | ||
642 | (drv->advise_release == NULL)) | ||
643 | return -EINVAL; | ||
644 | |||
645 | return 0; | ||
646 | } | ||
647 | |||
648 | int cx8802_register_driver(struct cx8802_driver *drv) | ||
649 | { | ||
650 | struct cx8802_dev *h; | ||
651 | struct cx8802_driver *driver; | ||
652 | struct list_head *list; | ||
653 | int err = 0, i = 0; | ||
654 | |||
655 | printk(KERN_INFO "%s() ->registering driver type=%s access=%s\n", __FUNCTION__ , | ||
656 | drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird", | ||
657 | drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive"); | ||
658 | |||
659 | if ((err = cx8802_check_driver(drv)) != 0) { | ||
660 | printk(KERN_INFO "%s() cx8802_driver is invalid\n", __FUNCTION__ ); | ||
661 | return err; | ||
662 | } | ||
663 | |||
664 | list_for_each(list,&cx8802_devlist) { | ||
665 | h = list_entry(list, struct cx8802_dev, devlist); | ||
666 | |||
667 | printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d]\n", | ||
668 | h->core->name,h->pci->subsystem_vendor, | ||
669 | h->pci->subsystem_device,cx88_boards[h->core->board].name, | ||
670 | h->core->board); | ||
671 | |||
672 | /* Bring up a new struct for each driver instance */ | ||
673 | driver = kzalloc(sizeof(*drv),GFP_KERNEL); | ||
674 | if (driver == NULL) | ||
675 | return -ENOMEM; | ||
676 | |||
677 | /* Snapshot of the driver registration data */ | ||
678 | drv->core = h->core; | ||
679 | drv->suspend = cx8802_suspend_common; | ||
680 | drv->resume = cx8802_resume_common; | ||
681 | drv->request_acquire = cx8802_request_acquire; | ||
682 | drv->request_release = cx8802_request_release; | ||
683 | memcpy(driver, drv, sizeof(*driver)); | ||
684 | |||
685 | err = drv->probe(driver); | ||
686 | if (err == 0) { | ||
687 | i++; | ||
688 | mutex_lock(&drv->core->lock); | ||
689 | list_add_tail(&driver->devlist,&h->drvlist.devlist); | ||
690 | mutex_unlock(&drv->core->lock); | ||
691 | } else { | ||
692 | printk(KERN_ERR "%s() ->probe failed err = %d\n", __FUNCTION__, err); | ||
693 | } | ||
694 | |||
695 | } | ||
696 | if (i == 0) | ||
697 | err = -ENODEV; | ||
698 | else | ||
699 | err = 0; | ||
700 | |||
701 | return err; | ||
702 | } | ||
703 | |||
704 | int cx8802_unregister_driver(struct cx8802_driver *drv) | ||
705 | { | ||
706 | struct cx8802_dev *h; | ||
707 | struct cx8802_driver *d; | ||
708 | struct list_head *list; | ||
709 | struct list_head *list2, *q; | ||
710 | int err = 0, i = 0; | ||
711 | |||
712 | printk(KERN_INFO "%s() ->unregistering driver type=%s\n", __FUNCTION__ , | ||
713 | drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird"); | ||
714 | |||
715 | list_for_each(list,&cx8802_devlist) { | ||
716 | i++; | ||
717 | h = list_entry(list, struct cx8802_dev, devlist); | ||
718 | |||
719 | printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d]\n", | ||
720 | h->core->name,h->pci->subsystem_vendor, | ||
721 | h->pci->subsystem_device,cx88_boards[h->core->board].name, | ||
722 | h->core->board); | ||
723 | |||
724 | list_for_each_safe(list2, q, &h->drvlist.devlist) { | ||
725 | d = list_entry(list2, struct cx8802_driver, devlist); | ||
726 | |||
727 | /* only unregister the correct driver type */ | ||
728 | if (d->type_id != drv->type_id) | ||
729 | continue; | ||
730 | |||
731 | err = d->remove(d); | ||
732 | if (err == 0) { | ||
733 | mutex_lock(&drv->core->lock); | ||
734 | list_del(list2); | ||
735 | mutex_unlock(&drv->core->lock); | ||
736 | } else | ||
737 | printk(KERN_ERR "%s() ->remove failed err = %d\n", __FUNCTION__, err); | ||
738 | |||
739 | } | ||
740 | |||
741 | } | ||
742 | |||
743 | return err; | ||
744 | } | ||
745 | |||
545 | /* ----------------------------------------------------------- */ | 746 | /* ----------------------------------------------------------- */ |
747 | static int __devinit cx8802_probe(struct pci_dev *pci_dev, | ||
748 | const struct pci_device_id *pci_id) | ||
749 | { | ||
750 | struct cx8802_dev *dev; | ||
751 | struct cx88_core *core; | ||
752 | int err; | ||
753 | |||
754 | /* general setup */ | ||
755 | core = cx88_core_get(pci_dev); | ||
756 | if (NULL == core) | ||
757 | return -EINVAL; | ||
546 | 758 | ||
759 | printk("%s/2: cx2388x 8802 Driver Manager\n", core->name); | ||
760 | |||
761 | err = -ENODEV; | ||
762 | if (!cx88_boards[core->board].mpeg) | ||
763 | goto fail_core; | ||
764 | |||
765 | err = -ENOMEM; | ||
766 | dev = kzalloc(sizeof(*dev),GFP_KERNEL); | ||
767 | if (NULL == dev) | ||
768 | goto fail_core; | ||
769 | dev->pci = pci_dev; | ||
770 | dev->core = core; | ||
771 | |||
772 | err = cx8802_init_common(dev); | ||
773 | if (err != 0) | ||
774 | goto fail_free; | ||
775 | |||
776 | INIT_LIST_HEAD(&dev->drvlist.devlist); | ||
777 | list_add_tail(&dev->devlist,&cx8802_devlist); | ||
778 | |||
779 | /* Maintain a reference so cx88-video can query the 8802 device. */ | ||
780 | core->dvbdev = dev; | ||
781 | return 0; | ||
782 | |||
783 | fail_free: | ||
784 | kfree(dev); | ||
785 | fail_core: | ||
786 | cx88_core_put(core,pci_dev); | ||
787 | return err; | ||
788 | } | ||
789 | |||
790 | static void __devexit cx8802_remove(struct pci_dev *pci_dev) | ||
791 | { | ||
792 | struct cx8802_dev *dev; | ||
793 | struct cx8802_driver *h; | ||
794 | struct list_head *list; | ||
795 | |||
796 | dev = pci_get_drvdata(pci_dev); | ||
797 | |||
798 | dprintk( 1, "%s\n", __FUNCTION__); | ||
799 | |||
800 | list_for_each(list,&dev->drvlist.devlist) { | ||
801 | h = list_entry(list, struct cx8802_driver, devlist); | ||
802 | dprintk( 1, " ->driver\n"); | ||
803 | if (h->remove == NULL) { | ||
804 | printk(KERN_ERR "%s .. skipping driver, no probe function\n", __FUNCTION__); | ||
805 | continue; | ||
806 | } | ||
807 | printk(KERN_INFO "%s .. Removing driver type %d\n", __FUNCTION__, h->type_id); | ||
808 | cx8802_unregister_driver(h); | ||
809 | list_del(&dev->drvlist.devlist); | ||
810 | } | ||
811 | |||
812 | /* Destroy any 8802 reference. */ | ||
813 | dev->core->dvbdev = NULL; | ||
814 | |||
815 | /* common */ | ||
816 | cx8802_fini_common(dev); | ||
817 | cx88_core_put(dev->core,dev->pci); | ||
818 | kfree(dev); | ||
819 | } | ||
820 | |||
821 | static struct pci_device_id cx8802_pci_tbl[] = { | ||
822 | { | ||
823 | .vendor = 0x14f1, | ||
824 | .device = 0x8802, | ||
825 | .subvendor = PCI_ANY_ID, | ||
826 | .subdevice = PCI_ANY_ID, | ||
827 | },{ | ||
828 | /* --- end of list --- */ | ||
829 | } | ||
830 | }; | ||
831 | MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl); | ||
832 | |||
833 | static struct pci_driver cx8802_pci_driver = { | ||
834 | .name = "cx88-mpeg driver manager", | ||
835 | .id_table = cx8802_pci_tbl, | ||
836 | .probe = cx8802_probe, | ||
837 | .remove = __devexit_p(cx8802_remove), | ||
838 | }; | ||
839 | |||
840 | static int cx8802_init(void) | ||
841 | { | ||
842 | printk(KERN_INFO "cx2388x cx88-mpeg Driver Manager version %d.%d.%d loaded\n", | ||
843 | (CX88_VERSION_CODE >> 16) & 0xff, | ||
844 | (CX88_VERSION_CODE >> 8) & 0xff, | ||
845 | CX88_VERSION_CODE & 0xff); | ||
846 | #ifdef SNAPSHOT | ||
847 | printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", | ||
848 | SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); | ||
849 | #endif | ||
850 | return pci_register_driver(&cx8802_pci_driver); | ||
851 | } | ||
852 | |||
853 | static void cx8802_fini(void) | ||
854 | { | ||
855 | pci_unregister_driver(&cx8802_pci_driver); | ||
856 | } | ||
857 | |||
858 | module_init(cx8802_init); | ||
859 | module_exit(cx8802_fini); | ||
547 | EXPORT_SYMBOL(cx8802_buf_prepare); | 860 | EXPORT_SYMBOL(cx8802_buf_prepare); |
548 | EXPORT_SYMBOL(cx8802_buf_queue); | 861 | EXPORT_SYMBOL(cx8802_buf_queue); |
549 | EXPORT_SYMBOL(cx8802_cancel_buffers); | 862 | EXPORT_SYMBOL(cx8802_cancel_buffers); |
@@ -551,9 +864,10 @@ EXPORT_SYMBOL(cx8802_cancel_buffers); | |||
551 | EXPORT_SYMBOL(cx8802_init_common); | 864 | EXPORT_SYMBOL(cx8802_init_common); |
552 | EXPORT_SYMBOL(cx8802_fini_common); | 865 | EXPORT_SYMBOL(cx8802_fini_common); |
553 | 866 | ||
554 | EXPORT_SYMBOL(cx8802_suspend_common); | 867 | EXPORT_SYMBOL(cx8802_register_driver); |
555 | EXPORT_SYMBOL(cx8802_resume_common); | 868 | EXPORT_SYMBOL(cx8802_unregister_driver); |
556 | 869 | EXPORT_SYMBOL(cx8802_get_device); | |
870 | EXPORT_SYMBOL(cx8802_get_driver); | ||
557 | /* ----------------------------------------------------------- */ | 871 | /* ----------------------------------------------------------- */ |
558 | /* | 872 | /* |
559 | * Local variables: | 873 | * Local variables: |
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c index 58ba9f773524..3482e0114d43 100644 --- a/drivers/media/video/cx88/cx88-tvaudio.c +++ b/drivers/media/video/cx88/cx88-tvaudio.c | |||
@@ -143,19 +143,6 @@ static void set_audio_finish(struct cx88_core *core, u32 ctl) | |||
143 | cx88_start_audio_dma(core); | 143 | cx88_start_audio_dma(core); |
144 | 144 | ||
145 | if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) { | 145 | if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) { |
146 | /* sets sound input from external adc */ | ||
147 | switch (core->board) { | ||
148 | case CX88_BOARD_HAUPPAUGE_ROSLYN: | ||
149 | case CX88_BOARD_KWORLD_MCE200_DELUXE: | ||
150 | case CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT: | ||
151 | case CX88_BOARD_PIXELVIEW_PLAYTV_P7000: | ||
152 | case CX88_BOARD_ASUS_PVR_416: | ||
153 | cx_clear(AUD_CTL, EN_I2SIN_ENABLE); | ||
154 | break; | ||
155 | default: | ||
156 | cx_set(AUD_CTL, EN_I2SIN_ENABLE); | ||
157 | } | ||
158 | |||
159 | cx_write(AUD_I2SINPUTCNTL, 4); | 146 | cx_write(AUD_I2SINPUTCNTL, 4); |
160 | cx_write(AUD_BAUDRATE, 1); | 147 | cx_write(AUD_BAUDRATE, 1); |
161 | /* 'pass-thru mode': this enables the i2s output to the mpeg encoder */ | 148 | /* 'pass-thru mode': this enables the i2s output to the mpeg encoder */ |
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 90e298d074d1..8613378428fd 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c | |||
@@ -454,6 +454,14 @@ static int video_mux(struct cx88_core *core, unsigned int input) | |||
454 | cx_clear(MO_FILTER_ODD, 0x00002020); | 454 | cx_clear(MO_FILTER_ODD, 0x00002020); |
455 | break; | 455 | break; |
456 | } | 456 | } |
457 | |||
458 | if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) { | ||
459 | /* sets sound input from external adc */ | ||
460 | if (INPUT(input)->extadc) | ||
461 | cx_set(AUD_CTL, EN_I2SIN_ENABLE); | ||
462 | else | ||
463 | cx_clear(AUD_CTL, EN_I2SIN_ENABLE); | ||
464 | } | ||
457 | return 0; | 465 | return 0; |
458 | } | 466 | } |
459 | 467 | ||
@@ -1490,6 +1498,30 @@ int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, | |||
1490 | mutex_unlock(&core->lock); | 1498 | mutex_unlock(&core->lock); |
1491 | return 0; | 1499 | return 0; |
1492 | } | 1500 | } |
1501 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
1502 | /* ioctls to allow direct acces to the cx2388x registers */ | ||
1503 | case VIDIOC_INT_G_REGISTER: | ||
1504 | { | ||
1505 | struct v4l2_register *reg = arg; | ||
1506 | |||
1507 | if (reg->i2c_id != 0) | ||
1508 | return -EINVAL; | ||
1509 | /* cx2388x has a 24-bit register space */ | ||
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 | |||
1517 | if (reg->i2c_id != 0) | ||
1518 | return -EINVAL; | ||
1519 | if (!capable(CAP_SYS_ADMIN)) | ||
1520 | return -EPERM; | ||
1521 | cx_write(reg->reg&0xffffff, reg->val); | ||
1522 | return 0; | ||
1523 | } | ||
1524 | #endif | ||
1493 | 1525 | ||
1494 | default: | 1526 | default: |
1495 | return v4l_compat_translate_ioctl(inode,file,cmd,arg, | 1527 | return v4l_compat_translate_ioctl(inode,file,cmd,arg, |
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 3bc91aad4fe5..7054e941f1d7 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h | |||
@@ -74,6 +74,11 @@ enum cx88_board_type { | |||
74 | CX88_MPEG_BLACKBIRD | 74 | CX88_MPEG_BLACKBIRD |
75 | }; | 75 | }; |
76 | 76 | ||
77 | enum cx8802_board_access { | ||
78 | CX8802_DRVCTL_SHARED = 1, | ||
79 | CX8802_DRVCTL_EXCLUSIVE = 2, | ||
80 | }; | ||
81 | |||
77 | /* ----------------------------------------------------------- */ | 82 | /* ----------------------------------------------------------- */ |
78 | /* tv norms */ | 83 | /* tv norms */ |
79 | 84 | ||
@@ -220,6 +225,7 @@ struct cx88_input { | |||
220 | enum cx88_itype type; | 225 | enum cx88_itype type; |
221 | unsigned int vmux; | 226 | unsigned int vmux; |
222 | u32 gpio0, gpio1, gpio2, gpio3; | 227 | u32 gpio0, gpio1, gpio2, gpio3; |
228 | unsigned int extadc:1; | ||
223 | }; | 229 | }; |
224 | 230 | ||
225 | struct cx88_board { | 231 | struct cx88_board { |
@@ -330,6 +336,7 @@ struct cx88_core { | |||
330 | 336 | ||
331 | /* cx88-video needs to access cx8802 for hybrid tuner pll access. */ | 337 | /* cx88-video needs to access cx8802 for hybrid tuner pll access. */ |
332 | struct cx8802_dev *dvbdev; | 338 | struct cx8802_dev *dvbdev; |
339 | enum cx88_board_type active_type_id; | ||
333 | }; | 340 | }; |
334 | 341 | ||
335 | struct cx8800_dev; | 342 | struct cx8800_dev; |
@@ -405,6 +412,31 @@ struct cx8802_suspend_state { | |||
405 | int disabled; | 412 | int disabled; |
406 | }; | 413 | }; |
407 | 414 | ||
415 | struct cx8802_driver { | ||
416 | struct cx88_core *core; | ||
417 | struct list_head devlist; | ||
418 | |||
419 | /* Type of driver and access required */ | ||
420 | enum cx88_board_type type_id; | ||
421 | enum cx8802_board_access hw_access; | ||
422 | |||
423 | /* MPEG 8802 internal only */ | ||
424 | int (*suspend)(struct pci_dev *pci_dev, pm_message_t state); | ||
425 | int (*resume)(struct pci_dev *pci_dev); | ||
426 | |||
427 | /* MPEG 8802 -> mini driver - Driver probe and configuration */ | ||
428 | int (*probe)(struct cx8802_driver *drv); | ||
429 | int (*remove)(struct cx8802_driver *drv); | ||
430 | |||
431 | /* MPEG 8802 -> mini driver - Access for hardware control */ | ||
432 | int (*advise_acquire)(struct cx8802_driver *drv); | ||
433 | int (*advise_release)(struct cx8802_driver *drv); | ||
434 | |||
435 | /* MPEG 8802 <- mini driver - Access for hardware control */ | ||
436 | int (*request_acquire)(struct cx8802_driver *drv); | ||
437 | int (*request_release)(struct cx8802_driver *drv); | ||
438 | }; | ||
439 | |||
408 | struct cx8802_dev { | 440 | struct cx8802_dev { |
409 | struct cx88_core *core; | 441 | struct cx88_core *core; |
410 | spinlock_t slock; | 442 | spinlock_t slock; |
@@ -439,6 +471,9 @@ struct cx8802_dev { | |||
439 | 471 | ||
440 | /* mpeg params */ | 472 | /* mpeg params */ |
441 | struct cx2341x_mpeg_params params; | 473 | struct cx2341x_mpeg_params params; |
474 | |||
475 | /* List of attached drivers */ | ||
476 | struct cx8802_driver drvlist; | ||
442 | }; | 477 | }; |
443 | 478 | ||
444 | /* ----------------------------------------------------------- */ | 479 | /* ----------------------------------------------------------- */ |
@@ -571,6 +606,11 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t); | |||
571 | void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual); | 606 | void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual); |
572 | int cx88_audio_thread(void *data); | 607 | int cx88_audio_thread(void *data); |
573 | 608 | ||
609 | int cx8802_register_driver(struct cx8802_driver *drv); | ||
610 | int cx8802_unregister_driver(struct cx8802_driver *drv); | ||
611 | struct cx8802_dev * cx8802_get_device(struct inode *inode); | ||
612 | struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype); | ||
613 | |||
574 | /* ----------------------------------------------------------- */ | 614 | /* ----------------------------------------------------------- */ |
575 | /* cx88-input.c */ | 615 | /* cx88-input.c */ |
576 | 616 | ||
@@ -600,6 +640,13 @@ extern int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, | |||
600 | extern const u32 cx88_user_ctrls[]; | 640 | extern const u32 cx88_user_ctrls[]; |
601 | extern int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl); | 641 | extern int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl); |
602 | 642 | ||
643 | /* ----------------------------------------------------------- */ | ||
644 | /* cx88-blackbird.c */ | ||
645 | /* used by cx88-ivtv ioctl emulation layer */ | ||
646 | extern int (*cx88_ioctl_hook)(struct inode *inode, struct file *file, | ||
647 | unsigned int cmd, void *arg); | ||
648 | extern unsigned int (*cx88_ioctl_translator)(unsigned int cmd); | ||
649 | |||
603 | /* | 650 | /* |
604 | * Local variables: | 651 | * Local variables: |
605 | * c-basic-offset: 8 | 652 | * c-basic-offset: 8 |
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index ab87e7bfe84f..59edf58204de 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c | |||
@@ -305,15 +305,14 @@ static int ir_attach(struct i2c_adapter *adap, int addr, | |||
305 | int ir_type; | 305 | int ir_type; |
306 | struct IR_i2c *ir; | 306 | struct IR_i2c *ir; |
307 | struct input_dev *input_dev; | 307 | struct input_dev *input_dev; |
308 | int err; | ||
308 | 309 | ||
309 | ir = kzalloc(sizeof(struct IR_i2c),GFP_KERNEL); | 310 | ir = kzalloc(sizeof(struct IR_i2c),GFP_KERNEL); |
310 | input_dev = input_allocate_device(); | 311 | input_dev = input_allocate_device(); |
311 | if (!ir || !input_dev) { | 312 | if (!ir || !input_dev) { |
312 | input_free_device(input_dev); | 313 | err = -ENOMEM; |
313 | kfree(ir); | 314 | goto err_out_free; |
314 | return -ENOMEM; | ||
315 | } | 315 | } |
316 | memset(ir,0,sizeof(*ir)); | ||
317 | 316 | ||
318 | ir->c = client_template; | 317 | ir->c = client_template; |
319 | ir->input = input_dev; | 318 | ir->input = input_dev; |
@@ -355,32 +354,34 @@ static int ir_attach(struct i2c_adapter *adap, int addr, | |||
355 | break; | 354 | break; |
356 | case 0x7a: | 355 | case 0x7a: |
357 | case 0x47: | 356 | case 0x47: |
357 | case 0x71: | ||
358 | /* Handled by saa7134-input */ | 358 | /* Handled by saa7134-input */ |
359 | name = "SAA713x remote"; | 359 | name = "SAA713x remote"; |
360 | ir_type = IR_TYPE_OTHER; | 360 | ir_type = IR_TYPE_OTHER; |
361 | break; | 361 | break; |
362 | default: | 362 | default: |
363 | /* shouldn't happen */ | 363 | /* shouldn't happen */ |
364 | printk(DEVNAME ": Huh? unknown i2c address (0x%02x)?\n",addr); | 364 | printk(DEVNAME ": Huh? unknown i2c address (0x%02x)?\n", addr); |
365 | kfree(ir); | 365 | err = -ENODEV; |
366 | return -1; | 366 | goto err_out_free; |
367 | } | 367 | } |
368 | 368 | ||
369 | /* Sets name */ | 369 | /* Sets name */ |
370 | snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (%s)", name); | 370 | snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (%s)", name); |
371 | ir->ir_codes=ir_codes; | 371 | ir->ir_codes = ir_codes; |
372 | 372 | ||
373 | /* register i2c device | 373 | /* register i2c device |
374 | * At device register, IR codes may be changed to be | 374 | * At device register, IR codes may be changed to be |
375 | * board dependent. | 375 | * board dependent. |
376 | */ | 376 | */ |
377 | i2c_attach_client(&ir->c); | 377 | err = i2c_attach_client(&ir->c); |
378 | if (err) | ||
379 | goto err_out_free; | ||
378 | 380 | ||
379 | /* If IR not supported or disabled, unregisters driver */ | 381 | /* If IR not supported or disabled, unregisters driver */ |
380 | if (ir->get_key == NULL) { | 382 | if (ir->get_key == NULL) { |
381 | i2c_detach_client(&ir->c); | 383 | err = -ENODEV; |
382 | kfree(ir); | 384 | goto err_out_detach; |
383 | return -1; | ||
384 | } | 385 | } |
385 | 386 | ||
386 | /* Phys addr can only be set after attaching (for ir->c.dev.bus_id) */ | 387 | /* Phys addr can only be set after attaching (for ir->c.dev.bus_id) */ |
@@ -389,15 +390,17 @@ static int ir_attach(struct i2c_adapter *adap, int addr, | |||
389 | ir->c.dev.bus_id); | 390 | ir->c.dev.bus_id); |
390 | 391 | ||
391 | /* init + register input device */ | 392 | /* init + register input device */ |
392 | ir_input_init(input_dev,&ir->ir,ir_type,ir->ir_codes); | 393 | ir_input_init(input_dev, &ir->ir, ir_type, ir->ir_codes); |
393 | input_dev->id.bustype = BUS_I2C; | 394 | input_dev->id.bustype = BUS_I2C; |
394 | input_dev->name = ir->c.name; | 395 | input_dev->name = ir->c.name; |
395 | input_dev->phys = ir->phys; | 396 | input_dev->phys = ir->phys; |
396 | 397 | ||
397 | /* register event device */ | 398 | err = input_register_device(ir->input); |
398 | input_register_device(ir->input); | 399 | if (err) |
400 | goto err_out_detach; | ||
401 | |||
399 | printk(DEVNAME ": %s detected at %s [%s]\n", | 402 | printk(DEVNAME ": %s detected at %s [%s]\n", |
400 | ir->input->name,ir->input->phys,adap->name); | 403 | ir->input->name, ir->input->phys, adap->name); |
401 | 404 | ||
402 | /* start polling via eventd */ | 405 | /* start polling via eventd */ |
403 | INIT_WORK(&ir->work, ir_work); | 406 | INIT_WORK(&ir->work, ir_work); |
@@ -407,6 +410,13 @@ static int ir_attach(struct i2c_adapter *adap, int addr, | |||
407 | schedule_work(&ir->work); | 410 | schedule_work(&ir->work); |
408 | 411 | ||
409 | return 0; | 412 | return 0; |
413 | |||
414 | err_out_detach: | ||
415 | i2c_detach_client(&ir->c); | ||
416 | err_out_free: | ||
417 | input_free_device(input_dev); | ||
418 | kfree(ir); | ||
419 | return err; | ||
410 | } | 420 | } |
411 | 421 | ||
412 | static int ir_detach(struct i2c_client *client) | 422 | static int ir_detach(struct i2c_client *client) |
@@ -414,7 +424,7 @@ static int ir_detach(struct i2c_client *client) | |||
414 | struct IR_i2c *ir = i2c_get_clientdata(client); | 424 | struct IR_i2c *ir = i2c_get_clientdata(client); |
415 | 425 | ||
416 | /* kill outstanding polls */ | 426 | /* kill outstanding polls */ |
417 | del_timer(&ir->timer); | 427 | del_timer_sync(&ir->timer); |
418 | flush_scheduled_work(); | 428 | flush_scheduled_work(); |
419 | 429 | ||
420 | /* unregister devices */ | 430 | /* unregister devices */ |
@@ -439,7 +449,7 @@ static int ir_probe(struct i2c_adapter *adap) | |||
439 | */ | 449 | */ |
440 | 450 | ||
441 | static const int probe_bttv[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1}; | 451 | static const int probe_bttv[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1}; |
442 | static const int probe_saa7134[] = { 0x7a, 0x47, -1 }; | 452 | static const int probe_saa7134[] = { 0x7a, 0x47, 0x71, -1 }; |
443 | static const int probe_em28XX[] = { 0x30, 0x47, -1 }; | 453 | static const int probe_em28XX[] = { 0x30, 0x47, -1 }; |
444 | const int *probe = NULL; | 454 | const int *probe = NULL; |
445 | struct i2c_client c; | 455 | struct i2c_client c; |
diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index b0aea4002d11..152cc6b3e152 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c | |||
@@ -160,10 +160,6 @@ static int mxb_probe(struct saa7146_dev* dev) | |||
160 | printk("mxb: saa7111 i2c module not available.\n"); | 160 | printk("mxb: saa7111 i2c module not available.\n"); |
161 | return -ENODEV; | 161 | return -ENODEV; |
162 | } | 162 | } |
163 | if ((result = request_module("tuner")) < 0) { | ||
164 | printk("mxb: tuner i2c module not available.\n"); | ||
165 | return -ENODEV; | ||
166 | } | ||
167 | if ((result = request_module("tea6420")) < 0) { | 163 | if ((result = request_module("tea6420")) < 0) { |
168 | printk("mxb: tea6420 i2c module not available.\n"); | 164 | printk("mxb: tea6420 i2c module not available.\n"); |
169 | return -ENODEV; | 165 | return -ENODEV; |
@@ -176,6 +172,10 @@ static int mxb_probe(struct saa7146_dev* dev) | |||
176 | printk("mxb: tda9840 i2c module not available.\n"); | 172 | printk("mxb: tda9840 i2c module not available.\n"); |
177 | return -ENODEV; | 173 | return -ENODEV; |
178 | } | 174 | } |
175 | if ((result = request_module("tuner")) < 0) { | ||
176 | printk("mxb: tuner i2c module not available.\n"); | ||
177 | return -ENODEV; | ||
178 | } | ||
179 | 179 | ||
180 | mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL); | 180 | mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL); |
181 | if( NULL == mxb ) { | 181 | if( NULL == mxb ) { |
diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c new file mode 100644 index 000000000000..89dd18c3c5cc --- /dev/null +++ b/drivers/media/video/ov7670.c | |||
@@ -0,0 +1,1333 @@ | |||
1 | /* | ||
2 | * A V4L2 driver for OmniVision OV7670 cameras. | ||
3 | * | ||
4 | * Copyright 2006 One Laptop Per Child Association, Inc. Written | ||
5 | * by Jonathan Corbet with substantial inspiration from Mark | ||
6 | * McClelland's ovcamchip code. | ||
7 | * | ||
8 | * This file may be distributed under the terms of the GNU General | ||
9 | * Public License, version 2. | ||
10 | */ | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/moduleparam.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/videodev.h> | ||
17 | #include <media/v4l2-common.h> | ||
18 | #include <linux/i2c.h> | ||
19 | |||
20 | |||
21 | MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net."); | ||
22 | MODULE_DESCRIPTION("A low-level driver for OmniVision ov7670 sensors"); | ||
23 | MODULE_LICENSE("GPL"); | ||
24 | |||
25 | /* | ||
26 | * Basic window sizes. These probably belong somewhere more globally | ||
27 | * useful. | ||
28 | */ | ||
29 | #define VGA_WIDTH 640 | ||
30 | #define VGA_HEIGHT 480 | ||
31 | #define QVGA_WIDTH 320 | ||
32 | #define QVGA_HEIGHT 240 | ||
33 | #define CIF_WIDTH 352 | ||
34 | #define CIF_HEIGHT 288 | ||
35 | #define QCIF_WIDTH 176 | ||
36 | #define QCIF_HEIGHT 144 | ||
37 | |||
38 | /* | ||
39 | * Our nominal (default) frame rate. | ||
40 | */ | ||
41 | #define OV7670_FRAME_RATE 30 | ||
42 | |||
43 | /* | ||
44 | * The 7670 sits on i2c with ID 0x42 | ||
45 | */ | ||
46 | #define OV7670_I2C_ADDR 0x42 | ||
47 | |||
48 | /* Registers */ | ||
49 | #define REG_GAIN 0x00 /* Gain lower 8 bits (rest in vref) */ | ||
50 | #define REG_BLUE 0x01 /* blue gain */ | ||
51 | #define REG_RED 0x02 /* red gain */ | ||
52 | #define REG_VREF 0x03 /* Pieces of GAIN, VSTART, VSTOP */ | ||
53 | #define REG_COM1 0x04 /* Control 1 */ | ||
54 | #define COM1_CCIR656 0x40 /* CCIR656 enable */ | ||
55 | #define REG_BAVE 0x05 /* U/B Average level */ | ||
56 | #define REG_GbAVE 0x06 /* Y/Gb Average level */ | ||
57 | #define REG_AECHH 0x07 /* AEC MS 5 bits */ | ||
58 | #define REG_RAVE 0x08 /* V/R Average level */ | ||
59 | #define REG_COM2 0x09 /* Control 2 */ | ||
60 | #define COM2_SSLEEP 0x10 /* Soft sleep mode */ | ||
61 | #define REG_PID 0x0a /* Product ID MSB */ | ||
62 | #define REG_VER 0x0b /* Product ID LSB */ | ||
63 | #define REG_COM3 0x0c /* Control 3 */ | ||
64 | #define COM3_SWAP 0x40 /* Byte swap */ | ||
65 | #define COM3_SCALEEN 0x08 /* Enable scaling */ | ||
66 | #define COM3_DCWEN 0x04 /* Enable downsamp/crop/window */ | ||
67 | #define REG_COM4 0x0d /* Control 4 */ | ||
68 | #define REG_COM5 0x0e /* All "reserved" */ | ||
69 | #define REG_COM6 0x0f /* Control 6 */ | ||
70 | #define REG_AECH 0x10 /* More bits of AEC value */ | ||
71 | #define REG_CLKRC 0x11 /* Clocl control */ | ||
72 | #define CLK_EXT 0x40 /* Use external clock directly */ | ||
73 | #define CLK_SCALE 0x3f /* Mask for internal clock scale */ | ||
74 | #define REG_COM7 0x12 /* Control 7 */ | ||
75 | #define COM7_RESET 0x80 /* Register reset */ | ||
76 | #define COM7_FMT_MASK 0x38 | ||
77 | #define COM7_FMT_VGA 0x00 | ||
78 | #define COM7_FMT_CIF 0x20 /* CIF format */ | ||
79 | #define COM7_FMT_QVGA 0x10 /* QVGA format */ | ||
80 | #define COM7_FMT_QCIF 0x08 /* QCIF format */ | ||
81 | #define COM7_RGB 0x04 /* bits 0 and 2 - RGB format */ | ||
82 | #define COM7_YUV 0x00 /* YUV */ | ||
83 | #define COM7_BAYER 0x01 /* Bayer format */ | ||
84 | #define COM7_PBAYER 0x05 /* "Processed bayer" */ | ||
85 | #define REG_COM8 0x13 /* Control 8 */ | ||
86 | #define COM8_FASTAEC 0x80 /* Enable fast AGC/AEC */ | ||
87 | #define COM8_AECSTEP 0x40 /* Unlimited AEC step size */ | ||
88 | #define COM8_BFILT 0x20 /* Band filter enable */ | ||
89 | #define COM8_AGC 0x04 /* Auto gain enable */ | ||
90 | #define COM8_AWB 0x02 /* White balance enable */ | ||
91 | #define COM8_AEC 0x01 /* Auto exposure enable */ | ||
92 | #define REG_COM9 0x14 /* Control 9 - gain ceiling */ | ||
93 | #define REG_COM10 0x15 /* Control 10 */ | ||
94 | #define COM10_HSYNC 0x40 /* HSYNC instead of HREF */ | ||
95 | #define COM10_PCLK_HB 0x20 /* Suppress PCLK on horiz blank */ | ||
96 | #define COM10_HREF_REV 0x08 /* Reverse HREF */ | ||
97 | #define COM10_VS_LEAD 0x04 /* VSYNC on clock leading edge */ | ||
98 | #define COM10_VS_NEG 0x02 /* VSYNC negative */ | ||
99 | #define COM10_HS_NEG 0x01 /* HSYNC negative */ | ||
100 | #define REG_HSTART 0x17 /* Horiz start high bits */ | ||
101 | #define REG_HSTOP 0x18 /* Horiz stop high bits */ | ||
102 | #define REG_VSTART 0x19 /* Vert start high bits */ | ||
103 | #define REG_VSTOP 0x1a /* Vert stop high bits */ | ||
104 | #define REG_PSHFT 0x1b /* Pixel delay after HREF */ | ||
105 | #define REG_MIDH 0x1c /* Manuf. ID high */ | ||
106 | #define REG_MIDL 0x1d /* Manuf. ID low */ | ||
107 | #define REG_MVFP 0x1e /* Mirror / vflip */ | ||
108 | #define MVFP_MIRROR 0x20 /* Mirror image */ | ||
109 | #define MVFP_FLIP 0x10 /* Vertical flip */ | ||
110 | |||
111 | #define REG_AEW 0x24 /* AGC upper limit */ | ||
112 | #define REG_AEB 0x25 /* AGC lower limit */ | ||
113 | #define REG_VPT 0x26 /* AGC/AEC fast mode op region */ | ||
114 | #define REG_HSYST 0x30 /* HSYNC rising edge delay */ | ||
115 | #define REG_HSYEN 0x31 /* HSYNC falling edge delay */ | ||
116 | #define REG_HREF 0x32 /* HREF pieces */ | ||
117 | #define REG_TSLB 0x3a /* lots of stuff */ | ||
118 | #define TSLB_YLAST 0x04 /* UYVY or VYUY - see com13 */ | ||
119 | #define REG_COM11 0x3b /* Control 11 */ | ||
120 | #define COM11_NIGHT 0x80 /* NIght mode enable */ | ||
121 | #define COM11_NMFR 0x60 /* Two bit NM frame rate */ | ||
122 | #define COM11_HZAUTO 0x10 /* Auto detect 50/60 Hz */ | ||
123 | #define COM11_50HZ 0x08 /* Manual 50Hz select */ | ||
124 | #define COM11_EXP 0x02 | ||
125 | #define REG_COM12 0x3c /* Control 12 */ | ||
126 | #define COM12_HREF 0x80 /* HREF always */ | ||
127 | #define REG_COM13 0x3d /* Control 13 */ | ||
128 | #define COM13_GAMMA 0x80 /* Gamma enable */ | ||
129 | #define COM13_UVSAT 0x40 /* UV saturation auto adjustment */ | ||
130 | #define COM13_UVSWAP 0x01 /* V before U - w/TSLB */ | ||
131 | #define REG_COM14 0x3e /* Control 14 */ | ||
132 | #define COM14_DCWEN 0x10 /* DCW/PCLK-scale enable */ | ||
133 | #define REG_EDGE 0x3f /* Edge enhancement factor */ | ||
134 | #define REG_COM15 0x40 /* Control 15 */ | ||
135 | #define COM15_R10F0 0x00 /* Data range 10 to F0 */ | ||
136 | #define COM15_R01FE 0x80 /* 01 to FE */ | ||
137 | #define COM15_R00FF 0xc0 /* 00 to FF */ | ||
138 | #define COM15_RGB565 0x10 /* RGB565 output */ | ||
139 | #define COM15_RGB555 0x30 /* RGB555 output */ | ||
140 | #define REG_COM16 0x41 /* Control 16 */ | ||
141 | #define COM16_AWBGAIN 0x08 /* AWB gain enable */ | ||
142 | #define REG_COM17 0x42 /* Control 17 */ | ||
143 | #define COM17_AECWIN 0xc0 /* AEC window - must match COM4 */ | ||
144 | #define COM17_CBAR 0x08 /* DSP Color bar */ | ||
145 | |||
146 | /* | ||
147 | * This matrix defines how the colors are generated, must be | ||
148 | * tweaked to adjust hue and saturation. | ||
149 | * | ||
150 | * Order: v-red, v-green, v-blue, u-red, u-green, u-blue | ||
151 | * | ||
152 | * They are nine-bit signed quantities, with the sign bit | ||
153 | * stored in 0x58. Sign for v-red is bit 0, and up from there. | ||
154 | */ | ||
155 | #define REG_CMATRIX_BASE 0x4f | ||
156 | #define CMATRIX_LEN 6 | ||
157 | #define REG_CMATRIX_SIGN 0x58 | ||
158 | |||
159 | |||
160 | #define REG_BRIGHT 0x55 /* Brightness */ | ||
161 | #define REG_CONTRAS 0x56 /* Contrast control */ | ||
162 | |||
163 | #define REG_GFIX 0x69 /* Fix gain control */ | ||
164 | |||
165 | #define REG_RGB444 0x8c /* RGB 444 control */ | ||
166 | #define R444_ENABLE 0x02 /* Turn on RGB444, overrides 5x5 */ | ||
167 | #define R444_RGBX 0x01 /* Empty nibble at end */ | ||
168 | |||
169 | #define REG_HAECC1 0x9f /* Hist AEC/AGC control 1 */ | ||
170 | #define REG_HAECC2 0xa0 /* Hist AEC/AGC control 2 */ | ||
171 | |||
172 | #define REG_BD50MAX 0xa5 /* 50hz banding step limit */ | ||
173 | #define REG_HAECC3 0xa6 /* Hist AEC/AGC control 3 */ | ||
174 | #define REG_HAECC4 0xa7 /* Hist AEC/AGC control 4 */ | ||
175 | #define REG_HAECC5 0xa8 /* Hist AEC/AGC control 5 */ | ||
176 | #define REG_HAECC6 0xa9 /* Hist AEC/AGC control 6 */ | ||
177 | #define REG_HAECC7 0xaa /* Hist AEC/AGC control 7 */ | ||
178 | #define REG_BD60MAX 0xab /* 60hz banding step limit */ | ||
179 | |||
180 | |||
181 | /* | ||
182 | * Information we maintain about a known sensor. | ||
183 | */ | ||
184 | struct ov7670_format_struct; /* coming later */ | ||
185 | struct ov7670_info { | ||
186 | struct ov7670_format_struct *fmt; /* Current format */ | ||
187 | unsigned char sat; /* Saturation value */ | ||
188 | int hue; /* Hue value */ | ||
189 | }; | ||
190 | |||
191 | |||
192 | |||
193 | |||
194 | /* | ||
195 | * The default register settings, as obtained from OmniVision. There | ||
196 | * is really no making sense of most of these - lots of "reserved" values | ||
197 | * and such. | ||
198 | * | ||
199 | * These settings give VGA YUYV. | ||
200 | */ | ||
201 | |||
202 | struct regval_list { | ||
203 | unsigned char reg_num; | ||
204 | unsigned char value; | ||
205 | }; | ||
206 | |||
207 | static struct regval_list ov7670_default_regs[] = { | ||
208 | { REG_COM7, COM7_RESET }, | ||
209 | /* | ||
210 | * Clock scale: 3 = 15fps | ||
211 | * 2 = 20fps | ||
212 | * 1 = 30fps | ||
213 | */ | ||
214 | { REG_CLKRC, 0x1 }, /* OV: clock scale (30 fps) */ | ||
215 | { REG_TSLB, 0x04 }, /* OV */ | ||
216 | { REG_COM7, 0 }, /* VGA */ | ||
217 | /* | ||
218 | * Set the hardware window. These values from OV don't entirely | ||
219 | * make sense - hstop is less than hstart. But they work... | ||
220 | */ | ||
221 | { REG_HSTART, 0x13 }, { REG_HSTOP, 0x01 }, | ||
222 | { REG_HREF, 0xb6 }, { REG_VSTART, 0x02 }, | ||
223 | { REG_VSTOP, 0x7a }, { REG_VREF, 0x0a }, | ||
224 | |||
225 | { REG_COM3, 0 }, { REG_COM14, 0 }, | ||
226 | /* Mystery scaling numbers */ | ||
227 | { 0x70, 0x3a }, { 0x71, 0x35 }, | ||
228 | { 0x72, 0x11 }, { 0x73, 0xf0 }, | ||
229 | { 0xa2, 0x02 }, { REG_COM10, 0x0 }, | ||
230 | |||
231 | /* Gamma curve values */ | ||
232 | { 0x7a, 0x20 }, { 0x7b, 0x10 }, | ||
233 | { 0x7c, 0x1e }, { 0x7d, 0x35 }, | ||
234 | { 0x7e, 0x5a }, { 0x7f, 0x69 }, | ||
235 | { 0x80, 0x76 }, { 0x81, 0x80 }, | ||
236 | { 0x82, 0x88 }, { 0x83, 0x8f }, | ||
237 | { 0x84, 0x96 }, { 0x85, 0xa3 }, | ||
238 | { 0x86, 0xaf }, { 0x87, 0xc4 }, | ||
239 | { 0x88, 0xd7 }, { 0x89, 0xe8 }, | ||
240 | |||
241 | /* AGC and AEC parameters. Note we start by disabling those features, | ||
242 | then turn them only after tweaking the values. */ | ||
243 | { REG_COM8, COM8_FASTAEC | COM8_AECSTEP | COM8_BFILT }, | ||
244 | { REG_GAIN, 0 }, { REG_AECH, 0 }, | ||
245 | { REG_COM4, 0x40 }, /* magic reserved bit */ | ||
246 | { REG_COM9, 0x18 }, /* 4x gain + magic rsvd bit */ | ||
247 | { REG_BD50MAX, 0x05 }, { REG_BD60MAX, 0x07 }, | ||
248 | { REG_AEW, 0x95 }, { REG_AEB, 0x33 }, | ||
249 | { REG_VPT, 0xe3 }, { REG_HAECC1, 0x78 }, | ||
250 | { REG_HAECC2, 0x68 }, { 0xa1, 0x03 }, /* magic */ | ||
251 | { REG_HAECC3, 0xd8 }, { REG_HAECC4, 0xd8 }, | ||
252 | { REG_HAECC5, 0xf0 }, { REG_HAECC6, 0x90 }, | ||
253 | { REG_HAECC7, 0x94 }, | ||
254 | { REG_COM8, COM8_FASTAEC|COM8_AECSTEP|COM8_BFILT|COM8_AGC|COM8_AEC }, | ||
255 | |||
256 | /* Almost all of these are magic "reserved" values. */ | ||
257 | { REG_COM5, 0x61 }, { REG_COM6, 0x4b }, | ||
258 | { 0x16, 0x02 }, { REG_MVFP, 0x07|MVFP_MIRROR }, | ||
259 | { 0x21, 0x02 }, { 0x22, 0x91 }, | ||
260 | { 0x29, 0x07 }, { 0x33, 0x0b }, | ||
261 | { 0x35, 0x0b }, { 0x37, 0x1d }, | ||
262 | { 0x38, 0x71 }, { 0x39, 0x2a }, | ||
263 | { REG_COM12, 0x78 }, { 0x4d, 0x40 }, | ||
264 | { 0x4e, 0x20 }, { REG_GFIX, 0 }, | ||
265 | { 0x6b, 0x4a }, { 0x74, 0x10 }, | ||
266 | { 0x8d, 0x4f }, { 0x8e, 0 }, | ||
267 | { 0x8f, 0 }, { 0x90, 0 }, | ||
268 | { 0x91, 0 }, { 0x96, 0 }, | ||
269 | { 0x9a, 0 }, { 0xb0, 0x84 }, | ||
270 | { 0xb1, 0x0c }, { 0xb2, 0x0e }, | ||
271 | { 0xb3, 0x82 }, { 0xb8, 0x0a }, | ||
272 | |||
273 | /* More reserved magic, some of which tweaks white balance */ | ||
274 | { 0x43, 0x0a }, { 0x44, 0xf0 }, | ||
275 | { 0x45, 0x34 }, { 0x46, 0x58 }, | ||
276 | { 0x47, 0x28 }, { 0x48, 0x3a }, | ||
277 | { 0x59, 0x88 }, { 0x5a, 0x88 }, | ||
278 | { 0x5b, 0x44 }, { 0x5c, 0x67 }, | ||
279 | { 0x5d, 0x49 }, { 0x5e, 0x0e }, | ||
280 | { 0x6c, 0x0a }, { 0x6d, 0x55 }, | ||
281 | { 0x6e, 0x11 }, { 0x6f, 0x9f }, /* "9e for advance AWB" */ | ||
282 | { 0x6a, 0x40 }, { REG_BLUE, 0x40 }, | ||
283 | { REG_RED, 0x60 }, | ||
284 | { REG_COM8, COM8_FASTAEC|COM8_AECSTEP|COM8_BFILT|COM8_AGC|COM8_AEC|COM8_AWB }, | ||
285 | |||
286 | /* Matrix coefficients */ | ||
287 | { 0x4f, 0x80 }, { 0x50, 0x80 }, | ||
288 | { 0x51, 0 }, { 0x52, 0x22 }, | ||
289 | { 0x53, 0x5e }, { 0x54, 0x80 }, | ||
290 | { 0x58, 0x9e }, | ||
291 | |||
292 | { REG_COM16, COM16_AWBGAIN }, { REG_EDGE, 0 }, | ||
293 | { 0x75, 0x05 }, { 0x76, 0xe1 }, | ||
294 | { 0x4c, 0 }, { 0x77, 0x01 }, | ||
295 | { REG_COM13, 0xc3 }, { 0x4b, 0x09 }, | ||
296 | { 0xc9, 0x60 }, { REG_COM16, 0x38 }, | ||
297 | { 0x56, 0x40 }, | ||
298 | |||
299 | { 0x34, 0x11 }, { REG_COM11, COM11_EXP|COM11_HZAUTO }, | ||
300 | { 0xa4, 0x88 }, { 0x96, 0 }, | ||
301 | { 0x97, 0x30 }, { 0x98, 0x20 }, | ||
302 | { 0x99, 0x30 }, { 0x9a, 0x84 }, | ||
303 | { 0x9b, 0x29 }, { 0x9c, 0x03 }, | ||
304 | { 0x9d, 0x4c }, { 0x9e, 0x3f }, | ||
305 | { 0x78, 0x04 }, | ||
306 | |||
307 | /* Extra-weird stuff. Some sort of multiplexor register */ | ||
308 | { 0x79, 0x01 }, { 0xc8, 0xf0 }, | ||
309 | { 0x79, 0x0f }, { 0xc8, 0x00 }, | ||
310 | { 0x79, 0x10 }, { 0xc8, 0x7e }, | ||
311 | { 0x79, 0x0a }, { 0xc8, 0x80 }, | ||
312 | { 0x79, 0x0b }, { 0xc8, 0x01 }, | ||
313 | { 0x79, 0x0c }, { 0xc8, 0x0f }, | ||
314 | { 0x79, 0x0d }, { 0xc8, 0x20 }, | ||
315 | { 0x79, 0x09 }, { 0xc8, 0x80 }, | ||
316 | { 0x79, 0x02 }, { 0xc8, 0xc0 }, | ||
317 | { 0x79, 0x03 }, { 0xc8, 0x40 }, | ||
318 | { 0x79, 0x05 }, { 0xc8, 0x30 }, | ||
319 | { 0x79, 0x26 }, | ||
320 | |||
321 | { 0xff, 0xff }, /* END MARKER */ | ||
322 | }; | ||
323 | |||
324 | |||
325 | /* | ||
326 | * Here we'll try to encapsulate the changes for just the output | ||
327 | * video format. | ||
328 | * | ||
329 | * RGB656 and YUV422 come from OV; RGB444 is homebrewed. | ||
330 | * | ||
331 | * IMPORTANT RULE: the first entry must be for COM7, see ov7670_s_fmt for why. | ||
332 | */ | ||
333 | |||
334 | |||
335 | static struct regval_list ov7670_fmt_yuv422[] = { | ||
336 | { REG_COM7, 0x0 }, /* Selects YUV mode */ | ||
337 | { REG_RGB444, 0 }, /* No RGB444 please */ | ||
338 | { REG_COM1, 0 }, | ||
339 | { REG_COM15, COM15_R00FF }, | ||
340 | { REG_COM9, 0x18 }, /* 4x gain ceiling; 0x8 is reserved bit */ | ||
341 | { 0x4f, 0x80 }, /* "matrix coefficient 1" */ | ||
342 | { 0x50, 0x80 }, /* "matrix coefficient 2" */ | ||
343 | { 0x51, 0 }, /* vb */ | ||
344 | { 0x52, 0x22 }, /* "matrix coefficient 4" */ | ||
345 | { 0x53, 0x5e }, /* "matrix coefficient 5" */ | ||
346 | { 0x54, 0x80 }, /* "matrix coefficient 6" */ | ||
347 | { REG_COM13, COM13_GAMMA|COM13_UVSAT }, | ||
348 | { 0xff, 0xff }, | ||
349 | }; | ||
350 | |||
351 | static struct regval_list ov7670_fmt_rgb565[] = { | ||
352 | { REG_COM7, COM7_RGB }, /* Selects RGB mode */ | ||
353 | { REG_RGB444, 0 }, /* No RGB444 please */ | ||
354 | { REG_COM1, 0x0 }, | ||
355 | { REG_COM15, COM15_RGB565 }, | ||
356 | { REG_COM9, 0x38 }, /* 16x gain ceiling; 0x8 is reserved bit */ | ||
357 | { 0x4f, 0xb3 }, /* "matrix coefficient 1" */ | ||
358 | { 0x50, 0xb3 }, /* "matrix coefficient 2" */ | ||
359 | { 0x51, 0 }, /* vb */ | ||
360 | { 0x52, 0x3d }, /* "matrix coefficient 4" */ | ||
361 | { 0x53, 0xa7 }, /* "matrix coefficient 5" */ | ||
362 | { 0x54, 0xe4 }, /* "matrix coefficient 6" */ | ||
363 | { REG_COM13, COM13_GAMMA|COM13_UVSAT }, | ||
364 | { 0xff, 0xff }, | ||
365 | }; | ||
366 | |||
367 | static struct regval_list ov7670_fmt_rgb444[] = { | ||
368 | { REG_COM7, COM7_RGB }, /* Selects RGB mode */ | ||
369 | { REG_RGB444, R444_ENABLE }, /* Enable xxxxrrrr ggggbbbb */ | ||
370 | { REG_COM1, 0x40 }, /* Magic reserved bit */ | ||
371 | { REG_COM15, COM15_R01FE|COM15_RGB565 }, /* Data range needed? */ | ||
372 | { REG_COM9, 0x38 }, /* 16x gain ceiling; 0x8 is reserved bit */ | ||
373 | { 0x4f, 0xb3 }, /* "matrix coefficient 1" */ | ||
374 | { 0x50, 0xb3 }, /* "matrix coefficient 2" */ | ||
375 | { 0x51, 0 }, /* vb */ | ||
376 | { 0x52, 0x3d }, /* "matrix coefficient 4" */ | ||
377 | { 0x53, 0xa7 }, /* "matrix coefficient 5" */ | ||
378 | { 0x54, 0xe4 }, /* "matrix coefficient 6" */ | ||
379 | { REG_COM13, COM13_GAMMA|COM13_UVSAT|0x2 }, /* Magic rsvd bit */ | ||
380 | { 0xff, 0xff }, | ||
381 | }; | ||
382 | |||
383 | |||
384 | |||
385 | |||
386 | /* | ||
387 | * Low-level register I/O. | ||
388 | */ | ||
389 | |||
390 | static int ov7670_read(struct i2c_client *c, unsigned char reg, | ||
391 | unsigned char *value) | ||
392 | { | ||
393 | int ret; | ||
394 | |||
395 | ret = i2c_smbus_read_byte_data(c, reg); | ||
396 | if (ret >= 0) | ||
397 | *value = (unsigned char) ret; | ||
398 | return ret; | ||
399 | } | ||
400 | |||
401 | |||
402 | static int ov7670_write(struct i2c_client *c, unsigned char reg, | ||
403 | unsigned char value) | ||
404 | { | ||
405 | return i2c_smbus_write_byte_data(c, reg, value); | ||
406 | } | ||
407 | |||
408 | |||
409 | /* | ||
410 | * Write a list of register settings; ff/ff stops the process. | ||
411 | */ | ||
412 | static int ov7670_write_array(struct i2c_client *c, struct regval_list *vals) | ||
413 | { | ||
414 | while (vals->reg_num != 0xff || vals->value != 0xff) { | ||
415 | int ret = ov7670_write(c, vals->reg_num, vals->value); | ||
416 | if (ret < 0) | ||
417 | return ret; | ||
418 | vals++; | ||
419 | } | ||
420 | return 0; | ||
421 | } | ||
422 | |||
423 | |||
424 | /* | ||
425 | * Stuff that knows about the sensor. | ||
426 | */ | ||
427 | static void ov7670_reset(struct i2c_client *client) | ||
428 | { | ||
429 | ov7670_write(client, REG_COM7, COM7_RESET); | ||
430 | msleep(1); | ||
431 | } | ||
432 | |||
433 | |||
434 | static int ov7670_init(struct i2c_client *client) | ||
435 | { | ||
436 | return ov7670_write_array(client, ov7670_default_regs); | ||
437 | } | ||
438 | |||
439 | |||
440 | |||
441 | static int ov7670_detect(struct i2c_client *client) | ||
442 | { | ||
443 | unsigned char v; | ||
444 | int ret; | ||
445 | |||
446 | ret = ov7670_init(client); | ||
447 | if (ret < 0) | ||
448 | return ret; | ||
449 | ret = ov7670_read(client, REG_MIDH, &v); | ||
450 | if (ret < 0) | ||
451 | return ret; | ||
452 | if (v != 0x7f) /* OV manuf. id. */ | ||
453 | return -ENODEV; | ||
454 | ret = ov7670_read(client, REG_MIDL, &v); | ||
455 | if (ret < 0) | ||
456 | return ret; | ||
457 | if (v != 0xa2) | ||
458 | return -ENODEV; | ||
459 | /* | ||
460 | * OK, we know we have an OmniVision chip...but which one? | ||
461 | */ | ||
462 | ret = ov7670_read(client, REG_PID, &v); | ||
463 | if (ret < 0) | ||
464 | return ret; | ||
465 | if (v != 0x76) /* PID + VER = 0x76 / 0x73 */ | ||
466 | return -ENODEV; | ||
467 | ret = ov7670_read(client, REG_VER, &v); | ||
468 | if (ret < 0) | ||
469 | return ret; | ||
470 | if (v != 0x73) /* PID + VER = 0x76 / 0x73 */ | ||
471 | return -ENODEV; | ||
472 | return 0; | ||
473 | } | ||
474 | |||
475 | |||
476 | /* | ||
477 | * Store information about the video data format. The color matrix | ||
478 | * is deeply tied into the format, so keep the relevant values here. | ||
479 | * The magic matrix nubmers come from OmniVision. | ||
480 | */ | ||
481 | static struct ov7670_format_struct { | ||
482 | __u8 *desc; | ||
483 | __u32 pixelformat; | ||
484 | struct regval_list *regs; | ||
485 | int cmatrix[CMATRIX_LEN]; | ||
486 | } ov7670_formats[] = { | ||
487 | { | ||
488 | .desc = "YUYV 4:2:2", | ||
489 | .pixelformat = V4L2_PIX_FMT_YUYV, | ||
490 | .regs = ov7670_fmt_yuv422, | ||
491 | .cmatrix = { 128, -128, 0, -34, -94, 128 }, | ||
492 | }, | ||
493 | { | ||
494 | .desc = "RGB 444", | ||
495 | .pixelformat = V4L2_PIX_FMT_RGB444, | ||
496 | .regs = ov7670_fmt_rgb444, | ||
497 | .cmatrix = { 179, -179, 0, -61, -176, 228 }, | ||
498 | }, | ||
499 | { | ||
500 | .desc = "RGB 565", | ||
501 | .pixelformat = V4L2_PIX_FMT_RGB565, | ||
502 | .regs = ov7670_fmt_rgb565, | ||
503 | .cmatrix = { 179, -179, 0, -61, -176, 228 }, | ||
504 | }, | ||
505 | }; | ||
506 | #define N_OV7670_FMTS (sizeof(ov7670_formats)/sizeof(ov7670_formats[0])) | ||
507 | |||
508 | /* | ||
509 | * All formats we support are 2 bytes/pixel. | ||
510 | */ | ||
511 | #define BYTES_PER_PIXEL 2 | ||
512 | |||
513 | /* | ||
514 | * Then there is the issue of window sizes. Try to capture the info here. | ||
515 | */ | ||
516 | |||
517 | /* | ||
518 | * QCIF mode is done (by OV) in a very strange way - it actually looks like | ||
519 | * VGA with weird scaling options - they do *not* use the canned QCIF mode | ||
520 | * which is allegedly provided by the sensor. So here's the weird register | ||
521 | * settings. | ||
522 | */ | ||
523 | static struct regval_list ov7670_qcif_regs[] = { | ||
524 | { REG_COM3, COM3_SCALEEN|COM3_DCWEN }, | ||
525 | { REG_COM3, COM3_DCWEN }, | ||
526 | { REG_COM14, COM14_DCWEN | 0x01}, | ||
527 | { 0x73, 0xf1 }, | ||
528 | { 0xa2, 0x52 }, | ||
529 | { 0x7b, 0x1c }, | ||
530 | { 0x7c, 0x28 }, | ||
531 | { 0x7d, 0x3c }, | ||
532 | { 0x7f, 0x69 }, | ||
533 | { REG_COM9, 0x38 }, | ||
534 | { 0xa1, 0x0b }, | ||
535 | { 0x74, 0x19 }, | ||
536 | { 0x9a, 0x80 }, | ||
537 | { 0x43, 0x14 }, | ||
538 | { REG_COM13, 0xc0 }, | ||
539 | { 0xff, 0xff }, | ||
540 | }; | ||
541 | |||
542 | static struct ov7670_win_size { | ||
543 | int width; | ||
544 | int height; | ||
545 | unsigned char com7_bit; | ||
546 | int hstart; /* Start/stop values for the camera. Note */ | ||
547 | int hstop; /* that they do not always make complete */ | ||
548 | int vstart; /* sense to humans, but evidently the sensor */ | ||
549 | int vstop; /* will do the right thing... */ | ||
550 | struct regval_list *regs; /* Regs to tweak */ | ||
551 | /* h/vref stuff */ | ||
552 | } ov7670_win_sizes[] = { | ||
553 | /* VGA */ | ||
554 | { | ||
555 | .width = VGA_WIDTH, | ||
556 | .height = VGA_HEIGHT, | ||
557 | .com7_bit = COM7_FMT_VGA, | ||
558 | .hstart = 158, /* These values from */ | ||
559 | .hstop = 14, /* Omnivision */ | ||
560 | .vstart = 10, | ||
561 | .vstop = 490, | ||
562 | .regs = NULL, | ||
563 | }, | ||
564 | /* CIF */ | ||
565 | { | ||
566 | .width = CIF_WIDTH, | ||
567 | .height = CIF_HEIGHT, | ||
568 | .com7_bit = COM7_FMT_CIF, | ||
569 | .hstart = 170, /* Empirically determined */ | ||
570 | .hstop = 90, | ||
571 | .vstart = 14, | ||
572 | .vstop = 494, | ||
573 | .regs = NULL, | ||
574 | }, | ||
575 | /* QVGA */ | ||
576 | { | ||
577 | .width = QVGA_WIDTH, | ||
578 | .height = QVGA_HEIGHT, | ||
579 | .com7_bit = COM7_FMT_QVGA, | ||
580 | .hstart = 164, /* Empirically determined */ | ||
581 | .hstop = 20, | ||
582 | .vstart = 14, | ||
583 | .vstop = 494, | ||
584 | .regs = NULL, | ||
585 | }, | ||
586 | /* QCIF */ | ||
587 | { | ||
588 | .width = QCIF_WIDTH, | ||
589 | .height = QCIF_HEIGHT, | ||
590 | .com7_bit = COM7_FMT_VGA, /* see comment above */ | ||
591 | .hstart = 456, /* Empirically determined */ | ||
592 | .hstop = 24, | ||
593 | .vstart = 14, | ||
594 | .vstop = 494, | ||
595 | .regs = ov7670_qcif_regs, | ||
596 | }, | ||
597 | }; | ||
598 | |||
599 | #define N_WIN_SIZES (sizeof(ov7670_win_sizes)/sizeof(ov7670_win_sizes[0])) | ||
600 | |||
601 | |||
602 | /* | ||
603 | * Store a set of start/stop values into the camera. | ||
604 | */ | ||
605 | static int ov7670_set_hw(struct i2c_client *client, int hstart, int hstop, | ||
606 | int vstart, int vstop) | ||
607 | { | ||
608 | int ret; | ||
609 | unsigned char v; | ||
610 | /* | ||
611 | * Horizontal: 11 bits, top 8 live in hstart and hstop. Bottom 3 of | ||
612 | * hstart are in href[2:0], bottom 3 of hstop in href[5:3]. There is | ||
613 | * a mystery "edge offset" value in the top two bits of href. | ||
614 | */ | ||
615 | ret = ov7670_write(client, REG_HSTART, (hstart >> 3) & 0xff); | ||
616 | ret += ov7670_write(client, REG_HSTOP, (hstop >> 3) & 0xff); | ||
617 | ret += ov7670_read(client, REG_HREF, &v); | ||
618 | v = (v & 0xc0) | ((hstop & 0x7) << 3) | (hstart & 0x7); | ||
619 | msleep(10); | ||
620 | ret += ov7670_write(client, REG_HREF, v); | ||
621 | /* | ||
622 | * Vertical: similar arrangement, but only 10 bits. | ||
623 | */ | ||
624 | ret += ov7670_write(client, REG_VSTART, (vstart >> 2) & 0xff); | ||
625 | ret += ov7670_write(client, REG_VSTOP, (vstop >> 2) & 0xff); | ||
626 | ret += ov7670_read(client, REG_VREF, &v); | ||
627 | v = (v & 0xf0) | ((vstop & 0x3) << 2) | (vstart & 0x3); | ||
628 | msleep(10); | ||
629 | ret += ov7670_write(client, REG_VREF, v); | ||
630 | return ret; | ||
631 | } | ||
632 | |||
633 | |||
634 | static int ov7670_enum_fmt(struct i2c_client *c, struct v4l2_fmtdesc *fmt) | ||
635 | { | ||
636 | struct ov7670_format_struct *ofmt; | ||
637 | |||
638 | if (fmt->index >= N_OV7670_FMTS) | ||
639 | return -EINVAL; | ||
640 | |||
641 | ofmt = ov7670_formats + fmt->index; | ||
642 | fmt->flags = 0; | ||
643 | strcpy(fmt->description, ofmt->desc); | ||
644 | fmt->pixelformat = ofmt->pixelformat; | ||
645 | return 0; | ||
646 | } | ||
647 | |||
648 | |||
649 | static int ov7670_try_fmt(struct i2c_client *c, struct v4l2_format *fmt, | ||
650 | struct ov7670_format_struct **ret_fmt, | ||
651 | struct ov7670_win_size **ret_wsize) | ||
652 | { | ||
653 | int index; | ||
654 | struct ov7670_win_size *wsize; | ||
655 | struct v4l2_pix_format *pix = &fmt->fmt.pix; | ||
656 | |||
657 | for (index = 0; index < N_OV7670_FMTS; index++) | ||
658 | if (ov7670_formats[index].pixelformat == pix->pixelformat) | ||
659 | break; | ||
660 | if (index >= N_OV7670_FMTS) | ||
661 | return -EINVAL; | ||
662 | if (ret_fmt != NULL) | ||
663 | *ret_fmt = ov7670_formats + index; | ||
664 | /* | ||
665 | * Fields: the OV devices claim to be progressive. | ||
666 | */ | ||
667 | if (pix->field == V4L2_FIELD_ANY) | ||
668 | pix->field = V4L2_FIELD_NONE; | ||
669 | else if (pix->field != V4L2_FIELD_NONE) | ||
670 | return -EINVAL; | ||
671 | /* | ||
672 | * Round requested image size down to the nearest | ||
673 | * we support, but not below the smallest. | ||
674 | */ | ||
675 | for (wsize = ov7670_win_sizes; wsize < ov7670_win_sizes + N_WIN_SIZES; | ||
676 | wsize++) | ||
677 | if (pix->width >= wsize->width && pix->height >= wsize->height) | ||
678 | break; | ||
679 | if (wsize >= ov7670_win_sizes + N_WIN_SIZES) | ||
680 | wsize--; /* Take the smallest one */ | ||
681 | if (ret_wsize != NULL) | ||
682 | *ret_wsize = wsize; | ||
683 | /* | ||
684 | * Note the size we'll actually handle. | ||
685 | */ | ||
686 | pix->width = wsize->width; | ||
687 | pix->height = wsize->height; | ||
688 | pix->bytesperline = pix->width*BYTES_PER_PIXEL; | ||
689 | pix->sizeimage = pix->height*pix->bytesperline; | ||
690 | return 0; | ||
691 | } | ||
692 | |||
693 | /* | ||
694 | * Set a format. | ||
695 | */ | ||
696 | static int ov7670_s_fmt(struct i2c_client *c, struct v4l2_format *fmt) | ||
697 | { | ||
698 | int ret; | ||
699 | struct ov7670_format_struct *ovfmt; | ||
700 | struct ov7670_win_size *wsize; | ||
701 | struct ov7670_info *info = i2c_get_clientdata(c); | ||
702 | unsigned char com7; | ||
703 | |||
704 | ret = ov7670_try_fmt(c, fmt, &ovfmt, &wsize); | ||
705 | if (ret) | ||
706 | return ret; | ||
707 | /* | ||
708 | * COM7 is a pain in the ass, it doesn't like to be read then | ||
709 | * quickly written afterward. But we have everything we need | ||
710 | * to set it absolutely here, as long as the format-specific | ||
711 | * register sets list it first. | ||
712 | */ | ||
713 | com7 = ovfmt->regs[0].value; | ||
714 | com7 |= wsize->com7_bit; | ||
715 | ov7670_write(c, REG_COM7, com7); | ||
716 | /* | ||
717 | * Now write the rest of the array. Also store start/stops | ||
718 | */ | ||
719 | ov7670_write_array(c, ovfmt->regs + 1); | ||
720 | ov7670_set_hw(c, wsize->hstart, wsize->hstop, wsize->vstart, | ||
721 | wsize->vstop); | ||
722 | ret = 0; | ||
723 | if (wsize->regs) | ||
724 | ret = ov7670_write_array(c, wsize->regs); | ||
725 | info->fmt = ovfmt; | ||
726 | return 0; | ||
727 | } | ||
728 | |||
729 | /* | ||
730 | * Implement G/S_PARM. There is a "high quality" mode we could try | ||
731 | * to do someday; for now, we just do the frame rate tweak. | ||
732 | */ | ||
733 | static int ov7670_g_parm(struct i2c_client *c, struct v4l2_streamparm *parms) | ||
734 | { | ||
735 | struct v4l2_captureparm *cp = &parms->parm.capture; | ||
736 | unsigned char clkrc; | ||
737 | int ret; | ||
738 | |||
739 | if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
740 | return -EINVAL; | ||
741 | ret = ov7670_read(c, REG_CLKRC, &clkrc); | ||
742 | if (ret < 0) | ||
743 | return ret; | ||
744 | memset(cp, 0, sizeof(struct v4l2_captureparm)); | ||
745 | cp->capability = V4L2_CAP_TIMEPERFRAME; | ||
746 | cp->timeperframe.numerator = 1; | ||
747 | cp->timeperframe.denominator = OV7670_FRAME_RATE; | ||
748 | if ((clkrc & CLK_EXT) == 0 && (clkrc & CLK_SCALE) > 1) | ||
749 | cp->timeperframe.denominator /= (clkrc & CLK_SCALE); | ||
750 | return 0; | ||
751 | } | ||
752 | |||
753 | static int ov7670_s_parm(struct i2c_client *c, struct v4l2_streamparm *parms) | ||
754 | { | ||
755 | struct v4l2_captureparm *cp = &parms->parm.capture; | ||
756 | struct v4l2_fract *tpf = &cp->timeperframe; | ||
757 | unsigned char clkrc; | ||
758 | int ret, div; | ||
759 | |||
760 | if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
761 | return -EINVAL; | ||
762 | if (cp->extendedmode != 0) | ||
763 | return -EINVAL; | ||
764 | /* | ||
765 | * CLKRC has a reserved bit, so let's preserve it. | ||
766 | */ | ||
767 | ret = ov7670_read(c, REG_CLKRC, &clkrc); | ||
768 | if (ret < 0) | ||
769 | return ret; | ||
770 | if (tpf->numerator == 0 || tpf->denominator == 0) | ||
771 | div = 1; /* Reset to full rate */ | ||
772 | else | ||
773 | div = (tpf->numerator*OV7670_FRAME_RATE)/tpf->denominator; | ||
774 | if (div == 0) | ||
775 | div = 1; | ||
776 | else if (div > CLK_SCALE) | ||
777 | div = CLK_SCALE; | ||
778 | clkrc = (clkrc & 0x80) | div; | ||
779 | tpf->numerator = 1; | ||
780 | tpf->denominator = OV7670_FRAME_RATE/div; | ||
781 | return ov7670_write(c, REG_CLKRC, clkrc); | ||
782 | } | ||
783 | |||
784 | |||
785 | |||
786 | /* | ||
787 | * Code for dealing with controls. | ||
788 | */ | ||
789 | |||
790 | |||
791 | |||
792 | |||
793 | |||
794 | static int ov7670_store_cmatrix(struct i2c_client *client, | ||
795 | int matrix[CMATRIX_LEN]) | ||
796 | { | ||
797 | int i, ret; | ||
798 | unsigned char signbits; | ||
799 | |||
800 | /* | ||
801 | * Weird crap seems to exist in the upper part of | ||
802 | * the sign bits register, so let's preserve it. | ||
803 | */ | ||
804 | ret = ov7670_read(client, REG_CMATRIX_SIGN, &signbits); | ||
805 | signbits &= 0xc0; | ||
806 | |||
807 | for (i = 0; i < CMATRIX_LEN; i++) { | ||
808 | unsigned char raw; | ||
809 | |||
810 | if (matrix[i] < 0) { | ||
811 | signbits |= (1 << i); | ||
812 | if (matrix[i] < -255) | ||
813 | raw = 0xff; | ||
814 | else | ||
815 | raw = (-1 * matrix[i]) & 0xff; | ||
816 | } | ||
817 | else { | ||
818 | if (matrix[i] > 255) | ||
819 | raw = 0xff; | ||
820 | else | ||
821 | raw = matrix[i] & 0xff; | ||
822 | } | ||
823 | ret += ov7670_write(client, REG_CMATRIX_BASE + i, raw); | ||
824 | } | ||
825 | ret += ov7670_write(client, REG_CMATRIX_SIGN, signbits); | ||
826 | return ret; | ||
827 | } | ||
828 | |||
829 | |||
830 | /* | ||
831 | * Hue also requires messing with the color matrix. It also requires | ||
832 | * trig functions, which tend not to be well supported in the kernel. | ||
833 | * So here is a simple table of sine values, 0-90 degrees, in steps | ||
834 | * of five degrees. Values are multiplied by 1000. | ||
835 | * | ||
836 | * The following naive approximate trig functions require an argument | ||
837 | * carefully limited to -180 <= theta <= 180. | ||
838 | */ | ||
839 | #define SIN_STEP 5 | ||
840 | static const int ov7670_sin_table[] = { | ||
841 | 0, 87, 173, 258, 342, 422, | ||
842 | 499, 573, 642, 707, 766, 819, | ||
843 | 866, 906, 939, 965, 984, 996, | ||
844 | 1000 | ||
845 | }; | ||
846 | |||
847 | static int ov7670_sine(int theta) | ||
848 | { | ||
849 | int chs = 1; | ||
850 | int sine; | ||
851 | |||
852 | if (theta < 0) { | ||
853 | theta = -theta; | ||
854 | chs = -1; | ||
855 | } | ||
856 | if (theta <= 90) | ||
857 | sine = ov7670_sin_table[theta/SIN_STEP]; | ||
858 | else { | ||
859 | theta -= 90; | ||
860 | sine = 1000 - ov7670_sin_table[theta/SIN_STEP]; | ||
861 | } | ||
862 | return sine*chs; | ||
863 | } | ||
864 | |||
865 | static int ov7670_cosine(int theta) | ||
866 | { | ||
867 | theta = 90 - theta; | ||
868 | if (theta > 180) | ||
869 | theta -= 360; | ||
870 | else if (theta < -180) | ||
871 | theta += 360; | ||
872 | return ov7670_sine(theta); | ||
873 | } | ||
874 | |||
875 | |||
876 | |||
877 | |||
878 | static void ov7670_calc_cmatrix(struct ov7670_info *info, | ||
879 | int matrix[CMATRIX_LEN]) | ||
880 | { | ||
881 | int i; | ||
882 | /* | ||
883 | * Apply the current saturation setting first. | ||
884 | */ | ||
885 | for (i = 0; i < CMATRIX_LEN; i++) | ||
886 | matrix[i] = (info->fmt->cmatrix[i]*info->sat) >> 7; | ||
887 | /* | ||
888 | * Then, if need be, rotate the hue value. | ||
889 | */ | ||
890 | if (info->hue != 0) { | ||
891 | int sinth, costh, tmpmatrix[CMATRIX_LEN]; | ||
892 | |||
893 | memcpy(tmpmatrix, matrix, CMATRIX_LEN*sizeof(int)); | ||
894 | sinth = ov7670_sine(info->hue); | ||
895 | costh = ov7670_cosine(info->hue); | ||
896 | |||
897 | matrix[0] = (matrix[3]*sinth + matrix[0]*costh)/1000; | ||
898 | matrix[1] = (matrix[4]*sinth + matrix[1]*costh)/1000; | ||
899 | matrix[2] = (matrix[5]*sinth + matrix[2]*costh)/1000; | ||
900 | matrix[3] = (matrix[3]*costh - matrix[0]*sinth)/1000; | ||
901 | matrix[4] = (matrix[4]*costh - matrix[1]*sinth)/1000; | ||
902 | matrix[5] = (matrix[5]*costh - matrix[2]*sinth)/1000; | ||
903 | } | ||
904 | } | ||
905 | |||
906 | |||
907 | |||
908 | static int ov7670_t_sat(struct i2c_client *client, int value) | ||
909 | { | ||
910 | struct ov7670_info *info = i2c_get_clientdata(client); | ||
911 | int matrix[CMATRIX_LEN]; | ||
912 | int ret; | ||
913 | |||
914 | info->sat = value; | ||
915 | ov7670_calc_cmatrix(info, matrix); | ||
916 | ret = ov7670_store_cmatrix(client, matrix); | ||
917 | return ret; | ||
918 | } | ||
919 | |||
920 | static int ov7670_q_sat(struct i2c_client *client, __s32 *value) | ||
921 | { | ||
922 | struct ov7670_info *info = i2c_get_clientdata(client); | ||
923 | |||
924 | *value = info->sat; | ||
925 | return 0; | ||
926 | } | ||
927 | |||
928 | static int ov7670_t_hue(struct i2c_client *client, int value) | ||
929 | { | ||
930 | struct ov7670_info *info = i2c_get_clientdata(client); | ||
931 | int matrix[CMATRIX_LEN]; | ||
932 | int ret; | ||
933 | |||
934 | if (value < -180 || value > 180) | ||
935 | return -EINVAL; | ||
936 | info->hue = value; | ||
937 | ov7670_calc_cmatrix(info, matrix); | ||
938 | ret = ov7670_store_cmatrix(client, matrix); | ||
939 | return ret; | ||
940 | } | ||
941 | |||
942 | |||
943 | static int ov7670_q_hue(struct i2c_client *client, __s32 *value) | ||
944 | { | ||
945 | struct ov7670_info *info = i2c_get_clientdata(client); | ||
946 | |||
947 | *value = info->hue; | ||
948 | return 0; | ||
949 | } | ||
950 | |||
951 | |||
952 | /* | ||
953 | * Some weird registers seem to store values in a sign/magnitude format! | ||
954 | */ | ||
955 | static unsigned char ov7670_sm_to_abs(unsigned char v) | ||
956 | { | ||
957 | if ((v & 0x80) == 0) | ||
958 | return v + 128; | ||
959 | else | ||
960 | return 128 - (v & 0x7f); | ||
961 | } | ||
962 | |||
963 | |||
964 | static unsigned char ov7670_abs_to_sm(unsigned char v) | ||
965 | { | ||
966 | if (v > 127) | ||
967 | return v & 0x7f; | ||
968 | else | ||
969 | return (128 - v) | 0x80; | ||
970 | } | ||
971 | |||
972 | static int ov7670_t_brightness(struct i2c_client *client, int value) | ||
973 | { | ||
974 | unsigned char com8, v; | ||
975 | int ret; | ||
976 | |||
977 | ov7670_read(client, REG_COM8, &com8); | ||
978 | com8 &= ~COM8_AEC; | ||
979 | ov7670_write(client, REG_COM8, com8); | ||
980 | v = ov7670_abs_to_sm(value); | ||
981 | ret = ov7670_write(client, REG_BRIGHT, v); | ||
982 | return ret; | ||
983 | } | ||
984 | |||
985 | static int ov7670_q_brightness(struct i2c_client *client, __s32 *value) | ||
986 | { | ||
987 | unsigned char v; | ||
988 | int ret = ov7670_read(client, REG_BRIGHT, &v); | ||
989 | |||
990 | *value = ov7670_sm_to_abs(v); | ||
991 | return ret; | ||
992 | } | ||
993 | |||
994 | static int ov7670_t_contrast(struct i2c_client *client, int value) | ||
995 | { | ||
996 | return ov7670_write(client, REG_CONTRAS, (unsigned char) value); | ||
997 | } | ||
998 | |||
999 | static int ov7670_q_contrast(struct i2c_client *client, __s32 *value) | ||
1000 | { | ||
1001 | unsigned char v; | ||
1002 | int ret = ov7670_read(client, REG_CONTRAS, &v); | ||
1003 | |||
1004 | *value = v; | ||
1005 | return ret; | ||
1006 | } | ||
1007 | |||
1008 | static int ov7670_q_hflip(struct i2c_client *client, __s32 *value) | ||
1009 | { | ||
1010 | int ret; | ||
1011 | unsigned char v; | ||
1012 | |||
1013 | ret = ov7670_read(client, REG_MVFP, &v); | ||
1014 | *value = (v & MVFP_MIRROR) == MVFP_MIRROR; | ||
1015 | return ret; | ||
1016 | } | ||
1017 | |||
1018 | |||
1019 | static int ov7670_t_hflip(struct i2c_client *client, int value) | ||
1020 | { | ||
1021 | unsigned char v; | ||
1022 | int ret; | ||
1023 | |||
1024 | ret = ov7670_read(client, REG_MVFP, &v); | ||
1025 | if (value) | ||
1026 | v |= MVFP_MIRROR; | ||
1027 | else | ||
1028 | v &= ~MVFP_MIRROR; | ||
1029 | msleep(10); /* FIXME */ | ||
1030 | ret += ov7670_write(client, REG_MVFP, v); | ||
1031 | return ret; | ||
1032 | } | ||
1033 | |||
1034 | |||
1035 | |||
1036 | static int ov7670_q_vflip(struct i2c_client *client, __s32 *value) | ||
1037 | { | ||
1038 | int ret; | ||
1039 | unsigned char v; | ||
1040 | |||
1041 | ret = ov7670_read(client, REG_MVFP, &v); | ||
1042 | *value = (v & MVFP_FLIP) == MVFP_FLIP; | ||
1043 | return ret; | ||
1044 | } | ||
1045 | |||
1046 | |||
1047 | static int ov7670_t_vflip(struct i2c_client *client, int value) | ||
1048 | { | ||
1049 | unsigned char v; | ||
1050 | int ret; | ||
1051 | |||
1052 | ret = ov7670_read(client, REG_MVFP, &v); | ||
1053 | if (value) | ||
1054 | v |= MVFP_FLIP; | ||
1055 | else | ||
1056 | v &= ~MVFP_FLIP; | ||
1057 | msleep(10); /* FIXME */ | ||
1058 | ret += ov7670_write(client, REG_MVFP, v); | ||
1059 | return ret; | ||
1060 | } | ||
1061 | |||
1062 | |||
1063 | static struct ov7670_control { | ||
1064 | struct v4l2_queryctrl qc; | ||
1065 | int (*query)(struct i2c_client *c, __s32 *value); | ||
1066 | int (*tweak)(struct i2c_client *c, int value); | ||
1067 | } ov7670_controls[] = | ||
1068 | { | ||
1069 | { | ||
1070 | .qc = { | ||
1071 | .id = V4L2_CID_BRIGHTNESS, | ||
1072 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
1073 | .name = "Brightness", | ||
1074 | .minimum = 0, | ||
1075 | .maximum = 255, | ||
1076 | .step = 1, | ||
1077 | .default_value = 0x80, | ||
1078 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
1079 | }, | ||
1080 | .tweak = ov7670_t_brightness, | ||
1081 | .query = ov7670_q_brightness, | ||
1082 | }, | ||
1083 | { | ||
1084 | .qc = { | ||
1085 | .id = V4L2_CID_CONTRAST, | ||
1086 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
1087 | .name = "Contrast", | ||
1088 | .minimum = 0, | ||
1089 | .maximum = 127, | ||
1090 | .step = 1, | ||
1091 | .default_value = 0x40, /* XXX ov7670 spec */ | ||
1092 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
1093 | }, | ||
1094 | .tweak = ov7670_t_contrast, | ||
1095 | .query = ov7670_q_contrast, | ||
1096 | }, | ||
1097 | { | ||
1098 | .qc = { | ||
1099 | .id = V4L2_CID_SATURATION, | ||
1100 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
1101 | .name = "Saturation", | ||
1102 | .minimum = 0, | ||
1103 | .maximum = 256, | ||
1104 | .step = 1, | ||
1105 | .default_value = 0x80, | ||
1106 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
1107 | }, | ||
1108 | .tweak = ov7670_t_sat, | ||
1109 | .query = ov7670_q_sat, | ||
1110 | }, | ||
1111 | { | ||
1112 | .qc = { | ||
1113 | .id = V4L2_CID_HUE, | ||
1114 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
1115 | .name = "HUE", | ||
1116 | .minimum = -180, | ||
1117 | .maximum = 180, | ||
1118 | .step = 5, | ||
1119 | .default_value = 0, | ||
1120 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
1121 | }, | ||
1122 | .tweak = ov7670_t_hue, | ||
1123 | .query = ov7670_q_hue, | ||
1124 | }, | ||
1125 | { | ||
1126 | .qc = { | ||
1127 | .id = V4L2_CID_VFLIP, | ||
1128 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
1129 | .name = "Vertical flip", | ||
1130 | .minimum = 0, | ||
1131 | .maximum = 1, | ||
1132 | .step = 1, | ||
1133 | .default_value = 0, | ||
1134 | }, | ||
1135 | .tweak = ov7670_t_vflip, | ||
1136 | .query = ov7670_q_vflip, | ||
1137 | }, | ||
1138 | { | ||
1139 | .qc = { | ||
1140 | .id = V4L2_CID_HFLIP, | ||
1141 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
1142 | .name = "Horizontal mirror", | ||
1143 | .minimum = 0, | ||
1144 | .maximum = 1, | ||
1145 | .step = 1, | ||
1146 | .default_value = 0, | ||
1147 | }, | ||
1148 | .tweak = ov7670_t_hflip, | ||
1149 | .query = ov7670_q_hflip, | ||
1150 | }, | ||
1151 | }; | ||
1152 | #define N_CONTROLS (sizeof(ov7670_controls)/sizeof(ov7670_controls[0])) | ||
1153 | |||
1154 | static struct ov7670_control *ov7670_find_control(__u32 id) | ||
1155 | { | ||
1156 | int i; | ||
1157 | |||
1158 | for (i = 0; i < N_CONTROLS; i++) | ||
1159 | if (ov7670_controls[i].qc.id == id) | ||
1160 | return ov7670_controls + i; | ||
1161 | return NULL; | ||
1162 | } | ||
1163 | |||
1164 | |||
1165 | static int ov7670_queryctrl(struct i2c_client *client, | ||
1166 | struct v4l2_queryctrl *qc) | ||
1167 | { | ||
1168 | struct ov7670_control *ctrl = ov7670_find_control(qc->id); | ||
1169 | |||
1170 | if (ctrl == NULL) | ||
1171 | return -EINVAL; | ||
1172 | *qc = ctrl->qc; | ||
1173 | return 0; | ||
1174 | } | ||
1175 | |||
1176 | static int ov7670_g_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) | ||
1177 | { | ||
1178 | struct ov7670_control *octrl = ov7670_find_control(ctrl->id); | ||
1179 | int ret; | ||
1180 | |||
1181 | if (octrl == NULL) | ||
1182 | return -EINVAL; | ||
1183 | ret = octrl->query(client, &ctrl->value); | ||
1184 | if (ret >= 0) | ||
1185 | return 0; | ||
1186 | return ret; | ||
1187 | } | ||
1188 | |||
1189 | static int ov7670_s_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) | ||
1190 | { | ||
1191 | struct ov7670_control *octrl = ov7670_find_control(ctrl->id); | ||
1192 | int ret; | ||
1193 | |||
1194 | if (octrl == NULL) | ||
1195 | return -EINVAL; | ||
1196 | ret = octrl->tweak(client, ctrl->value); | ||
1197 | if (ret >= 0) | ||
1198 | return 0; | ||
1199 | return ret; | ||
1200 | } | ||
1201 | |||
1202 | |||
1203 | |||
1204 | |||
1205 | |||
1206 | |||
1207 | /* | ||
1208 | * Basic i2c stuff. | ||
1209 | */ | ||
1210 | static struct i2c_driver ov7670_driver; | ||
1211 | |||
1212 | static int ov7670_attach(struct i2c_adapter *adapter) | ||
1213 | { | ||
1214 | int ret; | ||
1215 | struct i2c_client *client; | ||
1216 | struct ov7670_info *info; | ||
1217 | |||
1218 | /* | ||
1219 | * For now: only deal with adapters we recognize. | ||
1220 | */ | ||
1221 | if (adapter->id != I2C_HW_SMBUS_CAFE) | ||
1222 | return -ENODEV; | ||
1223 | |||
1224 | client = kzalloc(sizeof (struct i2c_client), GFP_KERNEL); | ||
1225 | if (! client) | ||
1226 | return -ENOMEM; | ||
1227 | client->adapter = adapter; | ||
1228 | client->addr = OV7670_I2C_ADDR; | ||
1229 | client->driver = &ov7670_driver, | ||
1230 | strcpy(client->name, "OV7670"); | ||
1231 | /* | ||
1232 | * Set up our info structure. | ||
1233 | */ | ||
1234 | info = kzalloc(sizeof (struct ov7670_info), GFP_KERNEL); | ||
1235 | if (! info) { | ||
1236 | ret = -ENOMEM; | ||
1237 | goto out_free; | ||
1238 | } | ||
1239 | info->fmt = &ov7670_formats[0]; | ||
1240 | info->sat = 128; /* Review this */ | ||
1241 | i2c_set_clientdata(client, info); | ||
1242 | |||
1243 | /* | ||
1244 | * Make sure it's an ov7670 | ||
1245 | */ | ||
1246 | ret = ov7670_detect(client); | ||
1247 | if (ret) | ||
1248 | goto out_free_info; | ||
1249 | i2c_attach_client(client); | ||
1250 | return 0; | ||
1251 | |||
1252 | out_free_info: | ||
1253 | kfree(info); | ||
1254 | out_free: | ||
1255 | kfree(client); | ||
1256 | return ret; | ||
1257 | } | ||
1258 | |||
1259 | |||
1260 | static int ov7670_detach(struct i2c_client *client) | ||
1261 | { | ||
1262 | i2c_detach_client(client); | ||
1263 | kfree(i2c_get_clientdata(client)); | ||
1264 | kfree(client); | ||
1265 | return 0; | ||
1266 | } | ||
1267 | |||
1268 | |||
1269 | static int ov7670_command(struct i2c_client *client, unsigned int cmd, | ||
1270 | void *arg) | ||
1271 | { | ||
1272 | switch (cmd) { | ||
1273 | case VIDIOC_INT_G_CHIP_IDENT: | ||
1274 | * (enum v4l2_chip_ident *) arg = V4L2_IDENT_OV7670; | ||
1275 | return 0; | ||
1276 | |||
1277 | case VIDIOC_INT_RESET: | ||
1278 | ov7670_reset(client); | ||
1279 | return 0; | ||
1280 | |||
1281 | case VIDIOC_INT_INIT: | ||
1282 | return ov7670_init(client); | ||
1283 | |||
1284 | case VIDIOC_ENUM_FMT: | ||
1285 | return ov7670_enum_fmt(client, (struct v4l2_fmtdesc *) arg); | ||
1286 | case VIDIOC_TRY_FMT: | ||
1287 | return ov7670_try_fmt(client, (struct v4l2_format *) arg, NULL, NULL); | ||
1288 | case VIDIOC_S_FMT: | ||
1289 | return ov7670_s_fmt(client, (struct v4l2_format *) arg); | ||
1290 | case VIDIOC_QUERYCTRL: | ||
1291 | return ov7670_queryctrl(client, (struct v4l2_queryctrl *) arg); | ||
1292 | case VIDIOC_S_CTRL: | ||
1293 | return ov7670_s_ctrl(client, (struct v4l2_control *) arg); | ||
1294 | case VIDIOC_G_CTRL: | ||
1295 | return ov7670_g_ctrl(client, (struct v4l2_control *) arg); | ||
1296 | case VIDIOC_S_PARM: | ||
1297 | return ov7670_s_parm(client, (struct v4l2_streamparm *) arg); | ||
1298 | case VIDIOC_G_PARM: | ||
1299 | return ov7670_g_parm(client, (struct v4l2_streamparm *) arg); | ||
1300 | } | ||
1301 | return -EINVAL; | ||
1302 | } | ||
1303 | |||
1304 | |||
1305 | |||
1306 | static struct i2c_driver ov7670_driver = { | ||
1307 | .driver = { | ||
1308 | .name = "ov7670", | ||
1309 | }, | ||
1310 | .id = I2C_DRIVERID_OV7670, | ||
1311 | .class = I2C_CLASS_CAM_DIGITAL, | ||
1312 | .attach_adapter = ov7670_attach, | ||
1313 | .detach_client = ov7670_detach, | ||
1314 | .command = ov7670_command, | ||
1315 | }; | ||
1316 | |||
1317 | |||
1318 | /* | ||
1319 | * Module initialization | ||
1320 | */ | ||
1321 | static int __init ov7670_mod_init(void) | ||
1322 | { | ||
1323 | printk(KERN_NOTICE "OmniVision ov7670 sensor driver, at your service\n"); | ||
1324 | return i2c_add_driver(&ov7670_driver); | ||
1325 | } | ||
1326 | |||
1327 | static void __exit ov7670_mod_exit(void) | ||
1328 | { | ||
1329 | i2c_del_driver(&ov7670_driver); | ||
1330 | } | ||
1331 | |||
1332 | module_init(ov7670_mod_init); | ||
1333 | module_exit(ov7670_mod_exit); | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c index c80c26be6e4d..848fb233d808 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c +++ b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c | |||
@@ -260,6 +260,22 @@ int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *hdw, | |||
260 | sizeof(decoder_ops[0]))) - 1; | 260 | sizeof(decoder_ops[0]))) - 1; |
261 | hdw->decoder_ctrl = &ctxt->ctrl; | 261 | hdw->decoder_ctrl = &ctxt->ctrl; |
262 | cp->handler = &ctxt->handler; | 262 | cp->handler = &ctxt->handler; |
263 | { | ||
264 | /* | ||
265 | Mike Isely <isely@pobox.com> 19-Nov-2006 - This bit | ||
266 | of nuttiness for cx25840 causes that module to | ||
267 | correctly set up its video scaling. This is really | ||
268 | a problem in the cx25840 module itself, but we work | ||
269 | around it here. The problem has not been seen in | ||
270 | ivtv because there VBI is supported and set up. We | ||
271 | don't do VBI here (at least not yet) and thus we | ||
272 | never attempted to even set it up. | ||
273 | */ | ||
274 | struct v4l2_format fmt; | ||
275 | memset(&fmt,0,sizeof(fmt)); | ||
276 | fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; | ||
277 | pvr2_i2c_client_cmd(ctxt->client,VIDIOC_S_FMT,&fmt); | ||
278 | } | ||
263 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x cx2584x V4L2 handler set up", | 279 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x cx2584x V4L2 handler set up", |
264 | cp->client->addr); | 280 | cp->client->addr); |
265 | return !0; | 281 | return !0; |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 1f787333d18c..d2004965187b 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c | |||
@@ -356,28 +356,6 @@ static int ctrl_freq_set(struct pvr2_ctrl *cptr,int m,int v) | |||
356 | return 0; | 356 | return 0; |
357 | } | 357 | } |
358 | 358 | ||
359 | static int ctrl_hres_max_get(struct pvr2_ctrl *cptr,int *vp) | ||
360 | { | ||
361 | /* If we're dealing with a 24xxx device, force the horizontal | ||
362 | maximum to be 720 no matter what, since we can't get the device | ||
363 | to work properly with any other value. Otherwise just return | ||
364 | the normal value. */ | ||
365 | *vp = cptr->info->def.type_int.max_value; | ||
366 | if (cptr->hdw->hdw_type == PVR2_HDW_TYPE_24XXX) *vp = 720; | ||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | static int ctrl_hres_min_get(struct pvr2_ctrl *cptr,int *vp) | ||
371 | { | ||
372 | /* If we're dealing with a 24xxx device, force the horizontal | ||
373 | minimum to be 720 no matter what, since we can't get the device | ||
374 | to work properly with any other value. Otherwise just return | ||
375 | the normal value. */ | ||
376 | *vp = cptr->info->def.type_int.min_value; | ||
377 | if (cptr->hdw->hdw_type == PVR2_HDW_TYPE_24XXX) *vp = 720; | ||
378 | return 0; | ||
379 | } | ||
380 | |||
381 | static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp) | 359 | static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp) |
382 | { | 360 | { |
383 | /* Actual maximum depends on the video standard in effect. */ | 361 | /* Actual maximum depends on the video standard in effect. */ |
@@ -758,10 +736,6 @@ static const struct pvr2_ctl_info control_defs[] = { | |||
758 | .default_value = 720, | 736 | .default_value = 720, |
759 | DEFREF(res_hor), | 737 | DEFREF(res_hor), |
760 | DEFINT(19,720), | 738 | DEFINT(19,720), |
761 | /* Hook in check for clamp on horizontal resolution in | ||
762 | order to avoid unsolved problem involving cx25840. */ | ||
763 | .get_max_value = ctrl_hres_max_get, | ||
764 | .get_min_value = ctrl_hres_min_get, | ||
765 | },{ | 739 | },{ |
766 | .desc = "Vertical capture resolution", | 740 | .desc = "Vertical capture resolution", |
767 | .name = "resolution_ver", | 741 | .name = "resolution_ver", |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index 3b9012f8e380..f9bb41d8f4f3 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | |||
@@ -185,6 +185,79 @@ static int pvr2_i2c_basic_op(struct pvr2_hdw *hdw, | |||
185 | } | 185 | } |
186 | } | 186 | } |
187 | 187 | ||
188 | |||
189 | /* This is a special entry point for cases of I2C transaction attempts to | ||
190 | the IR receiver. The implementation here simulates the IR receiver by | ||
191 | issuing a command to the FX2 firmware and using that response to return | ||
192 | what the real I2C receiver would have returned. We use this for 24xxx | ||
193 | devices, where the IR receiver chip has been removed and replaced with | ||
194 | FX2 related logic. */ | ||
195 | static int i2c_24xxx_ir(struct pvr2_hdw *hdw, | ||
196 | u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen) | ||
197 | { | ||
198 | u8 dat[4]; | ||
199 | unsigned int stat; | ||
200 | |||
201 | if (!(rlen || wlen)) { | ||
202 | /* This is a probe attempt. Just let it succeed. */ | ||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | /* We don't understand this kind of transaction */ | ||
207 | if ((wlen != 0) || (rlen == 0)) return -EIO; | ||
208 | |||
209 | if (rlen < 3) { | ||
210 | /* Mike Isely <isely@pobox.com> Appears to be a probe | ||
211 | attempt from lirc. Just fill in zeroes and return. If | ||
212 | we try instead to do the full transaction here, then bad | ||
213 | things seem to happen within the lirc driver module | ||
214 | (version 0.8.0-7 sources from Debian, when run under | ||
215 | vanilla 2.6.17.6 kernel) - and I don't have the patience | ||
216 | to chase it down. */ | ||
217 | if (rlen > 0) rdata[0] = 0; | ||
218 | if (rlen > 1) rdata[1] = 0; | ||
219 | return 0; | ||
220 | } | ||
221 | |||
222 | /* Issue a command to the FX2 to read the IR receiver. */ | ||
223 | LOCK_TAKE(hdw->ctl_lock); do { | ||
224 | hdw->cmd_buffer[0] = 0xec; | ||
225 | stat = pvr2_send_request(hdw, | ||
226 | hdw->cmd_buffer,1, | ||
227 | hdw->cmd_buffer,4); | ||
228 | dat[0] = hdw->cmd_buffer[0]; | ||
229 | dat[1] = hdw->cmd_buffer[1]; | ||
230 | dat[2] = hdw->cmd_buffer[2]; | ||
231 | dat[3] = hdw->cmd_buffer[3]; | ||
232 | } while (0); LOCK_GIVE(hdw->ctl_lock); | ||
233 | |||
234 | /* Give up if that operation failed. */ | ||
235 | if (stat != 0) return stat; | ||
236 | |||
237 | /* Mangle the results into something that looks like the real IR | ||
238 | receiver. */ | ||
239 | rdata[2] = 0xc1; | ||
240 | if (dat[0] != 1) { | ||
241 | /* No code received. */ | ||
242 | rdata[0] = 0; | ||
243 | rdata[1] = 0; | ||
244 | } else { | ||
245 | u16 val; | ||
246 | /* Mash the FX2 firmware-provided IR code into something | ||
247 | that the normal i2c chip-level driver expects. */ | ||
248 | val = dat[1]; | ||
249 | val <<= 8; | ||
250 | val |= dat[2]; | ||
251 | val >>= 1; | ||
252 | val &= ~0x0003; | ||
253 | val |= 0x8000; | ||
254 | rdata[0] = (val >> 8) & 0xffu; | ||
255 | rdata[1] = val & 0xffu; | ||
256 | } | ||
257 | |||
258 | return 0; | ||
259 | } | ||
260 | |||
188 | /* This is a special entry point that is entered if an I2C operation is | 261 | /* This is a special entry point that is entered if an I2C operation is |
189 | attempted to a wm8775 chip on model 24xxx hardware. Autodetect of this | 262 | attempted to a wm8775 chip on model 24xxx hardware. Autodetect of this |
190 | part doesn't work, but we know it is really there. So let's look for | 263 | part doesn't work, but we know it is really there. So let's look for |
@@ -887,17 +960,17 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw) | |||
887 | { | 960 | { |
888 | unsigned int idx; | 961 | unsigned int idx; |
889 | 962 | ||
890 | // The default action for all possible I2C addresses is just to do | 963 | /* The default action for all possible I2C addresses is just to do |
891 | // the transfer normally. | 964 | the transfer normally. */ |
892 | for (idx = 0; idx < PVR2_I2C_FUNC_CNT; idx++) { | 965 | for (idx = 0; idx < PVR2_I2C_FUNC_CNT; idx++) { |
893 | hdw->i2c_func[idx] = pvr2_i2c_basic_op; | 966 | hdw->i2c_func[idx] = pvr2_i2c_basic_op; |
894 | } | 967 | } |
895 | 968 | ||
896 | // If however we're dealing with new hardware, insert some hacks in | 969 | /* However, deal with various special cases for 24xxx hardware. */ |
897 | // the I2C transfer stack to let things work better. | ||
898 | if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) { | 970 | if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) { |
899 | hdw->i2c_func[0x1b] = i2c_hack_wm8775; | 971 | hdw->i2c_func[0x1b] = i2c_hack_wm8775; |
900 | hdw->i2c_func[0x44] = i2c_hack_cx25840; | 972 | hdw->i2c_func[0x44] = i2c_hack_cx25840; |
973 | hdw->i2c_func[0x18] = i2c_24xxx_ir; | ||
901 | } | 974 | } |
902 | 975 | ||
903 | // Configure the adapter and set up everything else related to it. | 976 | // Configure the adapter and set up everything else related to it. |
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index f28398dd9d93..c2374ed7ba9f 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c | |||
@@ -851,7 +851,7 @@ static int saa711x_set_size(struct i2c_client *client, int width, int height) | |||
851 | 851 | ||
852 | /* On 60Hz, it is using a higher Vertical Output Size */ | 852 | /* On 60Hz, it is using a higher Vertical Output Size */ |
853 | if (!is_50hz) | 853 | if (!is_50hz) |
854 | res+=(VRES_60HZ-480)>>1; | 854 | res += (VRES_60HZ - 480) >> 1; |
855 | 855 | ||
856 | /* height */ | 856 | /* height */ |
857 | saa711x_write(client, R_CE_B_VERT_OUTPUT_WINDOW_LENGTH, | 857 | saa711x_write(client, R_CE_B_VERT_OUTPUT_WINDOW_LENGTH, |
@@ -907,7 +907,7 @@ static int saa711x_set_size(struct i2c_client *client, int width, int height) | |||
907 | 907 | ||
908 | /* Activates task "B" */ | 908 | /* Activates task "B" */ |
909 | saa711x_write(client, R_80_GLOBAL_CNTL_1, | 909 | saa711x_write(client, R_80_GLOBAL_CNTL_1, |
910 | saa711x_read(client,R_80_GLOBAL_CNTL_1)|0x20); | 910 | saa711x_read(client,R_80_GLOBAL_CNTL_1) | 0x20); |
911 | 911 | ||
912 | return 0; | 912 | return 0; |
913 | } | 913 | } |
@@ -932,11 +932,11 @@ static void saa711x_set_v4lstd(struct i2c_client *client, v4l2_std_id std) | |||
932 | if (std & V4L2_STD_525_60) { | 932 | if (std & V4L2_STD_525_60) { |
933 | v4l_dbg(1, debug, client, "decoder set standard 60 Hz\n"); | 933 | v4l_dbg(1, debug, client, "decoder set standard 60 Hz\n"); |
934 | saa711x_writeregs(client, saa7115_cfg_60hz_video); | 934 | saa711x_writeregs(client, saa7115_cfg_60hz_video); |
935 | saa711x_set_size(client,720,480); | 935 | saa711x_set_size(client, 720, 480); |
936 | } else { | 936 | } else { |
937 | v4l_dbg(1, debug, client, "decoder set standard 50 Hz\n"); | 937 | v4l_dbg(1, debug, client, "decoder set standard 50 Hz\n"); |
938 | saa711x_writeregs(client, saa7115_cfg_50hz_video); | 938 | saa711x_writeregs(client, saa7115_cfg_50hz_video); |
939 | saa711x_set_size(client,720,576); | 939 | saa711x_set_size(client, 720, 576); |
940 | } | 940 | } |
941 | 941 | ||
942 | /* Register 0E - Bits D6-D4 on NO-AUTO mode | 942 | /* Register 0E - Bits D6-D4 on NO-AUTO mode |
@@ -1464,13 +1464,13 @@ static int saa711x_attach(struct i2c_adapter *adapter, int address, int kind) | |||
1464 | client->driver = &i2c_driver_saa711x; | 1464 | client->driver = &i2c_driver_saa711x; |
1465 | snprintf(client->name, sizeof(client->name) - 1, "saa7115"); | 1465 | snprintf(client->name, sizeof(client->name) - 1, "saa7115"); |
1466 | 1466 | ||
1467 | for (i=0;i<0x0f;i++) { | 1467 | for (i = 0; i < 0x0f; i++) { |
1468 | saa711x_write(client, 0, i); | 1468 | saa711x_write(client, 0, i); |
1469 | name[i] = (saa711x_read(client, 0) &0x0f) +'0'; | 1469 | name[i] = (saa711x_read(client, 0) & 0x0f) + '0'; |
1470 | if (name[i]>'9') | 1470 | if (name[i] > '9') |
1471 | name[i]+='a'-'9'-1; | 1471 | name[i] += 'a' - '9' - 1; |
1472 | } | 1472 | } |
1473 | name[i]='\0'; | 1473 | name[i] = '\0'; |
1474 | 1474 | ||
1475 | saa711x_write(client, 0, 5); | 1475 | saa711x_write(client, 0, 5); |
1476 | chip_id = saa711x_read(client, 0) & 0x0f; | 1476 | chip_id = saa711x_read(client, 0) & 0x0f; |
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index 4abf5c03a740..ffb0f647a86d 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c | |||
@@ -1,10 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * SAA713x ALSA support for V4L | 2 | * SAA713x ALSA support for V4L |
3 | * | 3 | * |
4 | * | ||
5 | * Caveats: | ||
6 | * - Volume doesn't work (it's always at max) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | 4 | * 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 | 5 | * it under the terms of the GNU General Public License as published by |
10 | * the Free Software Foundation, version 2 | 6 | * the Free Software Foundation, version 2 |
@@ -614,13 +610,18 @@ static int snd_card_saa7134_capture_open(struct snd_pcm_substream * substream) | |||
614 | snd_card_saa7134_pcm_t *pcm; | 610 | snd_card_saa7134_pcm_t *pcm; |
615 | snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); | 611 | snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); |
616 | struct saa7134_dev *dev = saa7134->dev; | 612 | struct saa7134_dev *dev = saa7134->dev; |
617 | int err; | 613 | int amux, err; |
618 | 614 | ||
619 | mutex_lock(&dev->dmasound.lock); | 615 | mutex_lock(&dev->dmasound.lock); |
620 | 616 | ||
621 | dev->dmasound.read_count = 0; | 617 | dev->dmasound.read_count = 0; |
622 | dev->dmasound.read_offset = 0; | 618 | dev->dmasound.read_offset = 0; |
623 | 619 | ||
620 | amux = dev->input->amux; | ||
621 | if ((amux < 1) || (amux > 3)) | ||
622 | amux = 1; | ||
623 | dev->dmasound.input = amux - 1; | ||
624 | |||
624 | mutex_unlock(&dev->dmasound.lock); | 625 | mutex_unlock(&dev->dmasound.lock); |
625 | 626 | ||
626 | pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); | 627 | pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); |
@@ -713,6 +714,8 @@ static int snd_saa7134_volume_put(struct snd_kcontrol * kcontrol, | |||
713 | struct snd_ctl_elem_value * ucontrol) | 714 | struct snd_ctl_elem_value * ucontrol) |
714 | { | 715 | { |
715 | snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); | 716 | snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); |
717 | struct saa7134_dev *dev = chip->dev; | ||
718 | |||
716 | int change, addr = kcontrol->private_value; | 719 | int change, addr = kcontrol->private_value; |
717 | int left, right; | 720 | int left, right; |
718 | 721 | ||
@@ -727,10 +730,52 @@ static int snd_saa7134_volume_put(struct snd_kcontrol * kcontrol, | |||
727 | if (right > 20) | 730 | if (right > 20) |
728 | right = 20; | 731 | right = 20; |
729 | spin_lock_irq(&chip->mixer_lock); | 732 | spin_lock_irq(&chip->mixer_lock); |
730 | change = chip->mixer_volume[addr][0] != left || | 733 | change = 0; |
731 | chip->mixer_volume[addr][1] != right; | 734 | if (chip->mixer_volume[addr][0] != left) { |
732 | chip->mixer_volume[addr][0] = left; | 735 | change = 1; |
733 | chip->mixer_volume[addr][1] = right; | 736 | right = left; |
737 | } | ||
738 | if (chip->mixer_volume[addr][1] != right) { | ||
739 | change = 1; | ||
740 | left = right; | ||
741 | } | ||
742 | if (change) { | ||
743 | switch (dev->pci->device) { | ||
744 | case PCI_DEVICE_ID_PHILIPS_SAA7134: | ||
745 | switch (addr) { | ||
746 | case MIXER_ADDR_TVTUNER: | ||
747 | left = 20; | ||
748 | break; | ||
749 | case MIXER_ADDR_LINE1: | ||
750 | saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x10, | ||
751 | (left > 10) ? 0x00 : 0x10); | ||
752 | break; | ||
753 | case MIXER_ADDR_LINE2: | ||
754 | saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x20, | ||
755 | (left > 10) ? 0x00 : 0x20); | ||
756 | break; | ||
757 | } | ||
758 | break; | ||
759 | case PCI_DEVICE_ID_PHILIPS_SAA7133: | ||
760 | case PCI_DEVICE_ID_PHILIPS_SAA7135: | ||
761 | switch (addr) { | ||
762 | case MIXER_ADDR_TVTUNER: | ||
763 | left = 20; | ||
764 | break; | ||
765 | case MIXER_ADDR_LINE1: | ||
766 | saa_andorb(0x0594, 0x10, | ||
767 | (left > 10) ? 0x00 : 0x10); | ||
768 | break; | ||
769 | case MIXER_ADDR_LINE2: | ||
770 | saa_andorb(0x0594, 0x20, | ||
771 | (left > 10) ? 0x00 : 0x20); | ||
772 | break; | ||
773 | } | ||
774 | break; | ||
775 | } | ||
776 | chip->mixer_volume[addr][0] = left; | ||
777 | chip->mixer_volume[addr][1] = right; | ||
778 | } | ||
734 | spin_unlock_irq(&chip->mixer_lock); | 779 | spin_unlock_irq(&chip->mixer_lock); |
735 | return change; | 780 | return change; |
736 | } | 781 | } |
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 51f0cfdcb680..4dead84aff46 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c | |||
@@ -2462,14 +2462,17 @@ struct saa7134_board saa7134_boards[] = { | |||
2462 | .vmux = 1, | 2462 | .vmux = 1, |
2463 | .amux = TV, | 2463 | .amux = TV, |
2464 | .tv = 1, | 2464 | .tv = 1, |
2465 | .gpio = 0x0000000, | ||
2465 | },{ | 2466 | },{ |
2466 | .name = name_comp1, | 2467 | .name = name_comp1, |
2467 | .vmux = 3, | 2468 | .vmux = 3, |
2468 | .amux = LINE2, | 2469 | .amux = LINE2, |
2470 | .gpio = 0x0200000, | ||
2469 | },{ | 2471 | },{ |
2470 | .name = name_svideo, | 2472 | .name = name_svideo, |
2471 | .vmux = 8, | 2473 | .vmux = 8, |
2472 | .amux = LINE2, | 2474 | .amux = LINE2, |
2475 | .gpio = 0x0200000, | ||
2473 | }}, | 2476 | }}, |
2474 | .radio = { | 2477 | .radio = { |
2475 | .name = name_radio, | 2478 | .name = name_radio, |
@@ -3022,6 +3025,158 @@ struct saa7134_board saa7134_boards[] = { | |||
3022 | .amux = LINE1, | 3025 | .amux = LINE1, |
3023 | }, | 3026 | }, |
3024 | }, | 3027 | }, |
3028 | [SAA7134_BOARD_PINNACLE_PCTV_310i] = { | ||
3029 | .name = "Pinnacle PCTV 310i", | ||
3030 | .audio_clock = 0x00187de7, | ||
3031 | .tuner_type = TUNER_PHILIPS_TDA8290, | ||
3032 | .radio_type = UNSET, | ||
3033 | .tuner_addr = ADDR_UNSET, | ||
3034 | .radio_addr = ADDR_UNSET, | ||
3035 | .mpeg = SAA7134_MPEG_DVB, | ||
3036 | .gpiomask = 0x000200000, | ||
3037 | .inputs = {{ | ||
3038 | .name = name_tv, | ||
3039 | .vmux = 4, | ||
3040 | .amux = TV, | ||
3041 | .tv = 1, | ||
3042 | },{ | ||
3043 | .name = name_comp1, | ||
3044 | .vmux = 1, | ||
3045 | .amux = LINE2, | ||
3046 | },{ | ||
3047 | .name = name_comp2, | ||
3048 | .vmux = 0, | ||
3049 | .amux = LINE2, | ||
3050 | },{ | ||
3051 | .name = name_svideo, | ||
3052 | .vmux = 8, | ||
3053 | .amux = LINE2, | ||
3054 | }}, | ||
3055 | .radio = { | ||
3056 | .name = name_radio, | ||
3057 | .amux = TV, | ||
3058 | .gpio = 0x0200000, | ||
3059 | }, | ||
3060 | }, | ||
3061 | [SAA7134_BOARD_AVERMEDIA_STUDIO_507] = { | ||
3062 | /* Mikhail Fedotov <mo_fedotov@mail.ru> */ | ||
3063 | .name = "Avermedia AVerTV Studio 507", | ||
3064 | .audio_clock = 0x00187de7, | ||
3065 | .tuner_type = TUNER_PHILIPS_FM1256_IH3, | ||
3066 | .radio_type = UNSET, | ||
3067 | .tuner_addr = ADDR_UNSET, | ||
3068 | .radio_addr = ADDR_UNSET, | ||
3069 | .tda9887_conf = TDA9887_PRESENT, | ||
3070 | .gpiomask = 0x03, | ||
3071 | .inputs = {{ | ||
3072 | .name = name_tv, | ||
3073 | .vmux = 1, | ||
3074 | .amux = TV, | ||
3075 | .tv = 1, | ||
3076 | .gpio = 0x00, | ||
3077 | },{ | ||
3078 | .name = name_comp1, | ||
3079 | .vmux = 0, | ||
3080 | .amux = LINE2, | ||
3081 | .gpio = 0x00, | ||
3082 | },{ | ||
3083 | .name = name_comp2, | ||
3084 | .vmux = 3, | ||
3085 | .amux = LINE2, | ||
3086 | .gpio = 0x00, | ||
3087 | },{ | ||
3088 | .name = name_svideo, | ||
3089 | .vmux = 8, | ||
3090 | .amux = LINE2, | ||
3091 | .gpio = 0x00, | ||
3092 | }}, | ||
3093 | .radio = { | ||
3094 | .name = name_radio, | ||
3095 | .amux = LINE2, | ||
3096 | .gpio = 0x01, | ||
3097 | }, | ||
3098 | .mute = { | ||
3099 | .name = name_mute, | ||
3100 | .amux = LINE1, | ||
3101 | .gpio = 0x00, | ||
3102 | }, | ||
3103 | }, | ||
3104 | [SAA7134_BOARD_VIDEOMATE_DVBT_200A] = { | ||
3105 | /* Francis Barber <fedora@barber-family.id.au> */ | ||
3106 | .name = "Compro Videomate DVB-T200A", | ||
3107 | .audio_clock = 0x00187de7, | ||
3108 | .tuner_type = TUNER_ABSENT, | ||
3109 | .radio_type = UNSET, | ||
3110 | .tuner_addr = ADDR_UNSET, | ||
3111 | .radio_addr = ADDR_UNSET, | ||
3112 | .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE, | ||
3113 | .mpeg = SAA7134_MPEG_DVB, | ||
3114 | .inputs = {{ | ||
3115 | .name = name_tv, | ||
3116 | .vmux = 3, | ||
3117 | .amux = TV, | ||
3118 | .tv = 1, | ||
3119 | },{ | ||
3120 | .name = name_comp1, | ||
3121 | .vmux = 1, | ||
3122 | .amux = LINE2, | ||
3123 | },{ | ||
3124 | .name = name_svideo, | ||
3125 | .vmux = 8, | ||
3126 | .amux = LINE2, | ||
3127 | }}, | ||
3128 | }, | ||
3129 | [SAA7134_BOARD_HAUPPAUGE_HVR1110] = { | ||
3130 | /* Thomas Genty <tomlohave@gmail.com> */ | ||
3131 | .name = "Hauppauge WinTV-HVR1110 DVB-T/Hybrid", | ||
3132 | .audio_clock = 0x00187de7, | ||
3133 | .tuner_type = TUNER_PHILIPS_TDA8290, | ||
3134 | .radio_type = UNSET, | ||
3135 | .tuner_addr = ADDR_UNSET, | ||
3136 | .radio_addr = ADDR_UNSET, | ||
3137 | .mpeg = SAA7134_MPEG_DVB, | ||
3138 | .inputs = {{ | ||
3139 | .name = name_tv, | ||
3140 | .vmux = 1, | ||
3141 | .amux = TV, | ||
3142 | .tv = 1, | ||
3143 | },{ | ||
3144 | .name = name_comp1, | ||
3145 | .vmux = 3, | ||
3146 | .amux = LINE2, /* FIXME: audio doesn't work on svideo/composite */ | ||
3147 | },{ | ||
3148 | .name = name_svideo, | ||
3149 | .vmux = 8, | ||
3150 | .amux = LINE2, /* FIXME: audio doesn't work on svideo/composite */ | ||
3151 | }}, | ||
3152 | .radio = { | ||
3153 | .name = name_radio, | ||
3154 | .amux = TV, | ||
3155 | }, | ||
3156 | }, | ||
3157 | [SAA7134_BOARD_CINERGY_HT_PCMCIA] = { | ||
3158 | .name = "Terratec Cinergy HT PCMCIA", | ||
3159 | .audio_clock = 0x00187de7, | ||
3160 | .tuner_type = TUNER_PHILIPS_TDA8290, | ||
3161 | .radio_type = UNSET, | ||
3162 | .tuner_addr = ADDR_UNSET, | ||
3163 | .radio_addr = ADDR_UNSET, | ||
3164 | .mpeg = SAA7134_MPEG_DVB, | ||
3165 | .inputs = {{ | ||
3166 | .name = name_tv, | ||
3167 | .vmux = 1, | ||
3168 | .amux = TV, | ||
3169 | .tv = 1, | ||
3170 | },{ | ||
3171 | .name = name_comp1, | ||
3172 | .vmux = 0, | ||
3173 | .amux = LINE1, | ||
3174 | },{ | ||
3175 | .name = name_svideo, | ||
3176 | .vmux = 6, | ||
3177 | .amux = LINE1, | ||
3178 | }}, | ||
3179 | }, | ||
3025 | }; | 3180 | }; |
3026 | 3181 | ||
3027 | const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); | 3182 | const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); |
@@ -3631,6 +3786,36 @@ struct pci_device_id saa7134_pci_tbl[] = { | |||
3631 | .subdevice = 0x4860, | 3786 | .subdevice = 0x4860, |
3632 | .driver_data = SAA7134_BOARD_ASUS_EUROPA2_HYBRID, | 3787 | .driver_data = SAA7134_BOARD_ASUS_EUROPA2_HYBRID, |
3633 | },{ | 3788 | },{ |
3789 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
3790 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | ||
3791 | .subvendor = 0x11bd, | ||
3792 | .subdevice = 0x002f, | ||
3793 | .driver_data = SAA7134_BOARD_PINNACLE_PCTV_310i, | ||
3794 | },{ | ||
3795 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
3796 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | ||
3797 | .subvendor = 0x1461, /* Avermedia Technologies Inc */ | ||
3798 | .subdevice = 0x9715, | ||
3799 | .driver_data = SAA7134_BOARD_AVERMEDIA_STUDIO_507, | ||
3800 | },{ | ||
3801 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
3802 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | ||
3803 | .subvendor = 0x1043, | ||
3804 | .subdevice = 0x4876, | ||
3805 | .driver_data = SAA7134_BOARD_ASUSTeK_P7131_DUAL, | ||
3806 | },{ | ||
3807 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
3808 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | ||
3809 | .subvendor = 0x0070, | ||
3810 | .subdevice = 0x6701, | ||
3811 | .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1110, | ||
3812 | },{ | ||
3813 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
3814 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | ||
3815 | .subvendor = 0x153b, | ||
3816 | .subdevice = 0x1172, | ||
3817 | .driver_data = SAA7134_BOARD_CINERGY_HT_PCMCIA, | ||
3818 | },{ | ||
3634 | /* --- boards without eeprom + subsystem ID --- */ | 3819 | /* --- boards without eeprom + subsystem ID --- */ |
3635 | .vendor = PCI_VENDOR_ID_PHILIPS, | 3820 | .vendor = PCI_VENDOR_ID_PHILIPS, |
3636 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, | 3821 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, |
@@ -3717,6 +3902,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
3717 | case SAA7134_BOARD_AVERMEDIA_305: | 3902 | case SAA7134_BOARD_AVERMEDIA_305: |
3718 | case SAA7134_BOARD_AVERMEDIA_STUDIO_307: | 3903 | case SAA7134_BOARD_AVERMEDIA_STUDIO_307: |
3719 | case SAA7134_BOARD_AVERMEDIA_307: | 3904 | case SAA7134_BOARD_AVERMEDIA_307: |
3905 | case SAA7134_BOARD_AVERMEDIA_STUDIO_507: | ||
3720 | case SAA7134_BOARD_AVERMEDIA_GO_007_FM: | 3906 | case SAA7134_BOARD_AVERMEDIA_GO_007_FM: |
3721 | case SAA7134_BOARD_AVERMEDIA_777: | 3907 | case SAA7134_BOARD_AVERMEDIA_777: |
3722 | /* case SAA7134_BOARD_SABRENT_SBTTVFM: */ /* not finished yet */ | 3908 | /* case SAA7134_BOARD_SABRENT_SBTTVFM: */ /* not finished yet */ |
@@ -3725,6 +3911,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
3725 | case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII: | 3911 | case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII: |
3726 | case SAA7134_BOARD_VIDEOMATE_DVBT_300: | 3912 | case SAA7134_BOARD_VIDEOMATE_DVBT_300: |
3727 | case SAA7134_BOARD_VIDEOMATE_DVBT_200: | 3913 | case SAA7134_BOARD_VIDEOMATE_DVBT_200: |
3914 | case SAA7134_BOARD_VIDEOMATE_DVBT_200A: | ||
3728 | case SAA7134_BOARD_MANLI_MTV001: | 3915 | case SAA7134_BOARD_MANLI_MTV001: |
3729 | case SAA7134_BOARD_MANLI_MTV002: | 3916 | case SAA7134_BOARD_MANLI_MTV002: |
3730 | case SAA7134_BOARD_BEHOLD_409FM: | 3917 | case SAA7134_BOARD_BEHOLD_409FM: |
@@ -3793,7 +3980,9 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
3793 | break; | 3980 | break; |
3794 | /* i2c remotes */ | 3981 | /* i2c remotes */ |
3795 | case SAA7134_BOARD_PINNACLE_PCTV_110i: | 3982 | case SAA7134_BOARD_PINNACLE_PCTV_110i: |
3983 | case SAA7134_BOARD_PINNACLE_PCTV_310i: | ||
3796 | case SAA7134_BOARD_UPMOST_PURPLE_TV: | 3984 | case SAA7134_BOARD_UPMOST_PURPLE_TV: |
3985 | case SAA7134_BOARD_HAUPPAUGE_HVR1110: | ||
3797 | dev->has_remote = SAA7134_REMOTE_I2C; | 3986 | dev->has_remote = SAA7134_REMOTE_I2C; |
3798 | break; | 3987 | break; |
3799 | case SAA7134_BOARD_AVERMEDIA_A169_B: | 3988 | case SAA7134_BOARD_AVERMEDIA_A169_B: |
@@ -3924,9 +4113,11 @@ int saa7134_board_init2(struct saa7134_dev *dev) | |||
3924 | } | 4113 | } |
3925 | break; | 4114 | break; |
3926 | case SAA7134_BOARD_PHILIPS_TIGER: | 4115 | case SAA7134_BOARD_PHILIPS_TIGER: |
4116 | case SAA7134_BOARD_PINNACLE_PCTV_310i: | ||
3927 | case SAA7134_BOARD_TEVION_DVBT_220RF: | 4117 | case SAA7134_BOARD_TEVION_DVBT_220RF: |
3928 | case SAA7134_BOARD_ASUSTeK_P7131_DUAL: | 4118 | case SAA7134_BOARD_ASUSTeK_P7131_DUAL: |
3929 | case SAA7134_BOARD_MEDION_MD8800_QUADRO: | 4119 | case SAA7134_BOARD_MEDION_MD8800_QUADRO: |
4120 | case SAA7134_BOARD_HAUPPAUGE_HVR1110: | ||
3930 | /* this is a hybrid board, initialize to analog mode | 4121 | /* this is a hybrid board, initialize to analog mode |
3931 | * and configure firmware eeprom address | 4122 | * and configure firmware eeprom address |
3932 | */ | 4123 | */ |
@@ -3952,6 +4143,14 @@ int saa7134_board_init2(struct saa7134_dev *dev) | |||
3952 | i2c_transfer(&dev->i2c_adap, &msg, 1); | 4143 | i2c_transfer(&dev->i2c_adap, &msg, 1); |
3953 | } | 4144 | } |
3954 | break; | 4145 | break; |
4146 | case SAA7134_BOARD_CINERGY_HT_PCMCIA: | ||
4147 | /* make the tda10046 find its eeprom */ | ||
4148 | { | ||
4149 | u8 data[] = { 0x3c, 0x33, 0x60}; | ||
4150 | struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)}; | ||
4151 | i2c_transfer(&dev->i2c_adap, &msg, 1); | ||
4152 | } | ||
4153 | break; | ||
3955 | case SAA7134_BOARD_KWORLD_ATSC110: | 4154 | case SAA7134_BOARD_KWORLD_ATSC110: |
3956 | { | 4155 | { |
3957 | /* enable tuner */ | 4156 | /* enable tuner */ |
@@ -3964,6 +4163,29 @@ int saa7134_board_init2(struct saa7134_dev *dev) | |||
3964 | dev->name, i); | 4163 | dev->name, i); |
3965 | } | 4164 | } |
3966 | break; | 4165 | break; |
4166 | case SAA7134_BOARD_VIDEOMATE_DVBT_200: | ||
4167 | case SAA7134_BOARD_VIDEOMATE_DVBT_200A: | ||
4168 | /* The T200 and the T200A share the same pci id. Consequently, | ||
4169 | * we are going to query eeprom to try to find out which one we | ||
4170 | * are actually looking at. */ | ||
4171 | |||
4172 | /* Don't do this if the board was specifically selected with an | ||
4173 | * insmod option or if we have the default configuration T200*/ | ||
4174 | if(!dev->autodetected || (dev->eedata[0x41] == 0xd0)) | ||
4175 | break; | ||
4176 | if(dev->eedata[0x41] == 0x02) { | ||
4177 | /* Reconfigure board as T200A */ | ||
4178 | dev->board = SAA7134_BOARD_VIDEOMATE_DVBT_200A; | ||
4179 | dev->tuner_type = saa7134_boards[dev->board].tuner_type; | ||
4180 | dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf; | ||
4181 | printk(KERN_INFO "%s: Reconfigured board as %s\n", | ||
4182 | dev->name, saa7134_boards[dev->board].name); | ||
4183 | } else { | ||
4184 | printk(KERN_WARNING "%s: Unexpected tuner type info: %x in eeprom\n", | ||
4185 | dev->name, dev->eedata[0x41]); | ||
4186 | break; | ||
4187 | } | ||
4188 | break; | ||
3967 | } | 4189 | } |
3968 | return 0; | 4190 | return 0; |
3969 | } | 4191 | } |
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 5c9e63dfbea6..ed038fff3b4f 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c | |||
@@ -889,15 +889,16 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, | |||
889 | must_configure_manually(); | 889 | must_configure_manually(); |
890 | dev->board = SAA7134_BOARD_UNKNOWN; | 890 | dev->board = SAA7134_BOARD_UNKNOWN; |
891 | } | 891 | } |
892 | dev->autodetected = card[dev->nr] != dev->board; | ||
892 | dev->tuner_type = saa7134_boards[dev->board].tuner_type; | 893 | dev->tuner_type = saa7134_boards[dev->board].tuner_type; |
893 | dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf; | 894 | dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf; |
894 | if (UNSET != tuner[dev->nr]) | 895 | if (UNSET != tuner[dev->nr]) |
895 | dev->tuner_type = tuner[dev->nr]; | 896 | dev->tuner_type = tuner[dev->nr]; |
896 | printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", | 897 | printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", |
897 | dev->name,pci_dev->subsystem_vendor, | 898 | dev->name,pci_dev->subsystem_vendor, |
898 | pci_dev->subsystem_device,saa7134_boards[dev->board].name, | 899 | pci_dev->subsystem_device,saa7134_boards[dev->board].name, |
899 | dev->board, card[dev->nr] == dev->board ? | 900 | dev->board, dev->autodetected ? |
900 | "insmod option" : "autodetected"); | 901 | "autodetected" : "insmod option"); |
901 | 902 | ||
902 | /* get mmio */ | 903 | /* get mmio */ |
903 | if (!request_mem_region(pci_resource_start(pci_dev,0), | 904 | if (!request_mem_region(pci_resource_start(pci_dev,0), |
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 6b61d9b2fcb5..fa8339879095 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c | |||
@@ -50,6 +50,10 @@ static unsigned int antenna_pwr = 0; | |||
50 | module_param(antenna_pwr, int, 0444); | 50 | module_param(antenna_pwr, int, 0444); |
51 | MODULE_PARM_DESC(antenna_pwr,"enable antenna power (Pinnacle 300i)"); | 51 | MODULE_PARM_DESC(antenna_pwr,"enable antenna power (Pinnacle 300i)"); |
52 | 52 | ||
53 | static int use_frontent = 0; | ||
54 | module_param(use_frontent, int, 0644); | ||
55 | MODULE_PARM_DESC(use_frontent,"for cards with multiple frontends (0: terrestrial, 1: satellite)"); | ||
56 | |||
53 | /* ------------------------------------------------------------------ */ | 57 | /* ------------------------------------------------------------------ */ |
54 | static int pinnacle_antenna_pwr(struct saa7134_dev *dev, int on) | 58 | static int pinnacle_antenna_pwr(struct saa7134_dev *dev, int on) |
55 | { | 59 | { |
@@ -293,7 +297,7 @@ static int philips_tu1216_tuner_60_set_params(struct dvb_frontend *fe, struct dv | |||
293 | return philips_tda6651_pll_set(0x60, fe, params); | 297 | return philips_tda6651_pll_set(0x60, fe, params); |
294 | } | 298 | } |
295 | 299 | ||
296 | static int philips_tu1216_request_firmware(struct dvb_frontend *fe, | 300 | static int philips_tda1004x_request_firmware(struct dvb_frontend *fe, |
297 | const struct firmware **fw, char *name) | 301 | const struct firmware **fw, char *name) |
298 | { | 302 | { |
299 | struct saa7134_dev *dev = fe->dvb->priv; | 303 | struct saa7134_dev *dev = fe->dvb->priv; |
@@ -308,7 +312,7 @@ static struct tda1004x_config philips_tu1216_60_config = { | |||
308 | .xtal_freq = TDA10046_XTAL_4M, | 312 | .xtal_freq = TDA10046_XTAL_4M, |
309 | .agc_config = TDA10046_AGC_DEFAULT, | 313 | .agc_config = TDA10046_AGC_DEFAULT, |
310 | .if_freq = TDA10046_FREQ_3617, | 314 | .if_freq = TDA10046_FREQ_3617, |
311 | .request_firmware = philips_tu1216_request_firmware, | 315 | .request_firmware = philips_tda1004x_request_firmware, |
312 | }; | 316 | }; |
313 | 317 | ||
314 | /* ------------------------------------------------------------------ */ | 318 | /* ------------------------------------------------------------------ */ |
@@ -331,12 +335,12 @@ static struct tda1004x_config philips_tu1216_61_config = { | |||
331 | .xtal_freq = TDA10046_XTAL_4M, | 335 | .xtal_freq = TDA10046_XTAL_4M, |
332 | .agc_config = TDA10046_AGC_DEFAULT, | 336 | .agc_config = TDA10046_AGC_DEFAULT, |
333 | .if_freq = TDA10046_FREQ_3617, | 337 | .if_freq = TDA10046_FREQ_3617, |
334 | .request_firmware = philips_tu1216_request_firmware, | 338 | .request_firmware = philips_tda1004x_request_firmware, |
335 | }; | 339 | }; |
336 | 340 | ||
337 | /* ------------------------------------------------------------------ */ | 341 | /* ------------------------------------------------------------------ */ |
338 | 342 | ||
339 | static int philips_europa_tuner_init(struct dvb_frontend *fe) | 343 | static int philips_td1316_tuner_init(struct dvb_frontend *fe) |
340 | { | 344 | { |
341 | struct saa7134_dev *dev = fe->dvb->priv; | 345 | struct saa7134_dev *dev = fe->dvb->priv; |
342 | static u8 msg[] = { 0x0b, 0xf5, 0x86, 0xab }; | 346 | static u8 msg[] = { 0x0b, 0xf5, 0x86, 0xab }; |
@@ -347,18 +351,8 @@ static int philips_europa_tuner_init(struct dvb_frontend *fe) | |||
347 | fe->ops.i2c_gate_ctrl(fe, 1); | 351 | fe->ops.i2c_gate_ctrl(fe, 1); |
348 | if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1) | 352 | if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1) |
349 | return -EIO; | 353 | return -EIO; |
350 | msleep(1); | ||
351 | |||
352 | /* switch the board to dvb mode */ | ||
353 | init_msg.addr = 0x43; | ||
354 | init_msg.len = 0x02; | ||
355 | msg[0] = 0x00; | ||
356 | msg[1] = 0x40; | ||
357 | if (fe->ops.i2c_gate_ctrl) | 354 | if (fe->ops.i2c_gate_ctrl) |
358 | fe->ops.i2c_gate_ctrl(fe, 1); | 355 | fe->ops.i2c_gate_ctrl(fe, 0); |
359 | if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1) | ||
360 | return -EIO; | ||
361 | |||
362 | return 0; | 356 | return 0; |
363 | } | 357 | } |
364 | 358 | ||
@@ -367,6 +361,22 @@ static int philips_td1316_tuner_set_params(struct dvb_frontend *fe, struct dvb_f | |||
367 | return philips_tda6651_pll_set(0x61, fe, params); | 361 | return philips_tda6651_pll_set(0x61, fe, params); |
368 | } | 362 | } |
369 | 363 | ||
364 | static int philips_europa_tuner_init(struct dvb_frontend *fe) | ||
365 | { | ||
366 | struct saa7134_dev *dev = fe->dvb->priv; | ||
367 | static u8 msg[] = { 0x00, 0x40}; | ||
368 | struct i2c_msg init_msg = {.addr = 0x43,.flags = 0,.buf = msg,.len = sizeof(msg) }; | ||
369 | |||
370 | |||
371 | if (philips_td1316_tuner_init(fe)) | ||
372 | return -EIO; | ||
373 | msleep(1); | ||
374 | if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1) | ||
375 | return -EIO; | ||
376 | |||
377 | return 0; | ||
378 | } | ||
379 | |||
370 | static int philips_europa_tuner_sleep(struct dvb_frontend *fe) | 380 | static int philips_europa_tuner_sleep(struct dvb_frontend *fe) |
371 | { | 381 | { |
372 | struct saa7134_dev *dev = fe->dvb->priv; | 382 | struct saa7134_dev *dev = fe->dvb->priv; |
@@ -671,7 +681,7 @@ static struct tda1004x_config tda827x_lifeview_config = { | |||
671 | .invert = 1, | 681 | .invert = 1, |
672 | .invert_oclk = 0, | 682 | .invert_oclk = 0, |
673 | .xtal_freq = TDA10046_XTAL_16M, | 683 | .xtal_freq = TDA10046_XTAL_16M, |
674 | .agc_config = TDA10046_AGC_TDA827X, | 684 | .agc_config = TDA10046_AGC_TDA827X_GP11, |
675 | .if_freq = TDA10046_FREQ_045, | 685 | .if_freq = TDA10046_FREQ_045, |
676 | .request_firmware = NULL, | 686 | .request_firmware = NULL, |
677 | }; | 687 | }; |
@@ -812,32 +822,40 @@ static int philips_tda827xa_tuner_sleep(u8 addr, struct dvb_frontend *fe) | |||
812 | if (fe->ops.i2c_gate_ctrl) | 822 | if (fe->ops.i2c_gate_ctrl) |
813 | fe->ops.i2c_gate_ctrl(fe, 1); | 823 | fe->ops.i2c_gate_ctrl(fe, 1); |
814 | i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); | 824 | i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); |
825 | if (fe->ops.i2c_gate_ctrl) | ||
826 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
815 | return 0; | 827 | return 0; |
816 | } | 828 | } |
817 | 829 | ||
818 | /* ------------------------------------------------------------------ */ | 830 | /* ------------------------------------------------------------------ */ |
819 | 831 | ||
820 | static int philips_tiger_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) | 832 | static int tda8290_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) |
821 | { | 833 | { |
822 | int ret; | ||
823 | struct saa7134_dev *dev = fe->dvb->priv; | 834 | struct saa7134_dev *dev = fe->dvb->priv; |
824 | static u8 tda8290_close[] = { 0x21, 0xc0}; | 835 | static u8 tda8290_close[] = { 0x21, 0xc0}; |
825 | static u8 tda8290_open[] = { 0x21, 0x80}; | 836 | static u8 tda8290_open[] = { 0x21, 0x80}; |
826 | struct i2c_msg tda8290_msg = {.addr = 0x4b,.flags = 0, .len = 2}; | 837 | struct i2c_msg tda8290_msg = {.addr = 0x4b,.flags = 0, .len = 2}; |
827 | 838 | if (enable) { | |
828 | /* close tda8290 i2c bridge */ | 839 | tda8290_msg.buf = tda8290_close; |
829 | tda8290_msg.buf = tda8290_close; | 840 | } else { |
830 | ret = i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1); | 841 | tda8290_msg.buf = tda8290_open; |
831 | if (ret != 1) | 842 | } |
843 | if (i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1) != 1) | ||
832 | return -EIO; | 844 | return -EIO; |
833 | msleep(20); | 845 | msleep(20); |
846 | return 0; | ||
847 | } | ||
848 | |||
849 | /* ------------------------------------------------------------------ */ | ||
850 | |||
851 | static int philips_tiger_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) | ||
852 | { | ||
853 | int ret; | ||
854 | |||
834 | ret = philips_tda827xa_pll_set(0x61, fe, params); | 855 | ret = philips_tda827xa_pll_set(0x61, fe, params); |
835 | if (ret != 0) | 856 | if (ret != 0) |
836 | return ret; | 857 | return ret; |
837 | /* open tda8290 i2c bridge */ | 858 | return 0; |
838 | tda8290_msg.buf = tda8290_open; | ||
839 | i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1); | ||
840 | return ret; | ||
841 | } | 859 | } |
842 | 860 | ||
843 | static int philips_tiger_tuner_init(struct dvb_frontend *fe) | 861 | static int philips_tiger_tuner_init(struct dvb_frontend *fe) |
@@ -867,13 +885,80 @@ static struct tda1004x_config philips_tiger_config = { | |||
867 | .invert = 1, | 885 | .invert = 1, |
868 | .invert_oclk = 0, | 886 | .invert_oclk = 0, |
869 | .xtal_freq = TDA10046_XTAL_16M, | 887 | .xtal_freq = TDA10046_XTAL_16M, |
870 | .agc_config = TDA10046_AGC_TDA827X, | 888 | .agc_config = TDA10046_AGC_TDA827X_GP11, |
889 | .if_freq = TDA10046_FREQ_045, | ||
890 | .request_firmware = NULL, | ||
891 | }; | ||
892 | /* ------------------------------------------------------------------ */ | ||
893 | |||
894 | static int cinergy_ht_tuner_init(struct dvb_frontend *fe) | ||
895 | { | ||
896 | struct saa7134_dev *dev = fe->dvb->priv; | ||
897 | static u8 data[] = { 0x3c, 0x33, 0x62}; | ||
898 | struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)}; | ||
899 | |||
900 | if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) | ||
901 | return -EIO; | ||
902 | return 0; | ||
903 | } | ||
904 | |||
905 | static int cinergy_ht_tuner_sleep(struct dvb_frontend *fe) | ||
906 | { | ||
907 | struct saa7134_dev *dev = fe->dvb->priv; | ||
908 | static u8 data[] = { 0x3c, 0x33, 0x60}; | ||
909 | struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)}; | ||
910 | |||
911 | i2c_transfer(&dev->i2c_adap, &msg, 1); | ||
912 | philips_tda827xa_tuner_sleep( 0x61, fe); | ||
913 | return 0; | ||
914 | } | ||
915 | |||
916 | static struct tda1004x_config cinergy_ht_config = { | ||
917 | .demod_address = 0x08, | ||
918 | .invert = 1, | ||
919 | .invert_oclk = 0, | ||
920 | .xtal_freq = TDA10046_XTAL_16M, | ||
921 | .agc_config = TDA10046_AGC_TDA827X_GP01, | ||
871 | .if_freq = TDA10046_FREQ_045, | 922 | .if_freq = TDA10046_FREQ_045, |
872 | .request_firmware = NULL, | 923 | .request_firmware = NULL, |
873 | }; | 924 | }; |
874 | 925 | ||
875 | /* ------------------------------------------------------------------ */ | 926 | /* ------------------------------------------------------------------ */ |
876 | 927 | ||
928 | static struct tda1004x_config pinnacle_pctv_310i_config = { | ||
929 | .demod_address = 0x08, | ||
930 | .invert = 1, | ||
931 | .invert_oclk = 0, | ||
932 | .xtal_freq = TDA10046_XTAL_16M, | ||
933 | .agc_config = TDA10046_AGC_TDA827X_GP11, | ||
934 | .if_freq = TDA10046_FREQ_045, | ||
935 | .request_firmware = philips_tda1004x_request_firmware, | ||
936 | }; | ||
937 | |||
938 | /* ------------------------------------------------------------------ */ | ||
939 | |||
940 | static struct tda1004x_config hauppauge_hvr_1110_config = { | ||
941 | .demod_address = 0x08, | ||
942 | .invert = 1, | ||
943 | .invert_oclk = 0, | ||
944 | .xtal_freq = TDA10046_XTAL_16M, | ||
945 | .agc_config = TDA10046_AGC_TDA827X_GP11, | ||
946 | .if_freq = TDA10046_FREQ_045, | ||
947 | .request_firmware = philips_tda1004x_request_firmware, | ||
948 | }; | ||
949 | |||
950 | /* ------------------------------------------------------------------ */ | ||
951 | |||
952 | static struct tda1004x_config asus_p7131_dual_config = { | ||
953 | .demod_address = 0x08, | ||
954 | .invert = 1, | ||
955 | .invert_oclk = 0, | ||
956 | .xtal_freq = TDA10046_XTAL_16M, | ||
957 | .agc_config = TDA10046_AGC_TDA827X_GP11, | ||
958 | .if_freq = TDA10046_FREQ_045, | ||
959 | .request_firmware = philips_tda1004x_request_firmware, | ||
960 | }; | ||
961 | |||
877 | static int asus_p7131_dual_tuner_init(struct dvb_frontend *fe) | 962 | static int asus_p7131_dual_tuner_init(struct dvb_frontend *fe) |
878 | { | 963 | { |
879 | struct saa7134_dev *dev = fe->dvb->priv; | 964 | struct saa7134_dev *dev = fe->dvb->priv; |
@@ -921,7 +1006,7 @@ static struct tda1004x_config lifeview_trio_config = { | |||
921 | .invert = 1, | 1006 | .invert = 1, |
922 | .invert_oclk = 0, | 1007 | .invert_oclk = 0, |
923 | .xtal_freq = TDA10046_XTAL_16M, | 1008 | .xtal_freq = TDA10046_XTAL_16M, |
924 | .agc_config = TDA10046_AGC_TDA827X_GPL, | 1009 | .agc_config = TDA10046_AGC_TDA827X_GP00, |
925 | .if_freq = TDA10046_FREQ_045, | 1010 | .if_freq = TDA10046_FREQ_045, |
926 | .request_firmware = NULL, | 1011 | .request_firmware = NULL, |
927 | }; | 1012 | }; |
@@ -958,7 +1043,7 @@ static struct tda1004x_config ads_tech_duo_config = { | |||
958 | .invert = 1, | 1043 | .invert = 1, |
959 | .invert_oclk = 0, | 1044 | .invert_oclk = 0, |
960 | .xtal_freq = TDA10046_XTAL_16M, | 1045 | .xtal_freq = TDA10046_XTAL_16M, |
961 | .agc_config = TDA10046_AGC_TDA827X_GPL, | 1046 | .agc_config = TDA10046_AGC_TDA827X_GP00, |
962 | .if_freq = TDA10046_FREQ_045, | 1047 | .if_freq = TDA10046_FREQ_045, |
963 | .request_firmware = NULL, | 1048 | .request_firmware = NULL, |
964 | }; | 1049 | }; |
@@ -983,7 +1068,7 @@ static struct tda1004x_config tevion_dvbt220rf_config = { | |||
983 | .invert = 1, | 1068 | .invert = 1, |
984 | .invert_oclk = 0, | 1069 | .invert_oclk = 0, |
985 | .xtal_freq = TDA10046_XTAL_16M, | 1070 | .xtal_freq = TDA10046_XTAL_16M, |
986 | .agc_config = TDA10046_AGC_TDA827X, | 1071 | .agc_config = TDA10046_AGC_TDA827X_GP11, |
987 | .if_freq = TDA10046_FREQ_045, | 1072 | .if_freq = TDA10046_FREQ_045, |
988 | .request_firmware = NULL, | 1073 | .request_firmware = NULL, |
989 | }; | 1074 | }; |
@@ -1028,7 +1113,7 @@ static struct tda1004x_config md8800_dvbt_config = { | |||
1028 | .invert = 1, | 1113 | .invert = 1, |
1029 | .invert_oclk = 0, | 1114 | .invert_oclk = 0, |
1030 | .xtal_freq = TDA10046_XTAL_16M, | 1115 | .xtal_freq = TDA10046_XTAL_16M, |
1031 | .agc_config = TDA10046_AGC_TDA827X, | 1116 | .agc_config = TDA10046_AGC_TDA827X_GP11, |
1032 | .if_freq = TDA10046_FREQ_045, | 1117 | .if_freq = TDA10046_FREQ_045, |
1033 | .request_firmware = NULL, | 1118 | .request_firmware = NULL, |
1034 | }; | 1119 | }; |
@@ -1168,6 +1253,29 @@ static int dvb_init(struct saa7134_dev *dev) | |||
1168 | &philips_tiger_config, | 1253 | &philips_tiger_config, |
1169 | &dev->i2c_adap); | 1254 | &dev->i2c_adap); |
1170 | if (dev->dvb.frontend) { | 1255 | if (dev->dvb.frontend) { |
1256 | dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl; | ||
1257 | dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init; | ||
1258 | dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep; | ||
1259 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params; | ||
1260 | } | ||
1261 | break; | ||
1262 | case SAA7134_BOARD_PINNACLE_PCTV_310i: | ||
1263 | dev->dvb.frontend = dvb_attach(tda10046_attach, | ||
1264 | &pinnacle_pctv_310i_config, | ||
1265 | &dev->i2c_adap); | ||
1266 | if (dev->dvb.frontend) { | ||
1267 | dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl; | ||
1268 | dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init; | ||
1269 | dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep; | ||
1270 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params; | ||
1271 | } | ||
1272 | break; | ||
1273 | case SAA7134_BOARD_HAUPPAUGE_HVR1110: | ||
1274 | dev->dvb.frontend = dvb_attach(tda10046_attach, | ||
1275 | &hauppauge_hvr_1110_config, | ||
1276 | &dev->i2c_adap); | ||
1277 | if (dev->dvb.frontend) { | ||
1278 | dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl; | ||
1171 | dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init; | 1279 | dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init; |
1172 | dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep; | 1280 | dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep; |
1173 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params; | 1281 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params; |
@@ -1175,9 +1283,10 @@ static int dvb_init(struct saa7134_dev *dev) | |||
1175 | break; | 1283 | break; |
1176 | case SAA7134_BOARD_ASUSTeK_P7131_DUAL: | 1284 | case SAA7134_BOARD_ASUSTeK_P7131_DUAL: |
1177 | dev->dvb.frontend = dvb_attach(tda10046_attach, | 1285 | dev->dvb.frontend = dvb_attach(tda10046_attach, |
1178 | &philips_tiger_config, | 1286 | &asus_p7131_dual_config, |
1179 | &dev->i2c_adap); | 1287 | &dev->i2c_adap); |
1180 | if (dev->dvb.frontend) { | 1288 | if (dev->dvb.frontend) { |
1289 | dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl; | ||
1181 | dev->dvb.frontend->ops.tuner_ops.init = asus_p7131_dual_tuner_init; | 1290 | dev->dvb.frontend->ops.tuner_ops.init = asus_p7131_dual_tuner_init; |
1182 | dev->dvb.frontend->ops.tuner_ops.sleep = asus_p7131_dual_tuner_sleep; | 1291 | dev->dvb.frontend->ops.tuner_ops.sleep = asus_p7131_dual_tuner_sleep; |
1183 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params; | 1292 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params; |
@@ -1194,12 +1303,27 @@ static int dvb_init(struct saa7134_dev *dev) | |||
1194 | } | 1303 | } |
1195 | break; | 1304 | break; |
1196 | case SAA7134_BOARD_FLYDVB_TRIO: | 1305 | case SAA7134_BOARD_FLYDVB_TRIO: |
1197 | dev->dvb.frontend = dvb_attach(tda10046_attach, | 1306 | if(! use_frontent) { //terrestrial |
1198 | &lifeview_trio_config, | 1307 | dev->dvb.frontend = dvb_attach(tda10046_attach, |
1199 | &dev->i2c_adap); | 1308 | &lifeview_trio_config, |
1200 | if (dev->dvb.frontend) { | 1309 | &dev->i2c_adap); |
1201 | dev->dvb.frontend->ops.tuner_ops.sleep = lifeview_trio_tuner_sleep; | 1310 | if (dev->dvb.frontend) { |
1202 | dev->dvb.frontend->ops.tuner_ops.set_params = lifeview_trio_tuner_set_params; | 1311 | dev->dvb.frontend->ops.tuner_ops.sleep = lifeview_trio_tuner_sleep; |
1312 | dev->dvb.frontend->ops.tuner_ops.set_params = | ||
1313 | lifeview_trio_tuner_set_params; | ||
1314 | } | ||
1315 | } else { //satellite | ||
1316 | dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap); | ||
1317 | if (dev->dvb.frontend) { | ||
1318 | if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x63, | ||
1319 | &dev->i2c_adap, 0) == NULL) { | ||
1320 | printk("%s: Lifeview Trio, No tda826x found!\n", __FUNCTION__); | ||
1321 | } | ||
1322 | if (dvb_attach(isl6421_attach, dev->dvb.frontend, &dev->i2c_adap, | ||
1323 | 0x08, 0, 0) == NULL) { | ||
1324 | printk("%s: Lifeview Trio, No ISL6421 found!\n", __FUNCTION__); | ||
1325 | } | ||
1326 | } | ||
1203 | } | 1327 | } |
1204 | break; | 1328 | break; |
1205 | case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331: | 1329 | case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331: |
@@ -1281,7 +1405,27 @@ static int dvb_init(struct saa7134_dev *dev) | |||
1281 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_fmd1216_tuner_set_params; | 1405 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_fmd1216_tuner_set_params; |
1282 | } | 1406 | } |
1283 | break; | 1407 | break; |
1408 | case SAA7134_BOARD_VIDEOMATE_DVBT_200A: | ||
1409 | dev->dvb.frontend = dvb_attach(tda10046_attach, | ||
1410 | &philips_europa_config, | ||
1411 | &dev->i2c_adap); | ||
1412 | if (dev->dvb.frontend) { | ||
1413 | dev->dvb.frontend->ops.tuner_ops.init = philips_td1316_tuner_init; | ||
1414 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params; | ||
1415 | } | ||
1416 | break; | ||
1417 | case SAA7134_BOARD_CINERGY_HT_PCMCIA: | ||
1418 | dev->dvb.frontend = dvb_attach(tda10046_attach, | ||
1419 | &cinergy_ht_config, | ||
1420 | &dev->i2c_adap); | ||
1421 | if (dev->dvb.frontend) { | ||
1422 | dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl; | ||
1423 | dev->dvb.frontend->ops.tuner_ops.init = cinergy_ht_tuner_init; | ||
1424 | dev->dvb.frontend->ops.tuner_ops.sleep = cinergy_ht_tuner_sleep; | ||
1425 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params; | ||
1284 | 1426 | ||
1427 | } | ||
1428 | break; | ||
1285 | default: | 1429 | default: |
1286 | printk("%s: Huh? unknown DVB card?\n",dev->name); | 1430 | printk("%s: Huh? unknown DVB card?\n",dev->name); |
1287 | break; | 1431 | break; |
diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c index 6162550c4136..6f9fe86fed98 100644 --- a/drivers/media/video/saa7134/saa7134-i2c.c +++ b/drivers/media/video/saa7134/saa7134-i2c.c | |||
@@ -341,6 +341,7 @@ static int attach_inform(struct i2c_client *client) | |||
341 | switch (client->addr) { | 341 | switch (client->addr) { |
342 | case 0x7a: | 342 | case 0x7a: |
343 | case 0x47: | 343 | case 0x47: |
344 | case 0x71: | ||
344 | { | 345 | { |
345 | struct IR_i2c *ir = i2c_get_clientdata(client); | 346 | struct IR_i2c *ir = i2c_get_clientdata(client); |
346 | d1printk("%s i2c IR detected (%s).\n", | 347 | d1printk("%s i2c IR detected (%s).\n", |
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index dee83552e681..60b38defd9bc 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c | |||
@@ -112,6 +112,27 @@ static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | |||
112 | return 1; | 112 | return 1; |
113 | } | 113 | } |
114 | 114 | ||
115 | static int get_key_hvr1110(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | ||
116 | { | ||
117 | unsigned char buf[5], cod4, code3, code4; | ||
118 | |||
119 | /* poll IR chip */ | ||
120 | if (5 != i2c_master_recv(&ir->c,buf,5)) | ||
121 | return -EIO; | ||
122 | |||
123 | cod4 = buf[4]; | ||
124 | code4 = (cod4 >> 2); | ||
125 | code3 = buf[3]; | ||
126 | if (code3 == 0) | ||
127 | /* no key pressed */ | ||
128 | return 0; | ||
129 | |||
130 | /* return key */ | ||
131 | *ir_key = code4; | ||
132 | *ir_raw = code4; | ||
133 | return 1; | ||
134 | } | ||
135 | |||
115 | void saa7134_input_irq(struct saa7134_dev *dev) | 136 | void saa7134_input_irq(struct saa7134_dev *dev) |
116 | { | 137 | { |
117 | struct saa7134_ir *ir = dev->remote; | 138 | struct saa7134_ir *ir = dev->remote; |
@@ -131,6 +152,23 @@ static void saa7134_input_timer(unsigned long data) | |||
131 | mod_timer(&ir->timer, timeout); | 152 | mod_timer(&ir->timer, timeout); |
132 | } | 153 | } |
133 | 154 | ||
155 | static void saa7134_ir_start(struct saa7134_dev *dev, struct saa7134_ir *ir) | ||
156 | { | ||
157 | if (ir->polling) { | ||
158 | init_timer(&ir->timer); | ||
159 | ir->timer.function = saa7134_input_timer; | ||
160 | ir->timer.data = (unsigned long)dev; | ||
161 | ir->timer.expires = jiffies + HZ; | ||
162 | add_timer(&ir->timer); | ||
163 | } | ||
164 | } | ||
165 | |||
166 | static void saa7134_ir_stop(struct saa7134_dev *dev) | ||
167 | { | ||
168 | if (dev->remote->polling) | ||
169 | del_timer_sync(&dev->remote->timer); | ||
170 | } | ||
171 | |||
134 | int saa7134_input_init1(struct saa7134_dev *dev) | 172 | int saa7134_input_init1(struct saa7134_dev *dev) |
135 | { | 173 | { |
136 | struct saa7134_ir *ir; | 174 | struct saa7134_ir *ir; |
@@ -141,6 +179,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
141 | u32 mask_keyup = 0; | 179 | u32 mask_keyup = 0; |
142 | int polling = 0; | 180 | int polling = 0; |
143 | int ir_type = IR_TYPE_OTHER; | 181 | int ir_type = IR_TYPE_OTHER; |
182 | int err; | ||
144 | 183 | ||
145 | if (dev->has_remote != SAA7134_REMOTE_GPIO) | 184 | if (dev->has_remote != SAA7134_REMOTE_GPIO) |
146 | return -ENODEV; | 185 | return -ENODEV; |
@@ -184,6 +223,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
184 | case SAA7134_BOARD_AVERMEDIA_307: | 223 | case SAA7134_BOARD_AVERMEDIA_307: |
185 | case SAA7134_BOARD_AVERMEDIA_STUDIO_305: | 224 | case SAA7134_BOARD_AVERMEDIA_STUDIO_305: |
186 | case SAA7134_BOARD_AVERMEDIA_STUDIO_307: | 225 | case SAA7134_BOARD_AVERMEDIA_STUDIO_307: |
226 | case SAA7134_BOARD_AVERMEDIA_STUDIO_507: | ||
187 | case SAA7134_BOARD_AVERMEDIA_GO_007_FM: | 227 | case SAA7134_BOARD_AVERMEDIA_GO_007_FM: |
188 | ir_codes = ir_codes_avermedia; | 228 | ir_codes = ir_codes_avermedia; |
189 | mask_keycode = 0x0007C8; | 229 | mask_keycode = 0x0007C8; |
@@ -266,9 +306,8 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
266 | ir = kzalloc(sizeof(*ir), GFP_KERNEL); | 306 | ir = kzalloc(sizeof(*ir), GFP_KERNEL); |
267 | input_dev = input_allocate_device(); | 307 | input_dev = input_allocate_device(); |
268 | if (!ir || !input_dev) { | 308 | if (!ir || !input_dev) { |
269 | kfree(ir); | 309 | err = -ENOMEM; |
270 | input_free_device(input_dev); | 310 | goto err_out_free; |
271 | return -ENOMEM; | ||
272 | } | 311 | } |
273 | 312 | ||
274 | ir->dev = input_dev; | 313 | ir->dev = input_dev; |
@@ -299,18 +338,22 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
299 | } | 338 | } |
300 | input_dev->cdev.dev = &dev->pci->dev; | 339 | input_dev->cdev.dev = &dev->pci->dev; |
301 | 340 | ||
302 | /* all done */ | ||
303 | dev->remote = ir; | 341 | dev->remote = ir; |
304 | if (ir->polling) { | 342 | saa7134_ir_start(dev, ir); |
305 | init_timer(&ir->timer); | 343 | |
306 | ir->timer.function = saa7134_input_timer; | 344 | err = input_register_device(ir->dev); |
307 | ir->timer.data = (unsigned long)dev; | 345 | if (err) |
308 | ir->timer.expires = jiffies + HZ; | 346 | goto err_out_stop; |
309 | add_timer(&ir->timer); | ||
310 | } | ||
311 | 347 | ||
312 | input_register_device(ir->dev); | ||
313 | return 0; | 348 | return 0; |
349 | |||
350 | err_out_stop: | ||
351 | saa7134_ir_stop(dev); | ||
352 | dev->remote = NULL; | ||
353 | err_out_free: | ||
354 | input_free_device(input_dev); | ||
355 | kfree(ir); | ||
356 | return err; | ||
314 | } | 357 | } |
315 | 358 | ||
316 | void saa7134_input_fini(struct saa7134_dev *dev) | 359 | void saa7134_input_fini(struct saa7134_dev *dev) |
@@ -318,8 +361,7 @@ void saa7134_input_fini(struct saa7134_dev *dev) | |||
318 | if (NULL == dev->remote) | 361 | if (NULL == dev->remote) |
319 | return; | 362 | return; |
320 | 363 | ||
321 | if (dev->remote->polling) | 364 | saa7134_ir_stop(dev); |
322 | del_timer_sync(&dev->remote->timer); | ||
323 | input_unregister_device(dev->remote->dev); | 365 | input_unregister_device(dev->remote->dev); |
324 | kfree(dev->remote); | 366 | kfree(dev->remote); |
325 | dev->remote = NULL; | 367 | dev->remote = NULL; |
@@ -335,6 +377,7 @@ void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir) | |||
335 | 377 | ||
336 | switch (dev->board) { | 378 | switch (dev->board) { |
337 | case SAA7134_BOARD_PINNACLE_PCTV_110i: | 379 | case SAA7134_BOARD_PINNACLE_PCTV_110i: |
380 | case SAA7134_BOARD_PINNACLE_PCTV_310i: | ||
338 | snprintf(ir->c.name, sizeof(ir->c.name), "Pinnacle PCTV"); | 381 | snprintf(ir->c.name, sizeof(ir->c.name), "Pinnacle PCTV"); |
339 | if (pinnacle_remote == 0) { | 382 | if (pinnacle_remote == 0) { |
340 | ir->get_key = get_key_pinnacle_color; | 383 | ir->get_key = get_key_pinnacle_color; |
@@ -349,6 +392,11 @@ void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir) | |||
349 | ir->get_key = get_key_purpletv; | 392 | ir->get_key = get_key_purpletv; |
350 | ir->ir_codes = ir_codes_purpletv; | 393 | ir->ir_codes = ir_codes_purpletv; |
351 | break; | 394 | break; |
395 | case SAA7134_BOARD_HAUPPAUGE_HVR1110: | ||
396 | snprintf(ir->c.name, sizeof(ir->c.name), "HVR 1110"); | ||
397 | ir->get_key = get_key_hvr1110; | ||
398 | ir->ir_codes = ir_codes_hauppauge_new; | ||
399 | break; | ||
352 | default: | 400 | default: |
353 | dprintk("Shouldn't get here: Unknown board %x for I2C IR?\n",dev->board); | 401 | dprintk("Shouldn't get here: Unknown board %x for I2C IR?\n",dev->board); |
354 | break; | 402 | break; |
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 7cf96b430250..e88ad7b40c47 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h | |||
@@ -227,6 +227,11 @@ struct saa7134_format { | |||
227 | #define SAA7134_BOARD_PROTEUS_2309 98 | 227 | #define SAA7134_BOARD_PROTEUS_2309 98 |
228 | #define SAA7134_BOARD_AVERMEDIA_A16AR 99 | 228 | #define SAA7134_BOARD_AVERMEDIA_A16AR 99 |
229 | #define SAA7134_BOARD_ASUS_EUROPA2_HYBRID 100 | 229 | #define SAA7134_BOARD_ASUS_EUROPA2_HYBRID 100 |
230 | #define SAA7134_BOARD_PINNACLE_PCTV_310i 101 | ||
231 | #define SAA7134_BOARD_AVERMEDIA_STUDIO_507 102 | ||
232 | #define SAA7134_BOARD_VIDEOMATE_DVBT_200A 103 | ||
233 | #define SAA7134_BOARD_HAUPPAUGE_HVR1110 104 | ||
234 | #define SAA7134_BOARD_CINERGY_HT_PCMCIA 105 | ||
230 | 235 | ||
231 | #define SAA7134_MAXBOARDS 8 | 236 | #define SAA7134_MAXBOARDS 8 |
232 | #define SAA7134_INPUT_MAX 8 | 237 | #define SAA7134_INPUT_MAX 8 |
@@ -446,6 +451,9 @@ struct saa7134_dev { | |||
446 | struct v4l2_prio_state prio; | 451 | struct v4l2_prio_state prio; |
447 | #endif | 452 | #endif |
448 | 453 | ||
454 | /* insmod option/autodetected */ | ||
455 | int autodetected; | ||
456 | |||
449 | /* various device info */ | 457 | /* various device info */ |
450 | unsigned int resources; | 458 | unsigned int resources; |
451 | struct video_device *video_dev; | 459 | struct video_device *video_dev; |
diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c index 6d1ef1e2e8ef..a1ec3aca3f91 100644 --- a/drivers/media/video/stv680.c +++ b/drivers/media/video/stv680.c | |||
@@ -687,7 +687,7 @@ static int stv680_start_stream (struct usb_stv *stv680) | |||
687 | stv680->sbuf[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL); | 687 | stv680->sbuf[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL); |
688 | if (stv680->sbuf[i].data == NULL) { | 688 | if (stv680->sbuf[i].data == NULL) { |
689 | PDEBUG (0, "STV(e): Could not kmalloc raw data buffer %i", i); | 689 | PDEBUG (0, "STV(e): Could not kmalloc raw data buffer %i", i); |
690 | return -1; | 690 | goto nomem_err; |
691 | } | 691 | } |
692 | } | 692 | } |
693 | 693 | ||
@@ -698,7 +698,7 @@ static int stv680_start_stream (struct usb_stv *stv680) | |||
698 | stv680->scratch[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL); | 698 | stv680->scratch[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL); |
699 | if (stv680->scratch[i].data == NULL) { | 699 | if (stv680->scratch[i].data == NULL) { |
700 | PDEBUG (0, "STV(e): Could not kmalloc raw scratch buffer %i", i); | 700 | PDEBUG (0, "STV(e): Could not kmalloc raw scratch buffer %i", i); |
701 | return -1; | 701 | goto nomem_err; |
702 | } | 702 | } |
703 | stv680->scratch[i].state = BUFFER_UNUSED; | 703 | stv680->scratch[i].state = BUFFER_UNUSED; |
704 | } | 704 | } |
@@ -706,7 +706,7 @@ static int stv680_start_stream (struct usb_stv *stv680) | |||
706 | for (i = 0; i < STV680_NUMSBUF; i++) { | 706 | for (i = 0; i < STV680_NUMSBUF; i++) { |
707 | urb = usb_alloc_urb (0, GFP_KERNEL); | 707 | urb = usb_alloc_urb (0, GFP_KERNEL); |
708 | if (!urb) | 708 | if (!urb) |
709 | return -ENOMEM; | 709 | goto nomem_err; |
710 | 710 | ||
711 | /* sbuf is urb->transfer_buffer, later gets memcpyed to scratch */ | 711 | /* sbuf is urb->transfer_buffer, later gets memcpyed to scratch */ |
712 | usb_fill_bulk_urb (urb, stv680->udev, | 712 | usb_fill_bulk_urb (urb, stv680->udev, |
@@ -721,6 +721,21 @@ static int stv680_start_stream (struct usb_stv *stv680) | |||
721 | 721 | ||
722 | stv680->framecount = 0; | 722 | stv680->framecount = 0; |
723 | return 0; | 723 | return 0; |
724 | |||
725 | nomem_err: | ||
726 | for (i = 0; i < STV680_NUMSCRATCH; i++) { | ||
727 | kfree(stv680->scratch[i].data); | ||
728 | stv680->scratch[i].data = NULL; | ||
729 | } | ||
730 | for (i = 0; i < STV680_NUMSBUF; i++) { | ||
731 | usb_kill_urb(stv680->urb[i]); | ||
732 | usb_free_urb(stv680->urb[i]); | ||
733 | stv680->urb[i] = NULL; | ||
734 | kfree(stv680->sbuf[i].data); | ||
735 | stv680->sbuf[i].data = NULL; | ||
736 | } | ||
737 | return -ENOMEM; | ||
738 | |||
724 | } | 739 | } |
725 | 740 | ||
726 | static int stv680_stop_stream (struct usb_stv *stv680) | 741 | static int stv680_stop_stream (struct usb_stv *stv680) |
diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 87ffb0e84a7a..fde576f1101c 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c | |||
@@ -482,6 +482,12 @@ static int tda9887_set_config(struct tuner *t, char *buf) | |||
482 | buf[1] &= ~cQSS; | 482 | buf[1] &= ~cQSS; |
483 | if (t->tda9887_config & TDA9887_GATING_18) | 483 | if (t->tda9887_config & TDA9887_GATING_18) |
484 | buf[3] &= ~cGating_36; | 484 | buf[3] &= ~cGating_36; |
485 | |||
486 | if (t->tda9887_config & TDA9887_GAIN_NORMAL) { | ||
487 | radio_stereo.e &= ~cTunerGainLow; | ||
488 | radio_mono.e &= ~cTunerGainLow; | ||
489 | } | ||
490 | |||
485 | return 0; | 491 | return 0; |
486 | } | 492 | } |
487 | 493 | ||
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 40590bae5ff7..705daaa2a4ff 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c | |||
@@ -443,6 +443,10 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) | |||
443 | printk("%02x ",buffer[i]); | 443 | printk("%02x ",buffer[i]); |
444 | printk("\n"); | 444 | printk("\n"); |
445 | } | 445 | } |
446 | /* HACK: This test were added to avoid tuner to probe tda9840 and tea6415c on the MXB card */ | ||
447 | if (adap->id == I2C_HW_SAA7146 && addr < 0x4a) | ||
448 | return -ENODEV; | ||
449 | |||
446 | /* autodetection code based on the i2c addr */ | 450 | /* autodetection code based on the i2c addr */ |
447 | if (!no_autodetect) { | 451 | if (!no_autodetect) { |
448 | switch (addr) { | 452 | switch (addr) { |
diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 63db4e97ae6c..1b9b0742f753 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c | |||
@@ -108,6 +108,7 @@ static int tuner_stereo(struct i2c_client *c) | |||
108 | case TUNER_PHILIPS_FM1216ME_MK3: | 108 | case TUNER_PHILIPS_FM1216ME_MK3: |
109 | case TUNER_PHILIPS_FM1236_MK3: | 109 | case TUNER_PHILIPS_FM1236_MK3: |
110 | case TUNER_PHILIPS_FM1256_IH3: | 110 | case TUNER_PHILIPS_FM1256_IH3: |
111 | case TUNER_LG_NTSC_TAPE: | ||
111 | stereo = ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3); | 112 | stereo = ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3); |
112 | break; | 113 | break; |
113 | default: | 114 | default: |
@@ -421,6 +422,7 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq) | |||
421 | case TUNER_PHILIPS_FM1216ME_MK3: | 422 | case TUNER_PHILIPS_FM1216ME_MK3: |
422 | case TUNER_PHILIPS_FM1236_MK3: | 423 | case TUNER_PHILIPS_FM1236_MK3: |
423 | case TUNER_PHILIPS_FMD1216ME_MK3: | 424 | case TUNER_PHILIPS_FMD1216ME_MK3: |
425 | case TUNER_LG_NTSC_TAPE: | ||
424 | buffer[3] = 0x19; | 426 | buffer[3] = 0x19; |
425 | break; | 427 | break; |
426 | case TUNER_TNF_5335MF: | 428 | case TUNER_TNF_5335MF: |
@@ -465,6 +467,8 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq) | |||
465 | config |= TDA9887_INTERCARRIER; | 467 | config |= TDA9887_INTERCARRIER; |
466 | /* if (params->port1_set_for_fm_mono) | 468 | /* if (params->port1_set_for_fm_mono) |
467 | config &= ~TDA9887_PORT1_ACTIVE;*/ | 469 | config &= ~TDA9887_PORT1_ACTIVE;*/ |
470 | if (params->fm_gain_normal) | ||
471 | config |= TDA9887_GAIN_NORMAL; | ||
468 | i2c_clients_command(c->adapter, TDA9887_SET_CONFIG, &config); | 472 | i2c_clients_command(c->adapter, TDA9887_SET_CONFIG, &config); |
469 | } | 473 | } |
470 | if (4 != (rc = i2c_master_send(c,buffer,4))) | 474 | if (4 != (rc = i2c_master_send(c,buffer,4))) |
diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index 781682373b61..74c3e6f96f1a 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c | |||
@@ -651,6 +651,7 @@ static struct tuner_params tuner_microtune_4049_fm5_params[] = { | |||
651 | .has_tda9887 = 1, | 651 | .has_tda9887 = 1, |
652 | .port1_invert_for_secam_lc = 1, | 652 | .port1_invert_for_secam_lc = 1, |
653 | .default_pll_gating_18 = 1, | 653 | .default_pll_gating_18 = 1, |
654 | .fm_gain_normal=1, | ||
654 | }, | 655 | }, |
655 | }; | 656 | }; |
656 | 657 | ||
@@ -672,16 +673,6 @@ static struct tuner_params tuner_panasonic_vp27_params[] = { | |||
672 | }, | 673 | }, |
673 | }; | 674 | }; |
674 | 675 | ||
675 | /* ------------ TUNER_LG_NTSC_TAPE - LGINNOTEK NTSC ------------ */ | ||
676 | |||
677 | static struct tuner_params tuner_lg_ntsc_tape_params[] = { | ||
678 | { | ||
679 | .type = TUNER_PARAM_TYPE_NTSC, | ||
680 | .ranges = tuner_fm1236_mk3_ntsc_ranges, | ||
681 | .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges), | ||
682 | }, | ||
683 | }; | ||
684 | |||
685 | /* ------------ TUNER_TNF_8831BGFF - Philips PAL ------------ */ | 676 | /* ------------ TUNER_TNF_8831BGFF - Philips PAL ------------ */ |
686 | 677 | ||
687 | static struct tuner_range tuner_tnf_8831bgff_pal_ranges[] = { | 678 | static struct tuner_range tuner_tnf_8831bgff_pal_ranges[] = { |
@@ -1331,8 +1322,8 @@ struct tunertype tuners[] = { | |||
1331 | }, | 1322 | }, |
1332 | [TUNER_LG_NTSC_TAPE] = { /* LGINNOTEK NTSC */ | 1323 | [TUNER_LG_NTSC_TAPE] = { /* LGINNOTEK NTSC */ |
1333 | .name = "LG NTSC (TAPE series)", | 1324 | .name = "LG NTSC (TAPE series)", |
1334 | .params = tuner_lg_ntsc_tape_params, | 1325 | .params = tuner_fm1236_mk3_params, |
1335 | .count = ARRAY_SIZE(tuner_lg_ntsc_tape_params), | 1326 | .count = ARRAY_SIZE(tuner_fm1236_mk3_params), |
1336 | }, | 1327 | }, |
1337 | [TUNER_TNF_8831BGFF] = { /* Philips PAL */ | 1328 | [TUNER_TNF_8831BGFF] = { /* Philips PAL */ |
1338 | .name = "Tenna TNF 8831 BGFF)", | 1329 | .name = "Tenna TNF 8831 BGFF)", |
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index 6b9ef731b83a..2624e3f7dd29 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c | |||
@@ -430,7 +430,7 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, | |||
430 | tvee->has_radio = eeprom_data[i+len-1]; | 430 | tvee->has_radio = eeprom_data[i+len-1]; |
431 | /* old style tag, don't know how to detect | 431 | /* old style tag, don't know how to detect |
432 | IR presence, mark as unknown. */ | 432 | IR presence, mark as unknown. */ |
433 | tvee->has_ir = 2; | 433 | tvee->has_ir = -1; |
434 | tvee->model = | 434 | tvee->model = |
435 | eeprom_data[i+8] + | 435 | eeprom_data[i+8] + |
436 | (eeprom_data[i+9] << 8); | 436 | (eeprom_data[i+9] << 8); |
@@ -653,13 +653,14 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, | |||
653 | STRM(decoderIC, tvee->decoder_processor), | 653 | STRM(decoderIC, tvee->decoder_processor), |
654 | tvee->decoder_processor); | 654 | tvee->decoder_processor); |
655 | } | 655 | } |
656 | if (tvee->has_ir == 2) | 656 | if (tvee->has_ir == -1) |
657 | tveeprom_info("has %sradio\n", | 657 | tveeprom_info("has %sradio\n", |
658 | tvee->has_radio ? "" : "no "); | 658 | tvee->has_radio ? "" : "no "); |
659 | else | 659 | else |
660 | tveeprom_info("has %sradio, has %sIR remote\n", | 660 | tveeprom_info("has %sradio, has %sIR receiver, has %sIR transmitter\n", |
661 | tvee->has_radio ? "" : "no ", | 661 | tvee->has_radio ? "" : "no ", |
662 | tvee->has_ir ? "" : "no "); | 662 | (tvee->has_ir & 1) ? "" : "no ", |
663 | (tvee->has_ir & 2) ? "" : "no "); | ||
663 | } | 664 | } |
664 | EXPORT_SYMBOL(tveeprom_hauppauge_analog); | 665 | EXPORT_SYMBOL(tveeprom_hauppauge_analog); |
665 | 666 | ||
diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c index bbf2beeeb449..ec0ff2247f06 100644 --- a/drivers/media/video/usbvideo/quickcam_messenger.c +++ b/drivers/media/video/usbvideo/quickcam_messenger.c | |||
@@ -86,6 +86,7 @@ MODULE_DEVICE_TABLE(usb, qcm_table); | |||
86 | static void qcm_register_input(struct qcm *cam, struct usb_device *dev) | 86 | static void qcm_register_input(struct qcm *cam, struct usb_device *dev) |
87 | { | 87 | { |
88 | struct input_dev *input_dev; | 88 | struct input_dev *input_dev; |
89 | int error; | ||
89 | 90 | ||
90 | usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname)); | 91 | usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname)); |
91 | strncat(cam->input_physname, "/input0", sizeof(cam->input_physname)); | 92 | strncat(cam->input_physname, "/input0", sizeof(cam->input_physname)); |
@@ -106,7 +107,13 @@ static void qcm_register_input(struct qcm *cam, struct usb_device *dev) | |||
106 | 107 | ||
107 | input_dev->private = cam; | 108 | input_dev->private = cam; |
108 | 109 | ||
109 | input_register_device(cam->input); | 110 | error = input_register_device(cam->input); |
111 | if (error) { | ||
112 | warn("Failed to register camera's input device, err: %d\n", | ||
113 | error); | ||
114 | input_free_device(cam->input); | ||
115 | cam->input = NULL; | ||
116 | } | ||
110 | } | 117 | } |
111 | 118 | ||
112 | static void qcm_unregister_input(struct qcm *cam) | 119 | static void qcm_unregister_input(struct qcm *cam) |
diff --git a/drivers/media/video/usbvision/Kconfig b/drivers/media/video/usbvision/Kconfig new file mode 100644 index 000000000000..fc24ef05b3f3 --- /dev/null +++ b/drivers/media/video/usbvision/Kconfig | |||
@@ -0,0 +1,12 @@ | |||
1 | config VIDEO_USBVISION | ||
2 | tristate "USB video devices based on Nogatech NT1003/1004/1005" | ||
3 | depends on I2C && VIDEO_V4L2 | ||
4 | select VIDEO_TUNER | ||
5 | select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO | ||
6 | ---help--- | ||
7 | There are more than 50 different USB video devices based on | ||
8 | NT1003/1004/1005 USB Bridges. This driver enables using those | ||
9 | devices. | ||
10 | |||
11 | To compile this driver as a module, choose M here: the | ||
12 | module will be called usbvision. | ||
diff --git a/drivers/media/video/usbvision/Makefile b/drivers/media/video/usbvision/Makefile new file mode 100644 index 000000000000..9ac92a80c645 --- /dev/null +++ b/drivers/media/video/usbvision/Makefile | |||
@@ -0,0 +1,5 @@ | |||
1 | usbvision-objs := usbvision-core.o usbvision-video.o usbvision-i2c.o usbvision-cards.o | ||
2 | |||
3 | obj-$(CONFIG_VIDEO_USBVISION) += usbvision.o | ||
4 | |||
5 | EXTRA_CFLAGS += -Idrivers/media/video | ||
diff --git a/drivers/media/video/usbvision/usbvision-cards.c b/drivers/media/video/usbvision/usbvision-cards.c new file mode 100644 index 000000000000..134eb9865df6 --- /dev/null +++ b/drivers/media/video/usbvision/usbvision-cards.c | |||
@@ -0,0 +1,157 @@ | |||
1 | /* | ||
2 | * USBVISION.H | ||
3 | * usbvision header file | ||
4 | * | ||
5 | * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de> | ||
6 | * | ||
7 | * This module is part of usbvision driver project. | ||
8 | * Updates to driver completed by Dwaine P. Garden | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | */ | ||
24 | |||
25 | |||
26 | #include <linux/list.h> | ||
27 | #include <linux/i2c.h> | ||
28 | #include <media/v4l2-dev.h> | ||
29 | #include <media/tuner.h> | ||
30 | #include "usbvision.h" | ||
31 | |||
32 | /* Supported Devices: A table for usbvision.c*/ | ||
33 | struct usbvision_device_data_st usbvision_device_data[] = { | ||
34 | {0xFFF0, 0xFFF0, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Custom Dummy USBVision Device"}, | ||
35 | {0x0A6F, 0x0400, -1, CODEC_SAA7113, 4, V4L2_STD_NTSC, 1, 0, 1, 0, 0, -1, -1, -1, -1, -1, "Xanboo"}, | ||
36 | {0x050D, 0x0208, -1, CODEC_SAA7113, 2, V4L2_STD_PAL, 1, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Belkin USBView II"}, | ||
37 | {0x0571, 0x0002, 0, CODEC_SAA7111, 2, V4L2_STD_PAL, 0, 0, 1, 0, 0, -1, -1, -1, -1, 7, "echoFX InterView Lite"}, | ||
38 | {0x0573, 0x0003, -1, CODEC_SAA7111, 2, V4L2_STD_NTSC, 1, 0, 1, 0, 0, -1, -1, -1, -1, -1, "USBGear USBG-V1 resp. HAMA USB"}, | ||
39 | {0x0573, 0x0400, -1, CODEC_SAA7113, 4, V4L2_STD_NTSC, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "D-Link V100"}, | ||
40 | {0x0573, 0x2000, -1, CODEC_SAA7111, 2, V4L2_STD_NTSC, 1, 0, 1, 0, 0, -1, -1, -1, -1, -1, "X10 USB Camera"}, | ||
41 | {0x0573, 0x2d00, -1, CODEC_SAA7111, 2, V4L2_STD_PAL, 1, 0, 1, 0, 0, -1, -1, -1, 3, 7, "Osprey 50"}, | ||
42 | {0x0573, 0x2d01, -1, CODEC_SAA7113, 2, V4L2_STD_NTSC, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Hauppauge USB-Live Model 600"}, | ||
43 | {0x0573, 0x2101, -1, CODEC_SAA7113, 2, V4L2_STD_PAL, 2, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Zoran Co. PMD (Nogatech) AV-grabber Manhattan"}, | ||
44 | {0x0573, 0x4100, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, 20, -1, "Nogatech USB-TV (NTSC) FM"}, | ||
45 | {0x0573, 0x4110, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, 20, -1, "PNY USB-TV (NTSC) FM"}, | ||
46 | {0x0573, 0x4450, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "PixelView PlayTv-USB PRO (PAL) FM"}, | ||
47 | {0x0573, 0x4550, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "ZTV ZT-721 2.4GHz USB A/V Receiver"}, | ||
48 | {0x0573, 0x4d00, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 0, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, 20, -1, "Hauppauge WinTv-USB USA"}, | ||
49 | {0x0573, 0x4d01, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 0, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB"}, | ||
50 | {0x0573, 0x4d02, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 0, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB (NTSC)"}, | ||
51 | {0x0573, 0x4d03, -1, CODEC_SAA7111, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB (SECAM) "}, | ||
52 | {0x0573, 0x4d10, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB (NTSC) FM"}, | ||
53 | {0x0573, 0x4d11, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB (PAL) FM"}, | ||
54 | {0x0573, 0x4d12, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB (PAL) FM"}, | ||
55 | {0x0573, 0x4d2a, 0, CODEC_SAA7113, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_MICROTUNE_4049FM5, -1, -1, 0, 3, 7, "Hauppauge WinTv USB (NTSC) FM Model 602 40201 Rev B285"}, | ||
56 | {0x0573, 0x4d2b, 0, CODEC_SAA7113, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_MICROTUNE_4049FM5, -1, -1, 0, 3, 7, "Hauppauge WinTv USB (NTSC) FM Model 602 40201 Rev B282"}, | ||
57 | {0x0573, 0x4d2c, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_FM1216ME_MK3, -1, -1, 0, 3, 7, "Hauppauge WinTv USB (PAL/SECAM) 40209 Rev E1A5"}, | ||
58 | {0x0573, 0x4d20, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB II (PAL) FM Model 40201 Rev B226"}, | ||
59 | {0x0573, 0x4d21, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB II (PAL)"}, | ||
60 | {0x0573, 0x4d22, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB II (PAL) MODEL 566"}, | ||
61 | {0x0573, 0x4d23, -1, CODEC_SAA7113, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB (SECAM) 4D23"}, | ||
62 | {0x0573, 0x4d25, -1, CODEC_SAA7113, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB (SECAM) Model 40209 Rev B234"}, | ||
63 | {0x0573, 0x4d26, -1, CODEC_SAA7113, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB (SECAM) Model 40209 Rev B243"}, | ||
64 | {0x0573, 0x4d27, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_ALPS_TSBE1_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB Model 40204 Rev B281"}, | ||
65 | {0x0573, 0x4d28, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_ALPS_TSBE1_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB Model 40204 Rev B283"}, | ||
66 | {0x0573, 0x4d29, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB Model 40205 Rev B298"}, | ||
67 | {0x0573, 0x4d30, -1, CODEC_SAA7113, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB FM Model 40211 Rev B123"}, | ||
68 | {0x0573, 0x4d31, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB III (PAL) FM Model 568"}, | ||
69 | {0x0573, 0x4d32, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB III (PAL) FM Model 573"}, | ||
70 | {0x0573, 0x4d35, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_MICROTUNE_4049FM5, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB III (PAL) FM Model 40219 Rev B252"}, | ||
71 | {0x0573, 0x4d37, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_FM1216ME_MK3, -1, -1, 0, 3, 7, "Hauppauge WinTV USB device Model 40219 Rev E189"}, | ||
72 | {0x0768, 0x0006, -1, CODEC_SAA7113, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, 5, 5, -1, "Camtel Technology USB TV Genie Pro FM Model TVB330"}, | ||
73 | {0x07d0, 0x0001, -1, CODEC_SAA7113, 2, V4L2_STD_PAL, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Digital Video Creator I"}, | ||
74 | {0x07d0, 0x0002, -1, CODEC_SAA7111, 2, V4L2_STD_NTSC, 0, 0, 1, 0, 0, -1, -1, 82, 20, 7, "Global Village GV-007 (NTSC)"}, | ||
75 | {0x07d0, 0x0003, 0, CODEC_SAA7113, 2, V4L2_STD_NTSC, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Dazzle Fusion Model DVC-50 Rev 1 (NTSC)"}, | ||
76 | {0x07d0, 0x0004, 0, CODEC_SAA7113, 2, V4L2_STD_PAL, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Dazzle Fusion Model DVC-80 Rev 1 (PAL)"}, | ||
77 | {0x07d0, 0x0005, 0, CODEC_SAA7113, 2, V4L2_STD_SECAM, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Dazzle Fusion Model DVC-90 Rev 1 (SECAM)"}, | ||
78 | {0x2304, 0x010d, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 0, 0, 1, TUNER_TEMIC_4066FY5_PAL_I, -1, -1, -1, -1, -1, "Pinnacle Studio PCTV USB (PAL)"}, | ||
79 | {0x2304, 0x0109, -1, CODEC_SAA7111, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM, -1, -1, -1, -1, -1, "Pinnacle Studio PCTV USB (SECAM)"}, | ||
80 | {0x2304, 0x0110, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1,128, 23, -1, "Pinnacle Studio PCTV USB (PAL) FM"}, | ||
81 | {0x2304, 0x0111, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_PAL, -1, -1, -1, -1, -1, "Miro PCTV USB"}, | ||
82 | {0x2304, 0x0112, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Pinnacle Studio PCTV USB (NTSC) FM"}, | ||
83 | {0x2304, 0x0210, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_TEMIC_4009FR5_PAL, -1, -1, 0, 3, 7, "Pinnacle Studio PCTV USB (PAL) FM"}, | ||
84 | {0x2304, 0x0212, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_TEMIC_4039FR5_NTSC, -1, -1, 0, 3, 7, "Pinnacle Studio PCTV USB (NTSC) FM"}, | ||
85 | {0x2304, 0x0214, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_TEMIC_4009FR5_PAL, -1, -1, 0, 3, 7, "Pinnacle Studio PCTV USB (PAL) FM"}, | ||
86 | {0x2304, 0x0300, -1, CODEC_SAA7113, 2, V4L2_STD_NTSC, 1, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Pinnacle Studio Linx Video input cable (NTSC)"}, | ||
87 | {0x2304, 0x0301, -1, CODEC_SAA7113, 2, V4L2_STD_PAL, 1, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Pinnacle Studio Linx Video input cable (PAL)"}, | ||
88 | {0x2304, 0x0419, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_TEMIC_4009FR5_PAL, -1, -1, 0, 3, 7, "Pinnacle PCTV Bungee USB (PAL) FM"}, | ||
89 | {0x2400, 0x4200, -1, CODEC_SAA7111, 3, VIDEO_MODE_NTSC, 1, 0, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB"}, | ||
90 | {} /* Terminating entry */ | ||
91 | }; | ||
92 | |||
93 | /* Supported Devices */ | ||
94 | |||
95 | struct usb_device_id usbvision_table [] = { | ||
96 | { USB_DEVICE(0xFFF0, 0xFFF0) }, /* Custom Dummy USBVision Device */ | ||
97 | { USB_DEVICE(0x0A6F, 0x0400) }, /* Xanboo */ | ||
98 | { USB_DEVICE(0x050d, 0x0208) }, /* Belkin USBView II */ | ||
99 | { USB_DEVICE(0x0571, 0x0002) }, /* echoFX InterView Lite */ | ||
100 | { USB_DEVICE(0x0573, 0x0003) }, /* USBGear USBG-V1 */ | ||
101 | { USB_DEVICE(0x0573, 0x0400) }, /* D-Link V100 */ | ||
102 | { USB_DEVICE(0x0573, 0x2000) }, /* X10 USB Camera */ | ||
103 | { USB_DEVICE(0x0573, 0x2d00) }, /* Osprey 50 */ | ||
104 | { USB_DEVICE(0x0573, 0x2d01) }, /* Hauppauge USB-Live Model 600 */ | ||
105 | { USB_DEVICE(0x0573, 0x2101) }, /* Zoran Co. PMD (Nogatech) AV-grabber Manhattan */ | ||
106 | { USB_DEVICE(0x0573, 0x4100) }, /* Nogatech USB-TV FM (NTSC) */ | ||
107 | { USB_DEVICE(0x0573, 0x4110) }, /* PNY USB-TV (NTSC) FM */ | ||
108 | { USB_DEVICE(0x0573, 0x4450) }, /* PixelView PlayTv-USB PRO (PAL) FM */ | ||
109 | { USB_DEVICE(0x0573, 0x4550) }, /* ZTV ZT-721 2.4GHz USB A/V Receiver */ | ||
110 | { USB_DEVICE(0x0573, 0x4d00) }, /* Hauppauge WinTv-USB USA */ | ||
111 | { USB_DEVICE(0x0573, 0x4d01) }, /* Hauppauge WinTv-USB */ | ||
112 | { USB_DEVICE(0x0573, 0x4d02) }, /* Hauppauge WinTv-USB UK */ | ||
113 | { USB_DEVICE(0x0573, 0x4d03) }, /* Hauppauge WinTv-USB France */ | ||
114 | { USB_DEVICE(0x0573, 0x4d10) }, /* Hauppauge WinTv-USB with FM USA radio */ | ||
115 | { USB_DEVICE(0x0573, 0x4d11) }, /* Hauppauge WinTv-USB (PAL) with FM radio */ | ||
116 | { USB_DEVICE(0x0573, 0x4d12) }, /* Hauppauge WinTv-USB UK with FM Radio */ | ||
117 | { USB_DEVICE(0x0573, 0x4d2a) }, /* Hauppague WinTv USB Model 602 40201 Rev B285 */ | ||
118 | { USB_DEVICE(0x0573, 0x4d2b) }, /* Hauppague WinTv USB Model 602 40201 Rev B282 */ | ||
119 | { USB_DEVICE(0x0573, 0x4d2c) }, /* Hauppague WinTv USB Model 40209 Rev. E1A5 PAL*/ | ||
120 | { USB_DEVICE(0x0573, 0x4d20) }, /* Hauppauge WinTv-USB II (PAL) FM Model 40201 Rev B226 */ | ||
121 | { USB_DEVICE(0x0573, 0x4d21) }, /* Hauppauge WinTv-USB II (PAL) with FM radio*/ | ||
122 | { USB_DEVICE(0x0573, 0x4d22) }, /* Hauppauge WinTv-USB II (PAL) Model 566 */ | ||
123 | { USB_DEVICE(0x0573, 0x4d23) }, /* Hauppauge WinTv-USB France 4D23*/ | ||
124 | { USB_DEVICE(0x0573, 0x4d25) }, /* Hauppauge WinTv-USB Model 40209 rev B234 */ | ||
125 | { USB_DEVICE(0x0573, 0x4d26) }, /* Hauppauge WinTv-USB Model 40209 Rev B243 */ | ||
126 | { USB_DEVICE(0x0573, 0x4d27) }, /* Hauppauge WinTv-USB Model 40204 Rev B281 */ | ||
127 | { USB_DEVICE(0x0573, 0x4d28) }, /* Hauppauge WinTv-USB Model 40204 Rev B283 */ | ||
128 | { USB_DEVICE(0x0573, 0x4d29) }, /* Hauppauge WinTv-USB Model 40205 Rev B298 */ | ||
129 | { USB_DEVICE(0x0573, 0x4d30) }, /* Hauppauge WinTv-USB FM Model 40211 Rev B123 */ | ||
130 | { USB_DEVICE(0x0573, 0x4d31) }, /* Hauppauge WinTv-USB III (PAL) with FM radio Model 568 */ | ||
131 | { USB_DEVICE(0x0573, 0x4d32) }, /* Hauppauge WinTv-USB III (PAL) FM Model 573 */ | ||
132 | { USB_DEVICE(0x0573, 0x4d35) }, /* Hauppauge WinTv-USB III (SECAM) FM Model 40219 Rev B252 */ | ||
133 | { USB_DEVICE(0x0573, 0x4d37) }, /* Hauppauge WinTv-USB Model 40219 Rev E189 */ | ||
134 | { USB_DEVICE(0x0768, 0x0006) }, /* Camtel Technology USB TV Genie Pro FM Model TVB330 */ | ||
135 | { USB_DEVICE(0x07d0, 0x0001) }, /* Digital Video Creator I */ | ||
136 | { USB_DEVICE(0x07d0, 0x0002) }, /* Global Village GV-007 (NTSC) */ | ||
137 | { USB_DEVICE(0x07d0, 0x0003) }, /* Dazzle Fusion Model DVC-50 Rev 1 (NTSC) */ | ||
138 | { USB_DEVICE(0x07d0, 0x0004) }, /* Dazzle Fusion Model DVC-80 Rev 1 (PAL) */ | ||
139 | { USB_DEVICE(0x07d0, 0x0005) }, /* Dazzle Fusion Model DVC-90 Rev 1 (SECAM) */ | ||
140 | { USB_DEVICE(0x2304, 0x010d) }, /* Pinnacle Studio PCTV USB (PAL) */ | ||
141 | { USB_DEVICE(0x2304, 0x0109) }, /* Pinnacle Studio PCTV USB (SECAM) */ | ||
142 | { USB_DEVICE(0x2304, 0x0110) }, /* Pinnacle Studio PCTV USB (PAL) */ | ||
143 | { USB_DEVICE(0x2304, 0x0111) }, /* Miro PCTV USB */ | ||
144 | { USB_DEVICE(0x2304, 0x0112) }, /* Pinnacle Studio PCTV USB (NTSC) with FM radio */ | ||
145 | { USB_DEVICE(0x2304, 0x0210) }, /* Pinnacle Studio PCTV USB (PAL) with FM radio */ | ||
146 | { USB_DEVICE(0x2304, 0x0212) }, /* Pinnacle Studio PCTV USB (NTSC) with FM radio */ | ||
147 | { USB_DEVICE(0x2304, 0x0214) }, /* Pinnacle Studio PCTV USB (PAL) with FM radio */ | ||
148 | { USB_DEVICE(0x2304, 0x0300) }, /* Pinnacle Studio Linx Video input cable (NTSC) */ | ||
149 | { USB_DEVICE(0x2304, 0x0301) }, /* Pinnacle Studio Linx Video input cable (PAL) */ | ||
150 | { USB_DEVICE(0x2304, 0x0419) }, /* Pinnacle PCTV Bungee USB (PAL) FM */ | ||
151 | |||
152 | { USB_DEVICE(0x2400, 0x4200) }, /* Hauppauge WinTv-USB2 Model 42012 */ | ||
153 | |||
154 | { } /* Terminating entry */ | ||
155 | }; | ||
156 | |||
157 | MODULE_DEVICE_TABLE (usb, usbvision_table); | ||
diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c new file mode 100644 index 000000000000..797b97baf9ed --- /dev/null +++ b/drivers/media/video/usbvision/usbvision-core.c | |||
@@ -0,0 +1,2554 @@ | |||
1 | /* | ||
2 | * usbvision-core.c - driver for NT100x USB video capture devices | ||
3 | * | ||
4 | * | ||
5 | * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de> | ||
6 | * Dwaine Garden <dwainegarden@rogers.com> | ||
7 | * | ||
8 | * This module is part of usbvision driver project. | ||
9 | * Updates to driver completed by Dwaine P. Garden | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | */ | ||
25 | |||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/sched.h> | ||
28 | #include <linux/list.h> | ||
29 | #include <linux/timer.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/mm.h> | ||
32 | #include <linux/utsname.h> | ||
33 | #include <linux/highmem.h> | ||
34 | #include <linux/smp_lock.h> | ||
35 | #include <linux/videodev.h> | ||
36 | #include <linux/vmalloc.h> | ||
37 | #include <linux/module.h> | ||
38 | #include <linux/init.h> | ||
39 | #include <linux/spinlock.h> | ||
40 | #include <asm/io.h> | ||
41 | #include <linux/videodev2.h> | ||
42 | #include <linux/video_decoder.h> | ||
43 | #include <linux/i2c.h> | ||
44 | |||
45 | #include <media/saa7115.h> | ||
46 | #include <media/v4l2-common.h> | ||
47 | #include <media/tuner.h> | ||
48 | #include <media/audiochip.h> | ||
49 | |||
50 | #include <linux/moduleparam.h> | ||
51 | #include <linux/workqueue.h> | ||
52 | |||
53 | #ifdef CONFIG_KMOD | ||
54 | #include <linux/kmod.h> | ||
55 | #endif | ||
56 | |||
57 | #include "usbvision.h" | ||
58 | |||
59 | static unsigned int core_debug = 0; | ||
60 | module_param(core_debug,int,0644); | ||
61 | MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); | ||
62 | |||
63 | static unsigned int force_testpattern = 0; | ||
64 | module_param(force_testpattern,int,0644); | ||
65 | MODULE_PARM_DESC(force_testpattern,"enable test pattern display [core]"); | ||
66 | |||
67 | static int adjustCompression = 1; // Set the compression to be adaptive | ||
68 | module_param(adjustCompression, int, 0444); | ||
69 | MODULE_PARM_DESC(adjustCompression, " Set the ADPCM compression for the device. Default: 1 (On)"); | ||
70 | |||
71 | static int SwitchSVideoInput = 0; // To help people with Black and White output with using s-video input. Some cables and input device are wired differently. | ||
72 | module_param(SwitchSVideoInput, int, 0444); | ||
73 | MODULE_PARM_DESC(SwitchSVideoInput, " Set the S-Video input. Some cables and input device are wired differently. Default: 0 (Off)"); | ||
74 | |||
75 | #define ENABLE_HEXDUMP 0 /* Enable if you need it */ | ||
76 | |||
77 | |||
78 | #ifdef USBVISION_DEBUG | ||
79 | #define PDEBUG(level, fmt, args...) \ | ||
80 | if (core_debug & (level)) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , ## args) | ||
81 | #else | ||
82 | #define PDEBUG(level, fmt, args...) do {} while(0) | ||
83 | #endif | ||
84 | |||
85 | #define DBG_HEADER 1<<0 | ||
86 | #define DBG_IRQ 1<<1 | ||
87 | #define DBG_ISOC 1<<2 | ||
88 | #define DBG_PARSE 1<<3 | ||
89 | #define DBG_SCRATCH 1<<4 | ||
90 | #define DBG_FUNC 1<<5 | ||
91 | |||
92 | static const int max_imgwidth = MAX_FRAME_WIDTH; | ||
93 | static const int max_imgheight = MAX_FRAME_HEIGHT; | ||
94 | static const int min_imgwidth = MIN_FRAME_WIDTH; | ||
95 | static const int min_imgheight = MIN_FRAME_HEIGHT; | ||
96 | |||
97 | /* The value of 'scratch_buf_size' affects quality of the picture | ||
98 | * in many ways. Shorter buffers may cause loss of data when client | ||
99 | * is too slow. Larger buffers are memory-consuming and take longer | ||
100 | * to work with. This setting can be adjusted, but the default value | ||
101 | * should be OK for most desktop users. | ||
102 | */ | ||
103 | #define DEFAULT_SCRATCH_BUF_SIZE (0x20000) // 128kB memory scratch buffer | ||
104 | static const int scratch_buf_size = DEFAULT_SCRATCH_BUF_SIZE; | ||
105 | |||
106 | // Function prototypes | ||
107 | static int usbvision_request_intra (struct usb_usbvision *usbvision); | ||
108 | static int usbvision_unrequest_intra (struct usb_usbvision *usbvision); | ||
109 | static int usbvision_adjust_compression (struct usb_usbvision *usbvision); | ||
110 | static int usbvision_measure_bandwidth (struct usb_usbvision *usbvision); | ||
111 | |||
112 | /*******************************/ | ||
113 | /* Memory management functions */ | ||
114 | /*******************************/ | ||
115 | |||
116 | /* | ||
117 | * Here we want the physical address of the memory. | ||
118 | * This is used when initializing the contents of the area. | ||
119 | */ | ||
120 | |||
121 | void *usbvision_rvmalloc(unsigned long size) | ||
122 | { | ||
123 | void *mem; | ||
124 | unsigned long adr; | ||
125 | |||
126 | size = PAGE_ALIGN(size); | ||
127 | mem = vmalloc_32(size); | ||
128 | if (!mem) | ||
129 | return NULL; | ||
130 | |||
131 | memset(mem, 0, size); /* Clear the ram out, no junk to the user */ | ||
132 | adr = (unsigned long) mem; | ||
133 | while (size > 0) { | ||
134 | SetPageReserved(vmalloc_to_page((void *)adr)); | ||
135 | adr += PAGE_SIZE; | ||
136 | size -= PAGE_SIZE; | ||
137 | } | ||
138 | |||
139 | return mem; | ||
140 | } | ||
141 | |||
142 | void usbvision_rvfree(void *mem, unsigned long size) | ||
143 | { | ||
144 | unsigned long adr; | ||
145 | |||
146 | if (!mem) | ||
147 | return; | ||
148 | |||
149 | size = PAGE_ALIGN(size); | ||
150 | |||
151 | adr = (unsigned long) mem; | ||
152 | while ((long) size > 0) { | ||
153 | ClearPageReserved(vmalloc_to_page((void *)adr)); | ||
154 | adr += PAGE_SIZE; | ||
155 | size -= PAGE_SIZE; | ||
156 | } | ||
157 | |||
158 | vfree(mem); | ||
159 | } | ||
160 | |||
161 | |||
162 | |||
163 | #if ENABLE_HEXDUMP | ||
164 | static void usbvision_hexdump(const unsigned char *data, int len) | ||
165 | { | ||
166 | char tmp[80]; | ||
167 | int i, k; | ||
168 | |||
169 | for (i = k = 0; len > 0; i++, len--) { | ||
170 | if (i > 0 && (i % 16 == 0)) { | ||
171 | printk("%s\n", tmp); | ||
172 | k = 0; | ||
173 | } | ||
174 | k += sprintf(&tmp[k], "%02x ", data[i]); | ||
175 | } | ||
176 | if (k > 0) | ||
177 | printk("%s\n", tmp); | ||
178 | } | ||
179 | #endif | ||
180 | |||
181 | /******************************** | ||
182 | * scratch ring buffer handling | ||
183 | ********************************/ | ||
184 | int scratch_len(struct usb_usbvision *usbvision) /*This returns the amount of data actually in the buffer */ | ||
185 | { | ||
186 | int len = usbvision->scratch_write_ptr - usbvision->scratch_read_ptr; | ||
187 | if (len < 0) { | ||
188 | len += scratch_buf_size; | ||
189 | } | ||
190 | PDEBUG(DBG_SCRATCH, "scratch_len() = %d\n", len); | ||
191 | |||
192 | return len; | ||
193 | } | ||
194 | |||
195 | |||
196 | /* This returns the free space left in the buffer */ | ||
197 | int scratch_free(struct usb_usbvision *usbvision) | ||
198 | { | ||
199 | int free = usbvision->scratch_read_ptr - usbvision->scratch_write_ptr; | ||
200 | if (free <= 0) { | ||
201 | free += scratch_buf_size; | ||
202 | } | ||
203 | if (free) { | ||
204 | free -= 1; /* at least one byte in the buffer must */ | ||
205 | /* left blank, otherwise there is no chance to differ between full and empty */ | ||
206 | } | ||
207 | PDEBUG(DBG_SCRATCH, "return %d\n", free); | ||
208 | |||
209 | return free; | ||
210 | } | ||
211 | |||
212 | |||
213 | /* This puts data into the buffer */ | ||
214 | int scratch_put(struct usb_usbvision *usbvision, unsigned char *data, int len) | ||
215 | { | ||
216 | int len_part; | ||
217 | |||
218 | if (usbvision->scratch_write_ptr + len < scratch_buf_size) { | ||
219 | memcpy(usbvision->scratch + usbvision->scratch_write_ptr, data, len); | ||
220 | usbvision->scratch_write_ptr += len; | ||
221 | } | ||
222 | else { | ||
223 | len_part = scratch_buf_size - usbvision->scratch_write_ptr; | ||
224 | memcpy(usbvision->scratch + usbvision->scratch_write_ptr, data, len_part); | ||
225 | if (len == len_part) { | ||
226 | usbvision->scratch_write_ptr = 0; /* just set write_ptr to zero */ | ||
227 | } | ||
228 | else { | ||
229 | memcpy(usbvision->scratch, data + len_part, len - len_part); | ||
230 | usbvision->scratch_write_ptr = len - len_part; | ||
231 | } | ||
232 | } | ||
233 | |||
234 | PDEBUG(DBG_SCRATCH, "len=%d, new write_ptr=%d\n", len, usbvision->scratch_write_ptr); | ||
235 | |||
236 | return len; | ||
237 | } | ||
238 | |||
239 | /* This marks the write_ptr as position of new frame header */ | ||
240 | void scratch_mark_header(struct usb_usbvision *usbvision) | ||
241 | { | ||
242 | PDEBUG(DBG_SCRATCH, "header at write_ptr=%d\n", usbvision->scratch_headermarker_write_ptr); | ||
243 | |||
244 | usbvision->scratch_headermarker[usbvision->scratch_headermarker_write_ptr] = | ||
245 | usbvision->scratch_write_ptr; | ||
246 | usbvision->scratch_headermarker_write_ptr += 1; | ||
247 | usbvision->scratch_headermarker_write_ptr %= USBVISION_NUM_HEADERMARKER; | ||
248 | } | ||
249 | |||
250 | /* This gets data from the buffer at the given "ptr" position */ | ||
251 | int scratch_get_extra(struct usb_usbvision *usbvision, unsigned char *data, int *ptr, int len) | ||
252 | { | ||
253 | int len_part; | ||
254 | if (*ptr + len < scratch_buf_size) { | ||
255 | memcpy(data, usbvision->scratch + *ptr, len); | ||
256 | *ptr += len; | ||
257 | } | ||
258 | else { | ||
259 | len_part = scratch_buf_size - *ptr; | ||
260 | memcpy(data, usbvision->scratch + *ptr, len_part); | ||
261 | if (len == len_part) { | ||
262 | *ptr = 0; /* just set the y_ptr to zero */ | ||
263 | } | ||
264 | else { | ||
265 | memcpy(data + len_part, usbvision->scratch, len - len_part); | ||
266 | *ptr = len - len_part; | ||
267 | } | ||
268 | } | ||
269 | |||
270 | PDEBUG(DBG_SCRATCH, "len=%d, new ptr=%d\n", len, *ptr); | ||
271 | |||
272 | return len; | ||
273 | } | ||
274 | |||
275 | |||
276 | /* This sets the scratch extra read pointer */ | ||
277 | void scratch_set_extra_ptr(struct usb_usbvision *usbvision, int *ptr, int len) | ||
278 | { | ||
279 | *ptr = (usbvision->scratch_read_ptr + len)%scratch_buf_size; | ||
280 | |||
281 | PDEBUG(DBG_SCRATCH, "ptr=%d\n", *ptr); | ||
282 | } | ||
283 | |||
284 | |||
285 | /*This increments the scratch extra read pointer */ | ||
286 | void scratch_inc_extra_ptr(int *ptr, int len) | ||
287 | { | ||
288 | *ptr = (*ptr + len) % scratch_buf_size; | ||
289 | |||
290 | PDEBUG(DBG_SCRATCH, "ptr=%d\n", *ptr); | ||
291 | } | ||
292 | |||
293 | |||
294 | /* This gets data from the buffer */ | ||
295 | int scratch_get(struct usb_usbvision *usbvision, unsigned char *data, int len) | ||
296 | { | ||
297 | int len_part; | ||
298 | if (usbvision->scratch_read_ptr + len < scratch_buf_size) { | ||
299 | memcpy(data, usbvision->scratch + usbvision->scratch_read_ptr, len); | ||
300 | usbvision->scratch_read_ptr += len; | ||
301 | } | ||
302 | else { | ||
303 | len_part = scratch_buf_size - usbvision->scratch_read_ptr; | ||
304 | memcpy(data, usbvision->scratch + usbvision->scratch_read_ptr, len_part); | ||
305 | if (len == len_part) { | ||
306 | usbvision->scratch_read_ptr = 0; /* just set the read_ptr to zero */ | ||
307 | } | ||
308 | else { | ||
309 | memcpy(data + len_part, usbvision->scratch, len - len_part); | ||
310 | usbvision->scratch_read_ptr = len - len_part; | ||
311 | } | ||
312 | } | ||
313 | |||
314 | PDEBUG(DBG_SCRATCH, "len=%d, new read_ptr=%d\n", len, usbvision->scratch_read_ptr); | ||
315 | |||
316 | return len; | ||
317 | } | ||
318 | |||
319 | |||
320 | /* This sets read pointer to next header and returns it */ | ||
321 | int scratch_get_header(struct usb_usbvision *usbvision,struct usbvision_frame_header *header) | ||
322 | { | ||
323 | int errCode = 0; | ||
324 | |||
325 | PDEBUG(DBG_SCRATCH, "from read_ptr=%d", usbvision->scratch_headermarker_read_ptr); | ||
326 | |||
327 | while (usbvision->scratch_headermarker_write_ptr - | ||
328 | usbvision->scratch_headermarker_read_ptr != 0) { | ||
329 | usbvision->scratch_read_ptr = | ||
330 | usbvision->scratch_headermarker[usbvision->scratch_headermarker_read_ptr]; | ||
331 | usbvision->scratch_headermarker_read_ptr += 1; | ||
332 | usbvision->scratch_headermarker_read_ptr %= USBVISION_NUM_HEADERMARKER; | ||
333 | scratch_get(usbvision, (unsigned char *)header, USBVISION_HEADER_LENGTH); | ||
334 | if ((header->magic_1 == USBVISION_MAGIC_1) | ||
335 | && (header->magic_2 == USBVISION_MAGIC_2) | ||
336 | && (header->headerLength == USBVISION_HEADER_LENGTH)) { | ||
337 | errCode = USBVISION_HEADER_LENGTH; | ||
338 | header->frameWidth = header->frameWidthLo + (header->frameWidthHi << 8); | ||
339 | header->frameHeight = header->frameHeightLo + (header->frameHeightHi << 8); | ||
340 | break; | ||
341 | } | ||
342 | } | ||
343 | |||
344 | return errCode; | ||
345 | } | ||
346 | |||
347 | |||
348 | /*This removes len bytes of old data from the buffer */ | ||
349 | void scratch_rm_old(struct usb_usbvision *usbvision, int len) | ||
350 | { | ||
351 | |||
352 | usbvision->scratch_read_ptr += len; | ||
353 | usbvision->scratch_read_ptr %= scratch_buf_size; | ||
354 | PDEBUG(DBG_SCRATCH, "read_ptr is now %d\n", usbvision->scratch_read_ptr); | ||
355 | } | ||
356 | |||
357 | |||
358 | /*This resets the buffer - kills all data in it too */ | ||
359 | void scratch_reset(struct usb_usbvision *usbvision) | ||
360 | { | ||
361 | PDEBUG(DBG_SCRATCH, "\n"); | ||
362 | |||
363 | usbvision->scratch_read_ptr = 0; | ||
364 | usbvision->scratch_write_ptr = 0; | ||
365 | usbvision->scratch_headermarker_read_ptr = 0; | ||
366 | usbvision->scratch_headermarker_write_ptr = 0; | ||
367 | usbvision->isocstate = IsocState_NoFrame; | ||
368 | } | ||
369 | |||
370 | int usbvision_scratch_alloc(struct usb_usbvision *usbvision) | ||
371 | { | ||
372 | usbvision->scratch = vmalloc(scratch_buf_size); | ||
373 | scratch_reset(usbvision); | ||
374 | if(usbvision->scratch == NULL) { | ||
375 | err("%s: unable to allocate %d bytes for scratch", | ||
376 | __FUNCTION__, scratch_buf_size); | ||
377 | return -ENOMEM; | ||
378 | } | ||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | void usbvision_scratch_free(struct usb_usbvision *usbvision) | ||
383 | { | ||
384 | if (usbvision->scratch != NULL) { | ||
385 | vfree(usbvision->scratch); | ||
386 | usbvision->scratch = NULL; | ||
387 | } | ||
388 | } | ||
389 | |||
390 | /* | ||
391 | * usbvision_testpattern() | ||
392 | * | ||
393 | * Procedure forms a test pattern (yellow grid on blue background). | ||
394 | * | ||
395 | * Parameters: | ||
396 | * fullframe: if TRUE then entire frame is filled, otherwise the procedure | ||
397 | * continues from the current scanline. | ||
398 | * pmode 0: fill the frame with solid blue color (like on VCR or TV) | ||
399 | * 1: Draw a colored grid | ||
400 | * | ||
401 | */ | ||
402 | void usbvision_testpattern(struct usb_usbvision *usbvision, int fullframe, | ||
403 | int pmode) | ||
404 | { | ||
405 | static const char proc[] = "usbvision_testpattern"; | ||
406 | struct usbvision_frame *frame; | ||
407 | unsigned char *f; | ||
408 | int num_cell = 0; | ||
409 | int scan_length = 0; | ||
410 | static int num_pass = 0; | ||
411 | |||
412 | if (usbvision == NULL) { | ||
413 | printk(KERN_ERR "%s: usbvision == NULL\n", proc); | ||
414 | return; | ||
415 | } | ||
416 | if (usbvision->curFrame == NULL) { | ||
417 | printk(KERN_ERR "%s: usbvision->curFrame is NULL.\n", proc); | ||
418 | return; | ||
419 | } | ||
420 | |||
421 | /* Grab the current frame */ | ||
422 | frame = usbvision->curFrame; | ||
423 | |||
424 | /* Optionally start at the beginning */ | ||
425 | if (fullframe) { | ||
426 | frame->curline = 0; | ||
427 | frame->scanlength = 0; | ||
428 | } | ||
429 | |||
430 | /* Form every scan line */ | ||
431 | for (; frame->curline < frame->frmheight; frame->curline++) { | ||
432 | int i; | ||
433 | |||
434 | f = frame->data + (usbvision->curwidth * 3 * frame->curline); | ||
435 | for (i = 0; i < usbvision->curwidth; i++) { | ||
436 | unsigned char cb = 0x80; | ||
437 | unsigned char cg = 0; | ||
438 | unsigned char cr = 0; | ||
439 | |||
440 | if (pmode == 1) { | ||
441 | if (frame->curline % 32 == 0) | ||
442 | cb = 0, cg = cr = 0xFF; | ||
443 | else if (i % 32 == 0) { | ||
444 | if (frame->curline % 32 == 1) | ||
445 | num_cell++; | ||
446 | cb = 0, cg = cr = 0xFF; | ||
447 | } else { | ||
448 | cb = | ||
449 | ((num_cell * 7) + | ||
450 | num_pass) & 0xFF; | ||
451 | cg = | ||
452 | ((num_cell * 5) + | ||
453 | num_pass * 2) & 0xFF; | ||
454 | cr = | ||
455 | ((num_cell * 3) + | ||
456 | num_pass * 3) & 0xFF; | ||
457 | } | ||
458 | } else { | ||
459 | /* Just the blue screen */ | ||
460 | } | ||
461 | |||
462 | *f++ = cb; | ||
463 | *f++ = cg; | ||
464 | *f++ = cr; | ||
465 | scan_length += 3; | ||
466 | } | ||
467 | } | ||
468 | |||
469 | frame->grabstate = FrameState_Done; | ||
470 | frame->scanlength += scan_length; | ||
471 | ++num_pass; | ||
472 | |||
473 | } | ||
474 | |||
475 | /* | ||
476 | * usbvision_decompress_alloc() | ||
477 | * | ||
478 | * allocates intermediate buffer for decompression | ||
479 | */ | ||
480 | int usbvision_decompress_alloc(struct usb_usbvision *usbvision) | ||
481 | { | ||
482 | int IFB_size = MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * 3 / 2; | ||
483 | usbvision->IntraFrameBuffer = vmalloc(IFB_size); | ||
484 | if (usbvision->IntraFrameBuffer == NULL) { | ||
485 | err("%s: unable to allocate %d for compr. frame buffer", __FUNCTION__, IFB_size); | ||
486 | return -ENOMEM; | ||
487 | } | ||
488 | return 0; | ||
489 | } | ||
490 | |||
491 | /* | ||
492 | * usbvision_decompress_free() | ||
493 | * | ||
494 | * frees intermediate buffer for decompression | ||
495 | */ | ||
496 | void usbvision_decompress_free(struct usb_usbvision *usbvision) | ||
497 | { | ||
498 | if (usbvision->IntraFrameBuffer != NULL) { | ||
499 | vfree(usbvision->IntraFrameBuffer); | ||
500 | usbvision->IntraFrameBuffer = NULL; | ||
501 | } | ||
502 | } | ||
503 | |||
504 | /************************************************************ | ||
505 | * Here comes the data parsing stuff that is run as interrupt | ||
506 | ************************************************************/ | ||
507 | /* | ||
508 | * usbvision_find_header() | ||
509 | * | ||
510 | * Locate one of supported header markers in the scratch buffer. | ||
511 | */ | ||
512 | static enum ParseState usbvision_find_header(struct usb_usbvision *usbvision) | ||
513 | { | ||
514 | struct usbvision_frame *frame; | ||
515 | int foundHeader = 0; | ||
516 | |||
517 | frame = usbvision->curFrame; | ||
518 | |||
519 | while (scratch_get_header(usbvision, &frame->isocHeader) == USBVISION_HEADER_LENGTH) { | ||
520 | // found header in scratch | ||
521 | PDEBUG(DBG_HEADER, "found header: 0x%02x%02x %d %d %d %d %#x 0x%02x %u %u", | ||
522 | frame->isocHeader.magic_2, | ||
523 | frame->isocHeader.magic_1, | ||
524 | frame->isocHeader.headerLength, | ||
525 | frame->isocHeader.frameNum, | ||
526 | frame->isocHeader.framePhase, | ||
527 | frame->isocHeader.frameLatency, | ||
528 | frame->isocHeader.dataFormat, | ||
529 | frame->isocHeader.formatParam, | ||
530 | frame->isocHeader.frameWidth, | ||
531 | frame->isocHeader.frameHeight); | ||
532 | |||
533 | if (usbvision->requestIntra) { | ||
534 | if (frame->isocHeader.formatParam & 0x80) { | ||
535 | foundHeader = 1; | ||
536 | usbvision->lastIsocFrameNum = -1; // do not check for lost frames this time | ||
537 | usbvision_unrequest_intra(usbvision); | ||
538 | break; | ||
539 | } | ||
540 | } | ||
541 | else { | ||
542 | foundHeader = 1; | ||
543 | break; | ||
544 | } | ||
545 | } | ||
546 | |||
547 | if (foundHeader) { | ||
548 | frame->frmwidth = frame->isocHeader.frameWidth * usbvision->stretch_width; | ||
549 | frame->frmheight = frame->isocHeader.frameHeight * usbvision->stretch_height; | ||
550 | frame->v4l2_linesize = (frame->frmwidth * frame->v4l2_format.depth)>> 3; | ||
551 | } | ||
552 | else { // no header found | ||
553 | PDEBUG(DBG_HEADER, "skipping scratch data, no header"); | ||
554 | scratch_reset(usbvision); | ||
555 | return ParseState_EndParse; | ||
556 | } | ||
557 | |||
558 | // found header | ||
559 | if (frame->isocHeader.dataFormat==ISOC_MODE_COMPRESS) { | ||
560 | //check isocHeader.frameNum for lost frames | ||
561 | if (usbvision->lastIsocFrameNum >= 0) { | ||
562 | if (((usbvision->lastIsocFrameNum + 1) % 32) != frame->isocHeader.frameNum) { | ||
563 | // unexpected frame drop: need to request new intra frame | ||
564 | PDEBUG(DBG_HEADER, "Lost frame before %d on USB", frame->isocHeader.frameNum); | ||
565 | usbvision_request_intra(usbvision); | ||
566 | return ParseState_NextFrame; | ||
567 | } | ||
568 | } | ||
569 | usbvision->lastIsocFrameNum = frame->isocHeader.frameNum; | ||
570 | } | ||
571 | usbvision->header_count++; | ||
572 | frame->scanstate = ScanState_Lines; | ||
573 | frame->curline = 0; | ||
574 | |||
575 | if (force_testpattern) { | ||
576 | usbvision_testpattern(usbvision, 1, 1); | ||
577 | return ParseState_NextFrame; | ||
578 | } | ||
579 | return ParseState_Continue; | ||
580 | } | ||
581 | |||
582 | static enum ParseState usbvision_parse_lines_422(struct usb_usbvision *usbvision, | ||
583 | long *pcopylen) | ||
584 | { | ||
585 | volatile struct usbvision_frame *frame; | ||
586 | unsigned char *f; | ||
587 | int len; | ||
588 | int i; | ||
589 | unsigned char yuyv[4]={180, 128, 10, 128}; // YUV components | ||
590 | unsigned char rv, gv, bv; // RGB components | ||
591 | int clipmask_index, bytes_per_pixel; | ||
592 | int stretch_bytes, clipmask_add; | ||
593 | |||
594 | frame = usbvision->curFrame; | ||
595 | f = frame->data + (frame->v4l2_linesize * frame->curline); | ||
596 | |||
597 | /* Make sure there's enough data for the entire line */ | ||
598 | len = (frame->isocHeader.frameWidth * 2)+5; | ||
599 | if (scratch_len(usbvision) < len) { | ||
600 | PDEBUG(DBG_PARSE, "out of data in line %d, need %u.\n", frame->curline, len); | ||
601 | return ParseState_Out; | ||
602 | } | ||
603 | |||
604 | if ((frame->curline + 1) >= frame->frmheight) { | ||
605 | return ParseState_NextFrame; | ||
606 | } | ||
607 | |||
608 | bytes_per_pixel = frame->v4l2_format.bytes_per_pixel; | ||
609 | stretch_bytes = (usbvision->stretch_width - 1) * bytes_per_pixel; | ||
610 | clipmask_index = frame->curline * MAX_FRAME_WIDTH; | ||
611 | clipmask_add = usbvision->stretch_width; | ||
612 | |||
613 | for (i = 0; i < frame->frmwidth; i+=(2 * usbvision->stretch_width)) { | ||
614 | |||
615 | scratch_get(usbvision, &yuyv[0], 4); | ||
616 | |||
617 | if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { | ||
618 | *f++ = yuyv[0]; // Y | ||
619 | *f++ = yuyv[3]; // U | ||
620 | } | ||
621 | else { | ||
622 | |||
623 | YUV_TO_RGB_BY_THE_BOOK(yuyv[0], yuyv[1], yuyv[3], rv, gv, bv); | ||
624 | switch (frame->v4l2_format.format) { | ||
625 | case V4L2_PIX_FMT_RGB565: | ||
626 | *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 3)); | ||
627 | *f++ = (0x07 & (gv >> 5)) | (0xF8 & rv); | ||
628 | break; | ||
629 | case V4L2_PIX_FMT_RGB24: | ||
630 | *f++ = bv; | ||
631 | *f++ = gv; | ||
632 | *f++ = rv; | ||
633 | break; | ||
634 | case V4L2_PIX_FMT_RGB32: | ||
635 | *f++ = bv; | ||
636 | *f++ = gv; | ||
637 | *f++ = rv; | ||
638 | f++; | ||
639 | break; | ||
640 | case V4L2_PIX_FMT_RGB555: | ||
641 | *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 2)); | ||
642 | *f++ = (0x03 & (gv >> 6)) | (0x7C & (rv >> 1)); | ||
643 | break; | ||
644 | } | ||
645 | } | ||
646 | clipmask_index += clipmask_add; | ||
647 | f += stretch_bytes; | ||
648 | |||
649 | if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { | ||
650 | *f++ = yuyv[2]; // Y | ||
651 | *f++ = yuyv[1]; // V | ||
652 | } | ||
653 | else { | ||
654 | |||
655 | YUV_TO_RGB_BY_THE_BOOK(yuyv[2], yuyv[1], yuyv[3], rv, gv, bv); | ||
656 | switch (frame->v4l2_format.format) { | ||
657 | case V4L2_PIX_FMT_RGB565: | ||
658 | *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 3)); | ||
659 | *f++ = (0x07 & (gv >> 5)) | (0xF8 & rv); | ||
660 | break; | ||
661 | case V4L2_PIX_FMT_RGB24: | ||
662 | *f++ = bv; | ||
663 | *f++ = gv; | ||
664 | *f++ = rv; | ||
665 | break; | ||
666 | case V4L2_PIX_FMT_RGB32: | ||
667 | *f++ = bv; | ||
668 | *f++ = gv; | ||
669 | *f++ = rv; | ||
670 | f++; | ||
671 | break; | ||
672 | case V4L2_PIX_FMT_RGB555: | ||
673 | *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 2)); | ||
674 | *f++ = (0x03 & (gv >> 6)) | (0x7C & (rv >> 1)); | ||
675 | break; | ||
676 | } | ||
677 | } | ||
678 | clipmask_index += clipmask_add; | ||
679 | f += stretch_bytes; | ||
680 | } | ||
681 | |||
682 | frame->curline += usbvision->stretch_height; | ||
683 | *pcopylen += frame->v4l2_linesize * usbvision->stretch_height; | ||
684 | |||
685 | if (frame->curline >= frame->frmheight) { | ||
686 | return ParseState_NextFrame; | ||
687 | } | ||
688 | else { | ||
689 | return ParseState_Continue; | ||
690 | } | ||
691 | } | ||
692 | |||
693 | /* The decompression routine */ | ||
694 | static int usbvision_decompress(struct usb_usbvision *usbvision,unsigned char *Compressed, | ||
695 | unsigned char *Decompressed, int *StartPos, | ||
696 | int *BlockTypeStartPos, int Len) | ||
697 | { | ||
698 | int RestPixel, Idx, MaxPos, Pos, ExtraPos, BlockLen, BlockTypePos, BlockTypeLen; | ||
699 | unsigned char BlockByte, BlockCode, BlockType, BlockTypeByte, Integrator; | ||
700 | |||
701 | Integrator = 0; | ||
702 | Pos = *StartPos; | ||
703 | BlockTypePos = *BlockTypeStartPos; | ||
704 | MaxPos = 396; //Pos + Len; | ||
705 | ExtraPos = Pos; | ||
706 | BlockLen = 0; | ||
707 | BlockByte = 0; | ||
708 | BlockCode = 0; | ||
709 | BlockType = 0; | ||
710 | BlockTypeByte = 0; | ||
711 | BlockTypeLen = 0; | ||
712 | RestPixel = Len; | ||
713 | |||
714 | for (Idx = 0; Idx < Len; Idx++) { | ||
715 | |||
716 | if (BlockLen == 0) { | ||
717 | if (BlockTypeLen==0) { | ||
718 | BlockTypeByte = Compressed[BlockTypePos]; | ||
719 | BlockTypePos++; | ||
720 | BlockTypeLen = 4; | ||
721 | } | ||
722 | BlockType = (BlockTypeByte & 0xC0) >> 6; | ||
723 | |||
724 | //statistic: | ||
725 | usbvision->ComprBlockTypes[BlockType]++; | ||
726 | |||
727 | Pos = ExtraPos; | ||
728 | if (BlockType == 0) { | ||
729 | if(RestPixel >= 24) { | ||
730 | Idx += 23; | ||
731 | RestPixel -= 24; | ||
732 | Integrator = Decompressed[Idx]; | ||
733 | } else { | ||
734 | Idx += RestPixel - 1; | ||
735 | RestPixel = 0; | ||
736 | } | ||
737 | } else { | ||
738 | BlockCode = Compressed[Pos]; | ||
739 | Pos++; | ||
740 | if (RestPixel >= 24) { | ||
741 | BlockLen = 24; | ||
742 | } else { | ||
743 | BlockLen = RestPixel; | ||
744 | } | ||
745 | RestPixel -= BlockLen; | ||
746 | ExtraPos = Pos + (BlockLen / 4); | ||
747 | } | ||
748 | BlockTypeByte <<= 2; | ||
749 | BlockTypeLen -= 1; | ||
750 | } | ||
751 | if (BlockLen > 0) { | ||
752 | if ((BlockLen%4) == 0) { | ||
753 | BlockByte = Compressed[Pos]; | ||
754 | Pos++; | ||
755 | } | ||
756 | if (BlockType == 1) { //inter Block | ||
757 | Integrator = Decompressed[Idx]; | ||
758 | } | ||
759 | switch (BlockByte & 0xC0) { | ||
760 | case 0x03<<6: | ||
761 | Integrator += Compressed[ExtraPos]; | ||
762 | ExtraPos++; | ||
763 | break; | ||
764 | case 0x02<<6: | ||
765 | Integrator += BlockCode; | ||
766 | break; | ||
767 | case 0x00: | ||
768 | Integrator -= BlockCode; | ||
769 | break; | ||
770 | } | ||
771 | Decompressed[Idx] = Integrator; | ||
772 | BlockByte <<= 2; | ||
773 | BlockLen -= 1; | ||
774 | } | ||
775 | } | ||
776 | *StartPos = ExtraPos; | ||
777 | *BlockTypeStartPos = BlockTypePos; | ||
778 | return Idx; | ||
779 | } | ||
780 | |||
781 | |||
782 | /* | ||
783 | * usbvision_parse_compress() | ||
784 | * | ||
785 | * Parse compressed frame from the scratch buffer, put | ||
786 | * decoded RGB value into the current frame buffer and add the written | ||
787 | * number of bytes (RGB) to the *pcopylen. | ||
788 | * | ||
789 | */ | ||
790 | static enum ParseState usbvision_parse_compress(struct usb_usbvision *usbvision, | ||
791 | long *pcopylen) | ||
792 | { | ||
793 | #define USBVISION_STRIP_MAGIC 0x5A | ||
794 | #define USBVISION_STRIP_LEN_MAX 400 | ||
795 | #define USBVISION_STRIP_HEADER_LEN 3 | ||
796 | |||
797 | struct usbvision_frame *frame; | ||
798 | unsigned char *f,*u = NULL ,*v = NULL; | ||
799 | unsigned char StripData[USBVISION_STRIP_LEN_MAX]; | ||
800 | unsigned char StripHeader[USBVISION_STRIP_HEADER_LEN]; | ||
801 | int Idx, IdxEnd, StripLen, StripPtr, StartBlockPos, BlockPos, BlockTypePos; | ||
802 | int clipmask_index, bytes_per_pixel, rc; | ||
803 | int imageSize; | ||
804 | unsigned char rv, gv, bv; | ||
805 | static unsigned char *Y, *U, *V; | ||
806 | |||
807 | frame = usbvision->curFrame; | ||
808 | imageSize = frame->frmwidth * frame->frmheight; | ||
809 | if ( (frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) || | ||
810 | (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) ) { // this is a planar format | ||
811 | //... v4l2_linesize not used here. | ||
812 | f = frame->data + (frame->width * frame->curline); | ||
813 | } else | ||
814 | f = frame->data + (frame->v4l2_linesize * frame->curline); | ||
815 | |||
816 | if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV){ //initialise u and v pointers | ||
817 | // get base of u and b planes add halfoffset | ||
818 | |||
819 | u = frame->data | ||
820 | + imageSize | ||
821 | + (frame->frmwidth >>1) * frame->curline ; | ||
822 | v = u + (imageSize >>1 ); | ||
823 | |||
824 | } else if (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420){ | ||
825 | |||
826 | v = frame->data + imageSize + ((frame->curline* (frame->width))>>2) ; | ||
827 | u = v + (imageSize >>2) ; | ||
828 | } | ||
829 | |||
830 | if (frame->curline == 0) { | ||
831 | usbvision_adjust_compression(usbvision); | ||
832 | } | ||
833 | |||
834 | if (scratch_len(usbvision) < USBVISION_STRIP_HEADER_LEN) { | ||
835 | return ParseState_Out; | ||
836 | } | ||
837 | |||
838 | //get strip header without changing the scratch_read_ptr | ||
839 | scratch_set_extra_ptr(usbvision, &StripPtr, 0); | ||
840 | scratch_get_extra(usbvision, &StripHeader[0], &StripPtr, | ||
841 | USBVISION_STRIP_HEADER_LEN); | ||
842 | |||
843 | if (StripHeader[0] != USBVISION_STRIP_MAGIC) { | ||
844 | // wrong strip magic | ||
845 | usbvision->stripMagicErrors++; | ||
846 | return ParseState_NextFrame; | ||
847 | } | ||
848 | |||
849 | if (frame->curline != (int)StripHeader[2]) { | ||
850 | //line number missmatch error | ||
851 | usbvision->stripLineNumberErrors++; | ||
852 | } | ||
853 | |||
854 | StripLen = 2 * (unsigned int)StripHeader[1]; | ||
855 | if (StripLen > USBVISION_STRIP_LEN_MAX) { | ||
856 | // strip overrun | ||
857 | // I think this never happens | ||
858 | usbvision_request_intra(usbvision); | ||
859 | } | ||
860 | |||
861 | if (scratch_len(usbvision) < StripLen) { | ||
862 | //there is not enough data for the strip | ||
863 | return ParseState_Out; | ||
864 | } | ||
865 | |||
866 | if (usbvision->IntraFrameBuffer) { | ||
867 | Y = usbvision->IntraFrameBuffer + frame->frmwidth * frame->curline; | ||
868 | U = usbvision->IntraFrameBuffer + imageSize + (frame->frmwidth / 2) * (frame->curline / 2); | ||
869 | V = usbvision->IntraFrameBuffer + imageSize / 4 * 5 + (frame->frmwidth / 2) * (frame->curline / 2); | ||
870 | } | ||
871 | else { | ||
872 | return ParseState_NextFrame; | ||
873 | } | ||
874 | |||
875 | bytes_per_pixel = frame->v4l2_format.bytes_per_pixel; | ||
876 | clipmask_index = frame->curline * MAX_FRAME_WIDTH; | ||
877 | |||
878 | scratch_get(usbvision, StripData, StripLen); | ||
879 | |||
880 | IdxEnd = frame->frmwidth; | ||
881 | BlockTypePos = USBVISION_STRIP_HEADER_LEN; | ||
882 | StartBlockPos = BlockTypePos + (IdxEnd - 1) / 96 + (IdxEnd / 2 - 1) / 96 + 2; | ||
883 | BlockPos = StartBlockPos; | ||
884 | |||
885 | usbvision->BlockPos = BlockPos; | ||
886 | |||
887 | if ((rc = usbvision_decompress(usbvision, StripData, Y, &BlockPos, &BlockTypePos, IdxEnd)) != IdxEnd) { | ||
888 | //return ParseState_Continue; | ||
889 | } | ||
890 | if (StripLen > usbvision->maxStripLen) { | ||
891 | usbvision->maxStripLen = StripLen; | ||
892 | } | ||
893 | |||
894 | if (frame->curline%2) { | ||
895 | if ((rc = usbvision_decompress(usbvision, StripData, V, &BlockPos, &BlockTypePos, IdxEnd/2)) != IdxEnd/2) { | ||
896 | //return ParseState_Continue; | ||
897 | } | ||
898 | } | ||
899 | else { | ||
900 | if ((rc = usbvision_decompress(usbvision, StripData, U, &BlockPos, &BlockTypePos, IdxEnd/2)) != IdxEnd/2) { | ||
901 | //return ParseState_Continue; | ||
902 | } | ||
903 | } | ||
904 | |||
905 | if (BlockPos > usbvision->comprBlockPos) { | ||
906 | usbvision->comprBlockPos = BlockPos; | ||
907 | } | ||
908 | if (BlockPos > StripLen) { | ||
909 | usbvision->stripLenErrors++; | ||
910 | } | ||
911 | |||
912 | for (Idx = 0; Idx < IdxEnd; Idx++) { | ||
913 | if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { | ||
914 | *f++ = Y[Idx]; | ||
915 | *f++ = Idx & 0x01 ? U[Idx/2] : V[Idx/2]; | ||
916 | } | ||
917 | else if(frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) { | ||
918 | *f++ = Y[Idx]; | ||
919 | if ( Idx & 0x01) | ||
920 | *u++ = U[Idx>>1] ; | ||
921 | else | ||
922 | *v++ = V[Idx>>1]; | ||
923 | } | ||
924 | else if (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) { | ||
925 | *f++ = Y [Idx]; | ||
926 | if ( !(( Idx & 0x01 ) | ( frame->curline & 0x01 )) ){ | ||
927 | |||
928 | /* only need do this for 1 in 4 pixels */ | ||
929 | /* intraframe buffer is YUV420 format */ | ||
930 | |||
931 | *u++ = U[Idx >>1]; | ||
932 | *v++ = V[Idx >>1]; | ||
933 | } | ||
934 | |||
935 | } | ||
936 | else { | ||
937 | YUV_TO_RGB_BY_THE_BOOK(Y[Idx], U[Idx/2], V[Idx/2], rv, gv, bv); | ||
938 | switch (frame->v4l2_format.format) { | ||
939 | case V4L2_PIX_FMT_GREY: | ||
940 | *f++ = Y[Idx]; | ||
941 | break; | ||
942 | case V4L2_PIX_FMT_RGB555: | ||
943 | *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 2)); | ||
944 | *f++ = (0x03 & (gv >> 6)) | (0x7C & (rv >> 1)); | ||
945 | break; | ||
946 | case V4L2_PIX_FMT_RGB565: | ||
947 | *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 3)); | ||
948 | *f++ = (0x07 & (gv >> 5)) | (0xF8 & rv); | ||
949 | break; | ||
950 | case V4L2_PIX_FMT_RGB24: | ||
951 | *f++ = bv; | ||
952 | *f++ = gv; | ||
953 | *f++ = rv; | ||
954 | break; | ||
955 | case V4L2_PIX_FMT_RGB32: | ||
956 | *f++ = bv; | ||
957 | *f++ = gv; | ||
958 | *f++ = rv; | ||
959 | f++; | ||
960 | break; | ||
961 | } | ||
962 | } | ||
963 | clipmask_index++; | ||
964 | } | ||
965 | /* Deal with non-integer no. of bytes for YUV420P */ | ||
966 | if (frame->v4l2_format.format != V4L2_PIX_FMT_YVU420 ) | ||
967 | *pcopylen += frame->v4l2_linesize; | ||
968 | else | ||
969 | *pcopylen += frame->curline & 0x01 ? frame->v4l2_linesize : frame->v4l2_linesize << 1; | ||
970 | |||
971 | frame->curline += 1; | ||
972 | |||
973 | if (frame->curline >= frame->frmheight) { | ||
974 | return ParseState_NextFrame; | ||
975 | } | ||
976 | else { | ||
977 | return ParseState_Continue; | ||
978 | } | ||
979 | |||
980 | } | ||
981 | |||
982 | |||
983 | /* | ||
984 | * usbvision_parse_lines_420() | ||
985 | * | ||
986 | * Parse two lines from the scratch buffer, put | ||
987 | * decoded RGB value into the current frame buffer and add the written | ||
988 | * number of bytes (RGB) to the *pcopylen. | ||
989 | * | ||
990 | */ | ||
991 | static enum ParseState usbvision_parse_lines_420(struct usb_usbvision *usbvision, | ||
992 | long *pcopylen) | ||
993 | { | ||
994 | struct usbvision_frame *frame; | ||
995 | unsigned char *f_even = NULL, *f_odd = NULL; | ||
996 | unsigned int pixel_per_line, block; | ||
997 | int pixel, block_split; | ||
998 | int y_ptr, u_ptr, v_ptr, y_odd_offset; | ||
999 | const int y_block_size = 128; | ||
1000 | const int uv_block_size = 64; | ||
1001 | const int sub_block_size = 32; | ||
1002 | const int y_step[] = { 0, 0, 0, 2 }, y_step_size = 4; | ||
1003 | const int uv_step[]= { 0, 0, 0, 4 }, uv_step_size = 4; | ||
1004 | unsigned char y[2], u, v; /* YUV components */ | ||
1005 | int y_, u_, v_, vb, uvg, ur; | ||
1006 | int r_, g_, b_; /* RGB components */ | ||
1007 | unsigned char g; | ||
1008 | int clipmask_even_index, clipmask_odd_index, bytes_per_pixel; | ||
1009 | int clipmask_add, stretch_bytes; | ||
1010 | |||
1011 | frame = usbvision->curFrame; | ||
1012 | f_even = frame->data + (frame->v4l2_linesize * frame->curline); | ||
1013 | f_odd = f_even + frame->v4l2_linesize * usbvision->stretch_height; | ||
1014 | |||
1015 | /* Make sure there's enough data for the entire line */ | ||
1016 | /* In this mode usbvision transfer 3 bytes for every 2 pixels */ | ||
1017 | /* I need two lines to decode the color */ | ||
1018 | bytes_per_pixel = frame->v4l2_format.bytes_per_pixel; | ||
1019 | stretch_bytes = (usbvision->stretch_width - 1) * bytes_per_pixel; | ||
1020 | clipmask_even_index = frame->curline * MAX_FRAME_WIDTH; | ||
1021 | clipmask_odd_index = clipmask_even_index + MAX_FRAME_WIDTH; | ||
1022 | clipmask_add = usbvision->stretch_width; | ||
1023 | pixel_per_line = frame->isocHeader.frameWidth; | ||
1024 | |||
1025 | if (scratch_len(usbvision) < (int)pixel_per_line * 3) { | ||
1026 | //printk(KERN_DEBUG "out of data, need %d\n", len); | ||
1027 | return ParseState_Out; | ||
1028 | } | ||
1029 | |||
1030 | if ((frame->curline + 1) >= frame->frmheight) { | ||
1031 | return ParseState_NextFrame; | ||
1032 | } | ||
1033 | |||
1034 | block_split = (pixel_per_line%y_block_size) ? 1 : 0; //are some blocks splitted into different lines? | ||
1035 | |||
1036 | y_odd_offset = (pixel_per_line / y_block_size) * (y_block_size + uv_block_size) | ||
1037 | + block_split * uv_block_size; | ||
1038 | |||
1039 | scratch_set_extra_ptr(usbvision, &y_ptr, y_odd_offset); | ||
1040 | scratch_set_extra_ptr(usbvision, &u_ptr, y_block_size); | ||
1041 | scratch_set_extra_ptr(usbvision, &v_ptr, y_odd_offset | ||
1042 | + (4 - block_split) * sub_block_size); | ||
1043 | |||
1044 | for (block = 0; block < (pixel_per_line / sub_block_size); | ||
1045 | block++) { | ||
1046 | |||
1047 | |||
1048 | for (pixel = 0; pixel < sub_block_size; pixel +=2) { | ||
1049 | scratch_get(usbvision, &y[0], 2); | ||
1050 | scratch_get_extra(usbvision, &u, &u_ptr, 1); | ||
1051 | scratch_get_extra(usbvision, &v, &v_ptr, 1); | ||
1052 | |||
1053 | //I don't use the YUV_TO_RGB macro for better performance | ||
1054 | v_ = v - 128; | ||
1055 | u_ = u - 128; | ||
1056 | vb = 132252 * v_; | ||
1057 | uvg= -53281 * u_ - 25625 * v_; | ||
1058 | ur = 104595 * u_; | ||
1059 | |||
1060 | if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { | ||
1061 | *f_even++ = y[0]; | ||
1062 | *f_even++ = v; | ||
1063 | } | ||
1064 | else { | ||
1065 | y_ = 76284 * (y[0] - 16); | ||
1066 | |||
1067 | b_ = (y_ + vb) >> 16; | ||
1068 | g_ = (y_ + uvg)>> 16; | ||
1069 | r_ = (y_ + ur) >> 16; | ||
1070 | |||
1071 | switch (frame->v4l2_format.format) { | ||
1072 | case V4L2_PIX_FMT_RGB565: | ||
1073 | g = LIMIT_RGB(g_); | ||
1074 | *f_even++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 3)); | ||
1075 | *f_even++ = (0x07 & ( g >> 5)) | (0xF8 & LIMIT_RGB(r_)); | ||
1076 | break; | ||
1077 | case V4L2_PIX_FMT_RGB24: | ||
1078 | *f_even++ = LIMIT_RGB(b_); | ||
1079 | *f_even++ = LIMIT_RGB(g_); | ||
1080 | *f_even++ = LIMIT_RGB(r_); | ||
1081 | break; | ||
1082 | case V4L2_PIX_FMT_RGB32: | ||
1083 | *f_even++ = LIMIT_RGB(b_); | ||
1084 | *f_even++ = LIMIT_RGB(g_); | ||
1085 | *f_even++ = LIMIT_RGB(r_); | ||
1086 | f_even++; | ||
1087 | break; | ||
1088 | case V4L2_PIX_FMT_RGB555: | ||
1089 | g = LIMIT_RGB(g_); | ||
1090 | *f_even++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 2)); | ||
1091 | *f_even++ = (0x03 & ( g >> 6)) | | ||
1092 | (0x7C & (LIMIT_RGB(r_) >> 1)); | ||
1093 | break; | ||
1094 | } | ||
1095 | } | ||
1096 | clipmask_even_index += clipmask_add; | ||
1097 | f_even += stretch_bytes; | ||
1098 | |||
1099 | if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { | ||
1100 | *f_even++ = y[1]; | ||
1101 | *f_even++ = u; | ||
1102 | } | ||
1103 | else { | ||
1104 | y_ = 76284 * (y[1] - 16); | ||
1105 | |||
1106 | b_ = (y_ + vb) >> 16; | ||
1107 | g_ = (y_ + uvg)>> 16; | ||
1108 | r_ = (y_ + ur) >> 16; | ||
1109 | |||
1110 | switch (frame->v4l2_format.format) { | ||
1111 | case V4L2_PIX_FMT_RGB565: | ||
1112 | g = LIMIT_RGB(g_); | ||
1113 | *f_even++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 3)); | ||
1114 | *f_even++ = (0x07 & ( g >> 5)) | (0xF8 & LIMIT_RGB(r_)); | ||
1115 | break; | ||
1116 | case V4L2_PIX_FMT_RGB24: | ||
1117 | *f_even++ = LIMIT_RGB(b_); | ||
1118 | *f_even++ = LIMIT_RGB(g_); | ||
1119 | *f_even++ = LIMIT_RGB(r_); | ||
1120 | break; | ||
1121 | case V4L2_PIX_FMT_RGB32: | ||
1122 | *f_even++ = LIMIT_RGB(b_); | ||
1123 | *f_even++ = LIMIT_RGB(g_); | ||
1124 | *f_even++ = LIMIT_RGB(r_); | ||
1125 | f_even++; | ||
1126 | break; | ||
1127 | case V4L2_PIX_FMT_RGB555: | ||
1128 | g = LIMIT_RGB(g_); | ||
1129 | *f_even++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 2)); | ||
1130 | *f_even++ = (0x03 & ( g >> 6)) | | ||
1131 | (0x7C & (LIMIT_RGB(r_) >> 1)); | ||
1132 | break; | ||
1133 | } | ||
1134 | } | ||
1135 | clipmask_even_index += clipmask_add; | ||
1136 | f_even += stretch_bytes; | ||
1137 | |||
1138 | scratch_get_extra(usbvision, &y[0], &y_ptr, 2); | ||
1139 | |||
1140 | if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { | ||
1141 | *f_odd++ = y[0]; | ||
1142 | *f_odd++ = v; | ||
1143 | } | ||
1144 | else { | ||
1145 | y_ = 76284 * (y[0] - 16); | ||
1146 | |||
1147 | b_ = (y_ + vb) >> 16; | ||
1148 | g_ = (y_ + uvg)>> 16; | ||
1149 | r_ = (y_ + ur) >> 16; | ||
1150 | |||
1151 | switch (frame->v4l2_format.format) { | ||
1152 | case V4L2_PIX_FMT_RGB565: | ||
1153 | g = LIMIT_RGB(g_); | ||
1154 | *f_odd++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 3)); | ||
1155 | *f_odd++ = (0x07 & ( g >> 5)) | (0xF8 & LIMIT_RGB(r_)); | ||
1156 | break; | ||
1157 | case V4L2_PIX_FMT_RGB24: | ||
1158 | *f_odd++ = LIMIT_RGB(b_); | ||
1159 | *f_odd++ = LIMIT_RGB(g_); | ||
1160 | *f_odd++ = LIMIT_RGB(r_); | ||
1161 | break; | ||
1162 | case V4L2_PIX_FMT_RGB32: | ||
1163 | *f_odd++ = LIMIT_RGB(b_); | ||
1164 | *f_odd++ = LIMIT_RGB(g_); | ||
1165 | *f_odd++ = LIMIT_RGB(r_); | ||
1166 | f_odd++; | ||
1167 | break; | ||
1168 | case V4L2_PIX_FMT_RGB555: | ||
1169 | g = LIMIT_RGB(g_); | ||
1170 | *f_odd++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 2)); | ||
1171 | *f_odd++ = (0x03 & ( g >> 6)) | | ||
1172 | (0x7C & (LIMIT_RGB(r_) >> 1)); | ||
1173 | break; | ||
1174 | } | ||
1175 | } | ||
1176 | clipmask_odd_index += clipmask_add; | ||
1177 | f_odd += stretch_bytes; | ||
1178 | |||
1179 | if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { | ||
1180 | *f_odd++ = y[1]; | ||
1181 | *f_odd++ = u; | ||
1182 | } | ||
1183 | else { | ||
1184 | y_ = 76284 * (y[1] - 16); | ||
1185 | |||
1186 | b_ = (y_ + vb) >> 16; | ||
1187 | g_ = (y_ + uvg)>> 16; | ||
1188 | r_ = (y_ + ur) >> 16; | ||
1189 | |||
1190 | switch (frame->v4l2_format.format) { | ||
1191 | case V4L2_PIX_FMT_RGB565: | ||
1192 | g = LIMIT_RGB(g_); | ||
1193 | *f_odd++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 3)); | ||
1194 | *f_odd++ = (0x07 & ( g >> 5)) | (0xF8 & LIMIT_RGB(r_)); | ||
1195 | break; | ||
1196 | case V4L2_PIX_FMT_RGB24: | ||
1197 | *f_odd++ = LIMIT_RGB(b_); | ||
1198 | *f_odd++ = LIMIT_RGB(g_); | ||
1199 | *f_odd++ = LIMIT_RGB(r_); | ||
1200 | break; | ||
1201 | case V4L2_PIX_FMT_RGB32: | ||
1202 | *f_odd++ = LIMIT_RGB(b_); | ||
1203 | *f_odd++ = LIMIT_RGB(g_); | ||
1204 | *f_odd++ = LIMIT_RGB(r_); | ||
1205 | f_odd++; | ||
1206 | break; | ||
1207 | case V4L2_PIX_FMT_RGB555: | ||
1208 | g = LIMIT_RGB(g_); | ||
1209 | *f_odd++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 2)); | ||
1210 | *f_odd++ = (0x03 & ( g >> 6)) | | ||
1211 | (0x7C & (LIMIT_RGB(r_) >> 1)); | ||
1212 | break; | ||
1213 | } | ||
1214 | } | ||
1215 | clipmask_odd_index += clipmask_add; | ||
1216 | f_odd += stretch_bytes; | ||
1217 | } | ||
1218 | |||
1219 | scratch_rm_old(usbvision,y_step[block % y_step_size] * sub_block_size); | ||
1220 | scratch_inc_extra_ptr(&y_ptr, y_step[(block + 2 * block_split) % y_step_size] | ||
1221 | * sub_block_size); | ||
1222 | scratch_inc_extra_ptr(&u_ptr, uv_step[block % uv_step_size] | ||
1223 | * sub_block_size); | ||
1224 | scratch_inc_extra_ptr(&v_ptr, uv_step[(block + 2 * block_split) % uv_step_size] | ||
1225 | * sub_block_size); | ||
1226 | } | ||
1227 | |||
1228 | scratch_rm_old(usbvision, pixel_per_line * 3 / 2 | ||
1229 | + block_split * sub_block_size); | ||
1230 | |||
1231 | frame->curline += 2 * usbvision->stretch_height; | ||
1232 | *pcopylen += frame->v4l2_linesize * 2 * usbvision->stretch_height; | ||
1233 | |||
1234 | if (frame->curline >= frame->frmheight) | ||
1235 | return ParseState_NextFrame; | ||
1236 | else | ||
1237 | return ParseState_Continue; | ||
1238 | } | ||
1239 | |||
1240 | /* | ||
1241 | * usbvision_parse_data() | ||
1242 | * | ||
1243 | * Generic routine to parse the scratch buffer. It employs either | ||
1244 | * usbvision_find_header() or usbvision_parse_lines() to do most | ||
1245 | * of work. | ||
1246 | * | ||
1247 | */ | ||
1248 | static void usbvision_parse_data(struct usb_usbvision *usbvision) | ||
1249 | { | ||
1250 | struct usbvision_frame *frame; | ||
1251 | enum ParseState newstate; | ||
1252 | long copylen = 0; | ||
1253 | unsigned long lock_flags; | ||
1254 | |||
1255 | frame = usbvision->curFrame; | ||
1256 | |||
1257 | PDEBUG(DBG_PARSE, "parsing len=%d\n", scratch_len(usbvision)); | ||
1258 | |||
1259 | while (1) { | ||
1260 | |||
1261 | newstate = ParseState_Out; | ||
1262 | if (scratch_len(usbvision)) { | ||
1263 | if (frame->scanstate == ScanState_Scanning) { | ||
1264 | newstate = usbvision_find_header(usbvision); | ||
1265 | } | ||
1266 | else if (frame->scanstate == ScanState_Lines) { | ||
1267 | if (usbvision->isocMode == ISOC_MODE_YUV420) { | ||
1268 | newstate = usbvision_parse_lines_420(usbvision, ©len); | ||
1269 | } | ||
1270 | else if (usbvision->isocMode == ISOC_MODE_YUV422) { | ||
1271 | newstate = usbvision_parse_lines_422(usbvision, ©len); | ||
1272 | } | ||
1273 | else if (usbvision->isocMode == ISOC_MODE_COMPRESS) { | ||
1274 | newstate = usbvision_parse_compress(usbvision, ©len); | ||
1275 | } | ||
1276 | |||
1277 | } | ||
1278 | } | ||
1279 | if (newstate == ParseState_Continue) { | ||
1280 | continue; | ||
1281 | } | ||
1282 | else if ((newstate == ParseState_NextFrame) || (newstate == ParseState_Out)) { | ||
1283 | break; | ||
1284 | } | ||
1285 | else { | ||
1286 | return; /* ParseState_EndParse */ | ||
1287 | } | ||
1288 | } | ||
1289 | |||
1290 | if (newstate == ParseState_NextFrame) { | ||
1291 | frame->grabstate = FrameState_Done; | ||
1292 | do_gettimeofday(&(frame->timestamp)); | ||
1293 | frame->sequence = usbvision->frame_num; | ||
1294 | |||
1295 | spin_lock_irqsave(&usbvision->queue_lock, lock_flags); | ||
1296 | list_move_tail(&(frame->frame), &usbvision->outqueue); | ||
1297 | usbvision->curFrame = NULL; | ||
1298 | spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); | ||
1299 | |||
1300 | usbvision->frame_num++; | ||
1301 | |||
1302 | /* This will cause the process to request another frame. */ | ||
1303 | if (waitqueue_active(&usbvision->wait_frame)) { | ||
1304 | PDEBUG(DBG_PARSE, "Wake up !"); | ||
1305 | wake_up_interruptible(&usbvision->wait_frame); | ||
1306 | } | ||
1307 | } | ||
1308 | else | ||
1309 | frame->grabstate = FrameState_Grabbing; | ||
1310 | |||
1311 | |||
1312 | /* Update the frame's uncompressed length. */ | ||
1313 | frame->scanlength += copylen; | ||
1314 | } | ||
1315 | |||
1316 | |||
1317 | /* | ||
1318 | * Make all of the blocks of data contiguous | ||
1319 | */ | ||
1320 | static int usbvision_compress_isochronous(struct usb_usbvision *usbvision, | ||
1321 | struct urb *urb) | ||
1322 | { | ||
1323 | unsigned char *packet_data; | ||
1324 | int i, totlen = 0; | ||
1325 | |||
1326 | for (i = 0; i < urb->number_of_packets; i++) { | ||
1327 | int packet_len = urb->iso_frame_desc[i].actual_length; | ||
1328 | int packet_stat = urb->iso_frame_desc[i].status; | ||
1329 | |||
1330 | packet_data = urb->transfer_buffer + urb->iso_frame_desc[i].offset; | ||
1331 | |||
1332 | /* Detect and ignore errored packets */ | ||
1333 | if (packet_stat) { // packet_stat != 0 ????????????? | ||
1334 | PDEBUG(DBG_ISOC, "data error: [%d] len=%d, status=%X", i, packet_len, packet_stat); | ||
1335 | usbvision->isocErrCount++; | ||
1336 | continue; | ||
1337 | } | ||
1338 | |||
1339 | /* Detect and ignore empty packets */ | ||
1340 | if (packet_len < 0) { | ||
1341 | PDEBUG(DBG_ISOC, "error packet [%d]", i); | ||
1342 | usbvision->isocSkipCount++; | ||
1343 | continue; | ||
1344 | } | ||
1345 | else if (packet_len == 0) { /* Frame end ????? */ | ||
1346 | PDEBUG(DBG_ISOC, "null packet [%d]", i); | ||
1347 | usbvision->isocstate=IsocState_NoFrame; | ||
1348 | usbvision->isocSkipCount++; | ||
1349 | continue; | ||
1350 | } | ||
1351 | else if (packet_len > usbvision->isocPacketSize) { | ||
1352 | PDEBUG(DBG_ISOC, "packet[%d] > isocPacketSize", i); | ||
1353 | usbvision->isocSkipCount++; | ||
1354 | continue; | ||
1355 | } | ||
1356 | |||
1357 | PDEBUG(DBG_ISOC, "packet ok [%d] len=%d", i, packet_len); | ||
1358 | |||
1359 | if (usbvision->isocstate==IsocState_NoFrame) { //new frame begins | ||
1360 | usbvision->isocstate=IsocState_InFrame; | ||
1361 | scratch_mark_header(usbvision); | ||
1362 | usbvision_measure_bandwidth(usbvision); | ||
1363 | PDEBUG(DBG_ISOC, "packet with header"); | ||
1364 | } | ||
1365 | |||
1366 | /* | ||
1367 | * If usbvision continues to feed us with data but there is no | ||
1368 | * consumption (if, for example, V4L client fell asleep) we | ||
1369 | * may overflow the buffer. We have to move old data over to | ||
1370 | * free room for new data. This is bad for old data. If we | ||
1371 | * just drop new data then it's bad for new data... choose | ||
1372 | * your favorite evil here. | ||
1373 | */ | ||
1374 | if (scratch_free(usbvision) < packet_len) { | ||
1375 | |||
1376 | usbvision->scratch_ovf_count++; | ||
1377 | PDEBUG(DBG_ISOC, "scratch buf overflow! scr_len: %d, n: %d", | ||
1378 | scratch_len(usbvision), packet_len); | ||
1379 | scratch_rm_old(usbvision, packet_len - scratch_free(usbvision)); | ||
1380 | } | ||
1381 | |||
1382 | /* Now we know that there is enough room in scratch buffer */ | ||
1383 | scratch_put(usbvision, packet_data, packet_len); | ||
1384 | totlen += packet_len; | ||
1385 | usbvision->isocDataCount += packet_len; | ||
1386 | usbvision->isocPacketCount++; | ||
1387 | } | ||
1388 | #if ENABLE_HEXDUMP | ||
1389 | if (totlen > 0) { | ||
1390 | static int foo = 0; | ||
1391 | if (foo < 1) { | ||
1392 | printk(KERN_DEBUG "+%d.\n", usbvision->scratchlen); | ||
1393 | usbvision_hexdump(data0, (totlen > 64) ? 64 : totlen); | ||
1394 | ++foo; | ||
1395 | } | ||
1396 | } | ||
1397 | #endif | ||
1398 | return totlen; | ||
1399 | } | ||
1400 | |||
1401 | static void usbvision_isocIrq(struct urb *urb) | ||
1402 | { | ||
1403 | int errCode = 0; | ||
1404 | int len; | ||
1405 | struct usb_usbvision *usbvision = urb->context; | ||
1406 | int i; | ||
1407 | unsigned long startTime = jiffies; | ||
1408 | struct usbvision_frame **f; | ||
1409 | |||
1410 | /* We don't want to do anything if we are about to be removed! */ | ||
1411 | if (!USBVISION_IS_OPERATIONAL(usbvision)) | ||
1412 | return; | ||
1413 | |||
1414 | f = &usbvision->curFrame; | ||
1415 | |||
1416 | /* Manage streaming interruption */ | ||
1417 | if (usbvision->streaming == Stream_Interrupt) { | ||
1418 | usbvision->streaming = Stream_Idle; | ||
1419 | if ((*f)) { | ||
1420 | (*f)->grabstate = FrameState_Ready; | ||
1421 | (*f)->scanstate = ScanState_Scanning; | ||
1422 | } | ||
1423 | PDEBUG(DBG_IRQ, "stream interrupted"); | ||
1424 | wake_up_interruptible(&usbvision->wait_stream); | ||
1425 | } | ||
1426 | |||
1427 | /* Copy the data received into our scratch buffer */ | ||
1428 | len = usbvision_compress_isochronous(usbvision, urb); | ||
1429 | |||
1430 | usbvision->isocUrbCount++; | ||
1431 | usbvision->urb_length = len; | ||
1432 | |||
1433 | if (usbvision->streaming == Stream_On) { | ||
1434 | |||
1435 | /* If we collected enough data let's parse! */ | ||
1436 | if (scratch_len(usbvision) > USBVISION_HEADER_LENGTH) { /* 12 == header_length */ | ||
1437 | /*If we don't have a frame we're current working on, complain */ | ||
1438 | if(!list_empty(&(usbvision->inqueue))) { | ||
1439 | if (!(*f)) { | ||
1440 | (*f) = list_entry(usbvision->inqueue.next,struct usbvision_frame, frame); | ||
1441 | } | ||
1442 | usbvision_parse_data(usbvision); | ||
1443 | } | ||
1444 | else { | ||
1445 | PDEBUG(DBG_IRQ, "received data, but no one needs it"); | ||
1446 | scratch_reset(usbvision); | ||
1447 | } | ||
1448 | } | ||
1449 | } | ||
1450 | else { | ||
1451 | PDEBUG(DBG_IRQ, "received data, but no one needs it"); | ||
1452 | scratch_reset(usbvision); | ||
1453 | } | ||
1454 | |||
1455 | usbvision->timeInIrq += jiffies - startTime; | ||
1456 | |||
1457 | for (i = 0; i < USBVISION_URB_FRAMES; i++) { | ||
1458 | urb->iso_frame_desc[i].status = 0; | ||
1459 | urb->iso_frame_desc[i].actual_length = 0; | ||
1460 | } | ||
1461 | |||
1462 | urb->status = 0; | ||
1463 | urb->dev = usbvision->dev; | ||
1464 | errCode = usb_submit_urb (urb, GFP_ATOMIC); | ||
1465 | |||
1466 | /* Disable this warning. By design of the driver. */ | ||
1467 | // if(errCode) { | ||
1468 | // err("%s: usb_submit_urb failed: error %d", __FUNCTION__, errCode); | ||
1469 | // } | ||
1470 | |||
1471 | return; | ||
1472 | } | ||
1473 | |||
1474 | /*************************************/ | ||
1475 | /* Low level usbvision access functions */ | ||
1476 | /*************************************/ | ||
1477 | |||
1478 | /* | ||
1479 | * usbvision_read_reg() | ||
1480 | * | ||
1481 | * return < 0 -> Error | ||
1482 | * >= 0 -> Data | ||
1483 | */ | ||
1484 | |||
1485 | int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg) | ||
1486 | { | ||
1487 | int errCode = 0; | ||
1488 | unsigned char buffer[1]; | ||
1489 | |||
1490 | if (!USBVISION_IS_OPERATIONAL(usbvision)) | ||
1491 | return -1; | ||
1492 | |||
1493 | errCode = usb_control_msg(usbvision->dev, usb_rcvctrlpipe(usbvision->dev, 1), | ||
1494 | USBVISION_OP_CODE, | ||
1495 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, | ||
1496 | 0, (__u16) reg, buffer, 1, HZ); | ||
1497 | |||
1498 | if (errCode < 0) { | ||
1499 | err("%s: failed: error %d", __FUNCTION__, errCode); | ||
1500 | return errCode; | ||
1501 | } | ||
1502 | return buffer[0]; | ||
1503 | } | ||
1504 | |||
1505 | /* | ||
1506 | * usbvision_write_reg() | ||
1507 | * | ||
1508 | * return 1 -> Reg written | ||
1509 | * 0 -> usbvision is not yet ready | ||
1510 | * -1 -> Something went wrong | ||
1511 | */ | ||
1512 | |||
1513 | int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg, | ||
1514 | unsigned char value) | ||
1515 | { | ||
1516 | int errCode = 0; | ||
1517 | |||
1518 | if (!USBVISION_IS_OPERATIONAL(usbvision)) | ||
1519 | return 0; | ||
1520 | |||
1521 | errCode = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), | ||
1522 | USBVISION_OP_CODE, | ||
1523 | USB_DIR_OUT | USB_TYPE_VENDOR | | ||
1524 | USB_RECIP_ENDPOINT, 0, (__u16) reg, &value, 1, HZ); | ||
1525 | |||
1526 | if (errCode < 0) { | ||
1527 | err("%s: failed: error %d", __FUNCTION__, errCode); | ||
1528 | } | ||
1529 | return errCode; | ||
1530 | } | ||
1531 | |||
1532 | |||
1533 | static void usbvision_ctrlUrb_complete(struct urb *urb) | ||
1534 | { | ||
1535 | struct usb_usbvision *usbvision = (struct usb_usbvision *)urb->context; | ||
1536 | |||
1537 | PDEBUG(DBG_IRQ, ""); | ||
1538 | usbvision->ctrlUrbBusy = 0; | ||
1539 | if (waitqueue_active(&usbvision->ctrlUrb_wq)) { | ||
1540 | wake_up_interruptible(&usbvision->ctrlUrb_wq); | ||
1541 | } | ||
1542 | } | ||
1543 | |||
1544 | |||
1545 | static int usbvision_write_reg_irq(struct usb_usbvision *usbvision,int address, | ||
1546 | unsigned char *data, int len) | ||
1547 | { | ||
1548 | int errCode = 0; | ||
1549 | |||
1550 | PDEBUG(DBG_IRQ, ""); | ||
1551 | if (len > 8) { | ||
1552 | return -EFAULT; | ||
1553 | } | ||
1554 | // down(&usbvision->ctrlUrbLock); | ||
1555 | if (usbvision->ctrlUrbBusy) { | ||
1556 | // up(&usbvision->ctrlUrbLock); | ||
1557 | return -EBUSY; | ||
1558 | } | ||
1559 | usbvision->ctrlUrbBusy = 1; | ||
1560 | // up(&usbvision->ctrlUrbLock); | ||
1561 | |||
1562 | usbvision->ctrlUrbSetup.bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT; | ||
1563 | usbvision->ctrlUrbSetup.bRequest = USBVISION_OP_CODE; | ||
1564 | usbvision->ctrlUrbSetup.wValue = 0; | ||
1565 | usbvision->ctrlUrbSetup.wIndex = cpu_to_le16(address); | ||
1566 | usbvision->ctrlUrbSetup.wLength = cpu_to_le16(len); | ||
1567 | usb_fill_control_urb (usbvision->ctrlUrb, usbvision->dev, | ||
1568 | usb_sndctrlpipe(usbvision->dev, 1), | ||
1569 | (unsigned char *)&usbvision->ctrlUrbSetup, | ||
1570 | (void *)usbvision->ctrlUrbBuffer, len, | ||
1571 | usbvision_ctrlUrb_complete, | ||
1572 | (void *)usbvision); | ||
1573 | |||
1574 | memcpy(usbvision->ctrlUrbBuffer, data, len); | ||
1575 | |||
1576 | errCode = usb_submit_urb(usbvision->ctrlUrb, GFP_ATOMIC); | ||
1577 | if (errCode < 0) { | ||
1578 | // error in usb_submit_urb() | ||
1579 | usbvision->ctrlUrbBusy = 0; | ||
1580 | } | ||
1581 | PDEBUG(DBG_IRQ, "submit %d byte: error %d", len, errCode); | ||
1582 | return errCode; | ||
1583 | } | ||
1584 | |||
1585 | |||
1586 | static int usbvision_init_compression(struct usb_usbvision *usbvision) | ||
1587 | { | ||
1588 | int errCode = 0; | ||
1589 | |||
1590 | usbvision->lastIsocFrameNum = -1; | ||
1591 | usbvision->isocDataCount = 0; | ||
1592 | usbvision->isocPacketCount = 0; | ||
1593 | usbvision->isocSkipCount = 0; | ||
1594 | usbvision->comprLevel = 50; | ||
1595 | usbvision->lastComprLevel = -1; | ||
1596 | usbvision->isocUrbCount = 0; | ||
1597 | usbvision->requestIntra = 1; | ||
1598 | usbvision->isocMeasureBandwidthCount = 0; | ||
1599 | |||
1600 | return errCode; | ||
1601 | } | ||
1602 | |||
1603 | /* this function measures the used bandwidth since last call | ||
1604 | * return: 0 : no error | ||
1605 | * sets usedBandwidth to 1-100 : 1-100% of full bandwidth resp. to isocPacketSize | ||
1606 | */ | ||
1607 | static int usbvision_measure_bandwidth (struct usb_usbvision *usbvision) | ||
1608 | { | ||
1609 | int errCode = 0; | ||
1610 | |||
1611 | if (usbvision->isocMeasureBandwidthCount < 2) { // this gives an average bandwidth of 3 frames | ||
1612 | usbvision->isocMeasureBandwidthCount++; | ||
1613 | return errCode; | ||
1614 | } | ||
1615 | if ((usbvision->isocPacketSize > 0) && (usbvision->isocPacketCount > 0)) { | ||
1616 | usbvision->usedBandwidth = usbvision->isocDataCount / | ||
1617 | (usbvision->isocPacketCount + usbvision->isocSkipCount) * | ||
1618 | 100 / usbvision->isocPacketSize; | ||
1619 | } | ||
1620 | usbvision->isocMeasureBandwidthCount = 0; | ||
1621 | usbvision->isocDataCount = 0; | ||
1622 | usbvision->isocPacketCount = 0; | ||
1623 | usbvision->isocSkipCount = 0; | ||
1624 | return errCode; | ||
1625 | } | ||
1626 | |||
1627 | static int usbvision_adjust_compression (struct usb_usbvision *usbvision) | ||
1628 | { | ||
1629 | int errCode = 0; | ||
1630 | unsigned char buffer[6]; | ||
1631 | |||
1632 | PDEBUG(DBG_IRQ, ""); | ||
1633 | if ((adjustCompression) && (usbvision->usedBandwidth > 0)) { | ||
1634 | usbvision->comprLevel += (usbvision->usedBandwidth - 90) / 2; | ||
1635 | RESTRICT_TO_RANGE(usbvision->comprLevel, 0, 100); | ||
1636 | if (usbvision->comprLevel != usbvision->lastComprLevel) { | ||
1637 | int distorsion; | ||
1638 | if (usbvision->bridgeType == BRIDGE_NT1004 || usbvision->bridgeType == BRIDGE_NT1005) { | ||
1639 | buffer[0] = (unsigned char)(4 + 16 * usbvision->comprLevel / 100); // PCM Threshold 1 | ||
1640 | buffer[1] = (unsigned char)(4 + 8 * usbvision->comprLevel / 100); // PCM Threshold 2 | ||
1641 | distorsion = 7 + 248 * usbvision->comprLevel / 100; | ||
1642 | buffer[2] = (unsigned char)(distorsion & 0xFF); // Average distorsion Threshold (inter) | ||
1643 | buffer[3] = (unsigned char)(distorsion & 0xFF); // Average distorsion Threshold (intra) | ||
1644 | distorsion = 1 + 42 * usbvision->comprLevel / 100; | ||
1645 | buffer[4] = (unsigned char)(distorsion & 0xFF); // Maximum distorsion Threshold (inter) | ||
1646 | buffer[5] = (unsigned char)(distorsion & 0xFF); // Maximum distorsion Threshold (intra) | ||
1647 | } | ||
1648 | else { //BRIDGE_NT1003 | ||
1649 | buffer[0] = (unsigned char)(4 + 16 * usbvision->comprLevel / 100); // PCM threshold 1 | ||
1650 | buffer[1] = (unsigned char)(4 + 8 * usbvision->comprLevel / 100); // PCM threshold 2 | ||
1651 | distorsion = 2 + 253 * usbvision->comprLevel / 100; | ||
1652 | buffer[2] = (unsigned char)(distorsion & 0xFF); // distorsion threshold bit0-7 | ||
1653 | buffer[3] = 0; //(unsigned char)((distorsion >> 8) & 0x0F); // distorsion threshold bit 8-11 | ||
1654 | distorsion = 0 + 43 * usbvision->comprLevel / 100; | ||
1655 | buffer[4] = (unsigned char)(distorsion & 0xFF); // maximum distorsion bit0-7 | ||
1656 | buffer[5] = 0; //(unsigned char)((distorsion >> 8) & 0x01); // maximum distorsion bit 8 | ||
1657 | } | ||
1658 | errCode = usbvision_write_reg_irq(usbvision, USBVISION_PCM_THR1, buffer, 6); | ||
1659 | if (errCode == 0){ | ||
1660 | PDEBUG(DBG_IRQ, "new compr params %#02x %#02x %#02x %#02x %#02x %#02x", buffer[0], | ||
1661 | buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); | ||
1662 | usbvision->lastComprLevel = usbvision->comprLevel; | ||
1663 | } | ||
1664 | } | ||
1665 | } | ||
1666 | return errCode; | ||
1667 | } | ||
1668 | |||
1669 | static int usbvision_request_intra (struct usb_usbvision *usbvision) | ||
1670 | { | ||
1671 | int errCode = 0; | ||
1672 | unsigned char buffer[1]; | ||
1673 | |||
1674 | PDEBUG(DBG_IRQ, ""); | ||
1675 | usbvision->requestIntra = 1; | ||
1676 | buffer[0] = 1; | ||
1677 | usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1); | ||
1678 | return errCode; | ||
1679 | } | ||
1680 | |||
1681 | static int usbvision_unrequest_intra (struct usb_usbvision *usbvision) | ||
1682 | { | ||
1683 | int errCode = 0; | ||
1684 | unsigned char buffer[1]; | ||
1685 | |||
1686 | PDEBUG(DBG_IRQ, ""); | ||
1687 | usbvision->requestIntra = 0; | ||
1688 | buffer[0] = 0; | ||
1689 | usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1); | ||
1690 | return errCode; | ||
1691 | } | ||
1692 | |||
1693 | /******************************* | ||
1694 | * usbvision utility functions | ||
1695 | *******************************/ | ||
1696 | |||
1697 | int usbvision_power_off(struct usb_usbvision *usbvision) | ||
1698 | { | ||
1699 | int errCode = 0; | ||
1700 | |||
1701 | PDEBUG(DBG_FUNC, ""); | ||
1702 | |||
1703 | errCode = usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN); | ||
1704 | if (errCode == 1) { | ||
1705 | usbvision->power = 0; | ||
1706 | } | ||
1707 | PDEBUG(DBG_FUNC, "%s: errCode %d", (errCode!=1)?"ERROR":"power is off", errCode); | ||
1708 | return errCode; | ||
1709 | } | ||
1710 | |||
1711 | /* | ||
1712 | * usbvision_set_video_format() | ||
1713 | * | ||
1714 | */ | ||
1715 | static int usbvision_set_video_format(struct usb_usbvision *usbvision, int format) | ||
1716 | { | ||
1717 | static const char proc[] = "usbvision_set_video_format"; | ||
1718 | int rc; | ||
1719 | unsigned char value[2]; | ||
1720 | |||
1721 | if (!USBVISION_IS_OPERATIONAL(usbvision)) | ||
1722 | return 0; | ||
1723 | |||
1724 | PDEBUG(DBG_FUNC, "isocMode %#02x", format); | ||
1725 | |||
1726 | if ((format != ISOC_MODE_YUV422) | ||
1727 | && (format != ISOC_MODE_YUV420) | ||
1728 | && (format != ISOC_MODE_COMPRESS)) { | ||
1729 | printk(KERN_ERR "usbvision: unknown video format %02x, using default YUV420", | ||
1730 | format); | ||
1731 | format = ISOC_MODE_YUV420; | ||
1732 | } | ||
1733 | value[0] = 0x0A; //TODO: See the effect of the filter | ||
1734 | value[1] = format; | ||
1735 | rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), | ||
1736 | USBVISION_OP_CODE, | ||
1737 | USB_DIR_OUT | USB_TYPE_VENDOR | | ||
1738 | USB_RECIP_ENDPOINT, 0, | ||
1739 | (__u16) USBVISION_FILT_CONT, value, 2, HZ); | ||
1740 | |||
1741 | if (rc < 0) { | ||
1742 | printk(KERN_ERR "%s: ERROR=%d. USBVISION stopped - " | ||
1743 | "reconnect or reload driver.\n", proc, rc); | ||
1744 | } | ||
1745 | usbvision->isocMode = format; | ||
1746 | return rc; | ||
1747 | } | ||
1748 | |||
1749 | /* | ||
1750 | * usbvision_set_output() | ||
1751 | * | ||
1752 | */ | ||
1753 | |||
1754 | int usbvision_set_output(struct usb_usbvision *usbvision, int width, | ||
1755 | int height) | ||
1756 | { | ||
1757 | int errCode = 0; | ||
1758 | int UsbWidth, UsbHeight; | ||
1759 | unsigned int frameRate=0, frameDrop=0; | ||
1760 | unsigned char value[4]; | ||
1761 | |||
1762 | if (!USBVISION_IS_OPERATIONAL(usbvision)) { | ||
1763 | return 0; | ||
1764 | } | ||
1765 | |||
1766 | if (width > MAX_USB_WIDTH) { | ||
1767 | UsbWidth = width / 2; | ||
1768 | usbvision->stretch_width = 2; | ||
1769 | } | ||
1770 | else { | ||
1771 | UsbWidth = width; | ||
1772 | usbvision->stretch_width = 1; | ||
1773 | } | ||
1774 | |||
1775 | if (height > MAX_USB_HEIGHT) { | ||
1776 | UsbHeight = height / 2; | ||
1777 | usbvision->stretch_height = 2; | ||
1778 | } | ||
1779 | else { | ||
1780 | UsbHeight = height; | ||
1781 | usbvision->stretch_height = 1; | ||
1782 | } | ||
1783 | |||
1784 | RESTRICT_TO_RANGE(UsbWidth, MIN_FRAME_WIDTH, MAX_USB_WIDTH); | ||
1785 | UsbWidth &= ~(MIN_FRAME_WIDTH-1); | ||
1786 | RESTRICT_TO_RANGE(UsbHeight, MIN_FRAME_HEIGHT, MAX_USB_HEIGHT); | ||
1787 | UsbHeight &= ~(1); | ||
1788 | |||
1789 | PDEBUG(DBG_FUNC, "usb %dx%d; screen %dx%d; stretch %dx%d", | ||
1790 | UsbWidth, UsbHeight, width, height, | ||
1791 | usbvision->stretch_width, usbvision->stretch_height); | ||
1792 | |||
1793 | /* I'll not rewrite the same values */ | ||
1794 | if ((UsbWidth != usbvision->curwidth) || (UsbHeight != usbvision->curheight)) { | ||
1795 | value[0] = UsbWidth & 0xff; //LSB | ||
1796 | value[1] = (UsbWidth >> 8) & 0x03; //MSB | ||
1797 | value[2] = UsbHeight & 0xff; //LSB | ||
1798 | value[3] = (UsbHeight >> 8) & 0x03; //MSB | ||
1799 | |||
1800 | errCode = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), | ||
1801 | USBVISION_OP_CODE, | ||
1802 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, | ||
1803 | 0, (__u16) USBVISION_LXSIZE_O, value, 4, HZ); | ||
1804 | |||
1805 | if (errCode < 0) { | ||
1806 | err("%s failed: error %d", __FUNCTION__, errCode); | ||
1807 | return errCode; | ||
1808 | } | ||
1809 | usbvision->curwidth = usbvision->stretch_width * UsbWidth; | ||
1810 | usbvision->curheight = usbvision->stretch_height * UsbHeight; | ||
1811 | } | ||
1812 | |||
1813 | if (usbvision->isocMode == ISOC_MODE_YUV422) { | ||
1814 | frameRate = (usbvision->isocPacketSize * 1000) / (UsbWidth * UsbHeight * 2); | ||
1815 | } | ||
1816 | else if (usbvision->isocMode == ISOC_MODE_YUV420) { | ||
1817 | frameRate = (usbvision->isocPacketSize * 1000) / ((UsbWidth * UsbHeight * 12) / 8); | ||
1818 | } | ||
1819 | else { | ||
1820 | frameRate = FRAMERATE_MAX; | ||
1821 | } | ||
1822 | |||
1823 | if (usbvision->tvnorm->id & V4L2_STD_625_50) { | ||
1824 | frameDrop = frameRate * 32 / 25 - 1; | ||
1825 | } | ||
1826 | else if (usbvision->tvnorm->id & V4L2_STD_525_60) { | ||
1827 | frameDrop = frameRate * 32 / 30 - 1; | ||
1828 | } | ||
1829 | |||
1830 | RESTRICT_TO_RANGE(frameDrop, FRAMERATE_MIN, FRAMERATE_MAX); | ||
1831 | |||
1832 | PDEBUG(DBG_FUNC, "frameRate %d fps, frameDrop %d", frameRate, frameDrop); | ||
1833 | |||
1834 | frameDrop = FRAMERATE_MAX; // We can allow the maximum here, because dropping is controlled | ||
1835 | |||
1836 | /* frameDrop = 7; => framePhase = 1, 5, 9, 13, 17, 21, 25, 0, 4, 8, ... | ||
1837 | => frameSkip = 4; | ||
1838 | => frameRate = (7 + 1) * 25 / 32 = 200 / 32 = 6.25; | ||
1839 | |||
1840 | frameDrop = 9; => framePhase = 1, 5, 8, 11, 14, 17, 21, 24, 27, 1, 4, 8, ... | ||
1841 | => frameSkip = 4, 3, 3, 3, 3, 4, 3, 3, 3, 3, 4, ... | ||
1842 | => frameRate = (9 + 1) * 25 / 32 = 250 / 32 = 7.8125; | ||
1843 | */ | ||
1844 | errCode = usbvision_write_reg(usbvision, USBVISION_FRM_RATE, frameDrop); | ||
1845 | return errCode; | ||
1846 | } | ||
1847 | |||
1848 | |||
1849 | /* | ||
1850 | * usbvision_frames_alloc | ||
1851 | * allocate the maximum frames this driver can manage | ||
1852 | */ | ||
1853 | int usbvision_frames_alloc(struct usb_usbvision *usbvision) | ||
1854 | { | ||
1855 | int i; | ||
1856 | |||
1857 | /* Allocate memory for the frame buffers */ | ||
1858 | usbvision->max_frame_size = MAX_FRAME_SIZE; | ||
1859 | usbvision->fbuf_size = USBVISION_NUMFRAMES * usbvision->max_frame_size; | ||
1860 | usbvision->fbuf = usbvision_rvmalloc(usbvision->fbuf_size); | ||
1861 | |||
1862 | if(usbvision->fbuf == NULL) { | ||
1863 | err("%s: unable to allocate %d bytes for fbuf ", | ||
1864 | __FUNCTION__, usbvision->fbuf_size); | ||
1865 | return -ENOMEM; | ||
1866 | } | ||
1867 | spin_lock_init(&usbvision->queue_lock); | ||
1868 | init_waitqueue_head(&usbvision->wait_frame); | ||
1869 | init_waitqueue_head(&usbvision->wait_stream); | ||
1870 | |||
1871 | /* Allocate all buffers */ | ||
1872 | for (i = 0; i < USBVISION_NUMFRAMES; i++) { | ||
1873 | usbvision->frame[i].index = i; | ||
1874 | usbvision->frame[i].grabstate = FrameState_Unused; | ||
1875 | usbvision->frame[i].data = usbvision->fbuf + | ||
1876 | i * usbvision->max_frame_size; | ||
1877 | /* | ||
1878 | * Set default sizes for read operation. | ||
1879 | */ | ||
1880 | usbvision->stretch_width = 1; | ||
1881 | usbvision->stretch_height = 1; | ||
1882 | usbvision->frame[i].width = usbvision->curwidth; | ||
1883 | usbvision->frame[i].height = usbvision->curheight; | ||
1884 | usbvision->frame[i].bytes_read = 0; | ||
1885 | } | ||
1886 | return 0; | ||
1887 | } | ||
1888 | |||
1889 | /* | ||
1890 | * usbvision_frames_free | ||
1891 | * frees memory allocated for the frames | ||
1892 | */ | ||
1893 | void usbvision_frames_free(struct usb_usbvision *usbvision) | ||
1894 | { | ||
1895 | /* Have to free all that memory */ | ||
1896 | if (usbvision->fbuf != NULL) { | ||
1897 | usbvision_rvfree(usbvision->fbuf, usbvision->fbuf_size); | ||
1898 | usbvision->fbuf = NULL; | ||
1899 | } | ||
1900 | } | ||
1901 | /* | ||
1902 | * usbvision_empty_framequeues() | ||
1903 | * prepare queues for incoming and outgoing frames | ||
1904 | */ | ||
1905 | void usbvision_empty_framequeues(struct usb_usbvision *usbvision) | ||
1906 | { | ||
1907 | u32 i; | ||
1908 | |||
1909 | INIT_LIST_HEAD(&(usbvision->inqueue)); | ||
1910 | INIT_LIST_HEAD(&(usbvision->outqueue)); | ||
1911 | |||
1912 | for (i = 0; i < USBVISION_NUMFRAMES; i++) { | ||
1913 | usbvision->frame[i].grabstate = FrameState_Unused; | ||
1914 | usbvision->frame[i].bytes_read = 0; | ||
1915 | } | ||
1916 | } | ||
1917 | |||
1918 | /* | ||
1919 | * usbvision_stream_interrupt() | ||
1920 | * stops streaming | ||
1921 | */ | ||
1922 | int usbvision_stream_interrupt(struct usb_usbvision *usbvision) | ||
1923 | { | ||
1924 | int ret = 0; | ||
1925 | |||
1926 | /* stop reading from the device */ | ||
1927 | |||
1928 | usbvision->streaming = Stream_Interrupt; | ||
1929 | ret = wait_event_timeout(usbvision->wait_stream, | ||
1930 | (usbvision->streaming == Stream_Idle), | ||
1931 | msecs_to_jiffies(USBVISION_NUMSBUF*USBVISION_URB_FRAMES)); | ||
1932 | return ret; | ||
1933 | } | ||
1934 | |||
1935 | /* | ||
1936 | * usbvision_set_compress_params() | ||
1937 | * | ||
1938 | */ | ||
1939 | |||
1940 | static int usbvision_set_compress_params(struct usb_usbvision *usbvision) | ||
1941 | { | ||
1942 | static const char proc[] = "usbvision_set_compresion_params: "; | ||
1943 | int rc; | ||
1944 | unsigned char value[6]; | ||
1945 | |||
1946 | value[0] = 0x0F; // Intra-Compression cycle | ||
1947 | value[1] = 0x01; // Reg.45 one line per strip | ||
1948 | value[2] = 0x00; // Reg.46 Force intra mode on all new frames | ||
1949 | value[3] = 0x00; // Reg.47 FORCE_UP <- 0 normal operation (not force) | ||
1950 | value[4] = 0xA2; // Reg.48 BUF_THR I'm not sure if this does something in not compressed mode. | ||
1951 | value[5] = 0x00; // Reg.49 DVI_YUV This has nothing to do with compression | ||
1952 | |||
1953 | //catched values for NT1004 | ||
1954 | // value[0] = 0xFF; // Never apply intra mode automatically | ||
1955 | // value[1] = 0xF1; // Use full frame height for virtual strip width; One line per strip | ||
1956 | // value[2] = 0x01; // Force intra mode on all new frames | ||
1957 | // value[3] = 0x00; // Strip size 400 Bytes; do not force up | ||
1958 | // value[4] = 0xA2; // | ||
1959 | if (!USBVISION_IS_OPERATIONAL(usbvision)) | ||
1960 | return 0; | ||
1961 | |||
1962 | rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), | ||
1963 | USBVISION_OP_CODE, | ||
1964 | USB_DIR_OUT | USB_TYPE_VENDOR | | ||
1965 | USB_RECIP_ENDPOINT, 0, | ||
1966 | (__u16) USBVISION_INTRA_CYC, value, 5, HZ); | ||
1967 | |||
1968 | if (rc < 0) { | ||
1969 | printk(KERN_ERR "%sERROR=%d. USBVISION stopped - " | ||
1970 | "reconnect or reload driver.\n", proc, rc); | ||
1971 | return rc; | ||
1972 | } | ||
1973 | |||
1974 | if (usbvision->bridgeType == BRIDGE_NT1004) { | ||
1975 | value[0] = 20; // PCM Threshold 1 | ||
1976 | value[1] = 12; // PCM Threshold 2 | ||
1977 | value[2] = 255; // Distorsion Threshold inter | ||
1978 | value[3] = 255; // Distorsion Threshold intra | ||
1979 | value[4] = 43; // Max Distorsion inter | ||
1980 | value[5] = 43; // Max Distorsion intra | ||
1981 | } | ||
1982 | else { | ||
1983 | value[0] = 20; // PCM Threshold 1 | ||
1984 | value[1] = 12; // PCM Threshold 2 | ||
1985 | value[2] = 255; // Distorsion Threshold d7-d0 | ||
1986 | value[3] = 0; // Distorsion Threshold d11-d8 | ||
1987 | value[4] = 43; // Max Distorsion d7-d0 | ||
1988 | value[5] = 0; // Max Distorsion d8 | ||
1989 | } | ||
1990 | |||
1991 | if (!USBVISION_IS_OPERATIONAL(usbvision)) | ||
1992 | return 0; | ||
1993 | |||
1994 | rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), | ||
1995 | USBVISION_OP_CODE, | ||
1996 | USB_DIR_OUT | USB_TYPE_VENDOR | | ||
1997 | USB_RECIP_ENDPOINT, 0, | ||
1998 | (__u16) USBVISION_PCM_THR1, value, 6, HZ); | ||
1999 | |||
2000 | if (rc < 0) { | ||
2001 | printk(KERN_ERR "%sERROR=%d. USBVISION stopped - " | ||
2002 | "reconnect or reload driver.\n", proc, rc); | ||
2003 | return rc; | ||
2004 | } | ||
2005 | |||
2006 | |||
2007 | return rc; | ||
2008 | } | ||
2009 | |||
2010 | |||
2011 | /* | ||
2012 | * usbvision_set_input() | ||
2013 | * | ||
2014 | * Set the input (saa711x, ...) size x y and other misc input params | ||
2015 | * I've no idea if this parameters are right | ||
2016 | * | ||
2017 | */ | ||
2018 | int usbvision_set_input(struct usb_usbvision *usbvision) | ||
2019 | { | ||
2020 | static const char proc[] = "usbvision_set_input: "; | ||
2021 | int rc; | ||
2022 | unsigned char value[8]; | ||
2023 | unsigned char dvi_yuv_value; | ||
2024 | |||
2025 | if (!USBVISION_IS_OPERATIONAL(usbvision)) | ||
2026 | return 0; | ||
2027 | |||
2028 | /* Set input format expected from decoder*/ | ||
2029 | if (usbvision_device_data[usbvision->DevModel].Vin_Reg1 >= 0) { | ||
2030 | value[0] = usbvision_device_data[usbvision->DevModel].Vin_Reg1 & 0xff; | ||
2031 | } else if(usbvision_device_data[usbvision->DevModel].Codec == CODEC_SAA7113) { | ||
2032 | /* SAA7113 uses 8 bit output */ | ||
2033 | value[0] = USBVISION_8_422_SYNC; | ||
2034 | } else { | ||
2035 | /* I'm sure only about d2-d0 [010] 16 bit 4:2:2 usin sync pulses | ||
2036 | * as that is how saa7111 is configured */ | ||
2037 | value[0] = USBVISION_16_422_SYNC; | ||
2038 | /* | USBVISION_VSNC_POL | USBVISION_VCLK_POL);*/ | ||
2039 | } | ||
2040 | |||
2041 | rc = usbvision_write_reg(usbvision, USBVISION_VIN_REG1, value[0]); | ||
2042 | if (rc < 0) { | ||
2043 | printk(KERN_ERR "%sERROR=%d. USBVISION stopped - " | ||
2044 | "reconnect or reload driver.\n", proc, rc); | ||
2045 | return rc; | ||
2046 | } | ||
2047 | |||
2048 | |||
2049 | if (usbvision->tvnorm->id & V4L2_STD_PAL) { | ||
2050 | value[0] = 0xC0; | ||
2051 | value[1] = 0x02; //0x02C0 -> 704 Input video line length | ||
2052 | value[2] = 0x20; | ||
2053 | value[3] = 0x01; //0x0120 -> 288 Input video n. of lines | ||
2054 | value[4] = 0x60; | ||
2055 | value[5] = 0x00; //0x0060 -> 96 Input video h offset | ||
2056 | value[6] = 0x16; | ||
2057 | value[7] = 0x00; //0x0016 -> 22 Input video v offset | ||
2058 | } else if (usbvision->tvnorm->id & V4L2_STD_SECAM) { | ||
2059 | value[0] = 0xC0; | ||
2060 | value[1] = 0x02; //0x02C0 -> 704 Input video line length | ||
2061 | value[2] = 0x20; | ||
2062 | value[3] = 0x01; //0x0120 -> 288 Input video n. of lines | ||
2063 | value[4] = 0x01; | ||
2064 | value[5] = 0x00; //0x0001 -> 01 Input video h offset | ||
2065 | value[6] = 0x01; | ||
2066 | value[7] = 0x00; //0x0001 -> 01 Input video v offset | ||
2067 | } else { /* V4L2_STD_NTSC */ | ||
2068 | value[0] = 0xD0; | ||
2069 | value[1] = 0x02; //0x02D0 -> 720 Input video line length | ||
2070 | value[2] = 0xF0; | ||
2071 | value[3] = 0x00; //0x00F0 -> 240 Input video number of lines | ||
2072 | value[4] = 0x50; | ||
2073 | value[5] = 0x00; //0x0050 -> 80 Input video h offset | ||
2074 | value[6] = 0x10; | ||
2075 | value[7] = 0x00; //0x0010 -> 16 Input video v offset | ||
2076 | } | ||
2077 | |||
2078 | if (usbvision_device_data[usbvision->DevModel].X_Offset >= 0) { | ||
2079 | value[4]=usbvision_device_data[usbvision->DevModel].X_Offset & 0xff; | ||
2080 | value[5]=(usbvision_device_data[usbvision->DevModel].X_Offset & 0x0300) >> 8; | ||
2081 | } | ||
2082 | |||
2083 | if (usbvision_device_data[usbvision->DevModel].Y_Offset >= 0) { | ||
2084 | value[6]=usbvision_device_data[usbvision->DevModel].Y_Offset & 0xff; | ||
2085 | value[7]=(usbvision_device_data[usbvision->DevModel].Y_Offset & 0x0300) >> 8; | ||
2086 | } | ||
2087 | |||
2088 | rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), | ||
2089 | USBVISION_OP_CODE, /* USBVISION specific code */ | ||
2090 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0, | ||
2091 | (__u16) USBVISION_LXSIZE_I, value, 8, HZ); | ||
2092 | if (rc < 0) { | ||
2093 | printk(KERN_ERR "%sERROR=%d. USBVISION stopped - " | ||
2094 | "reconnect or reload driver.\n", proc, rc); | ||
2095 | return rc; | ||
2096 | } | ||
2097 | |||
2098 | |||
2099 | dvi_yuv_value = 0x00; /* U comes after V, Ya comes after U/V, Yb comes after Yb */ | ||
2100 | |||
2101 | if(usbvision_device_data[usbvision->DevModel].Dvi_yuv >= 0){ | ||
2102 | dvi_yuv_value = usbvision_device_data[usbvision->DevModel].Dvi_yuv & 0xff; | ||
2103 | } | ||
2104 | else if(usbvision_device_data[usbvision->DevModel].Codec == CODEC_SAA7113) { | ||
2105 | /* This changes as the fine sync control changes. Further investigation necessary */ | ||
2106 | dvi_yuv_value = 0x06; | ||
2107 | } | ||
2108 | |||
2109 | return (usbvision_write_reg(usbvision, USBVISION_DVI_YUV, dvi_yuv_value)); | ||
2110 | } | ||
2111 | |||
2112 | |||
2113 | /* | ||
2114 | * usbvision_set_dram_settings() | ||
2115 | * | ||
2116 | * Set the buffer address needed by the usbvision dram to operate | ||
2117 | * This values has been taken with usbsnoop. | ||
2118 | * | ||
2119 | */ | ||
2120 | |||
2121 | static int usbvision_set_dram_settings(struct usb_usbvision *usbvision) | ||
2122 | { | ||
2123 | int rc; | ||
2124 | unsigned char value[8]; | ||
2125 | |||
2126 | if (usbvision->isocMode == ISOC_MODE_COMPRESS) { | ||
2127 | value[0] = 0x42; | ||
2128 | value[1] = 0x71; | ||
2129 | value[2] = 0xff; | ||
2130 | value[3] = 0x00; | ||
2131 | value[4] = 0x98; | ||
2132 | value[5] = 0xe0; | ||
2133 | value[6] = 0x71; | ||
2134 | value[7] = 0xff; | ||
2135 | // UR: 0x0E200-0x3FFFF = 204288 Words (1 Word = 2 Byte) | ||
2136 | // FDL: 0x00000-0x0E099 = 57498 Words | ||
2137 | // VDW: 0x0E3FF-0x3FFFF | ||
2138 | } | ||
2139 | else { | ||
2140 | value[0] = 0x42; | ||
2141 | value[1] = 0x00; | ||
2142 | value[2] = 0xff; | ||
2143 | value[3] = 0x00; | ||
2144 | value[4] = 0x00; | ||
2145 | value[5] = 0x00; | ||
2146 | value[6] = 0x00; | ||
2147 | value[7] = 0xff; | ||
2148 | } | ||
2149 | /* These are the values of the address of the video buffer, | ||
2150 | * they have to be loaded into the USBVISION_DRM_PRM1-8 | ||
2151 | * | ||
2152 | * Start address of video output buffer for read: drm_prm1-2 -> 0x00000 | ||
2153 | * End address of video output buffer for read: drm_prm1-3 -> 0x1ffff | ||
2154 | * Start address of video frame delay buffer: drm_prm1-4 -> 0x20000 | ||
2155 | * Only used in compressed mode | ||
2156 | * End address of video frame delay buffer: drm_prm1-5-6 -> 0x3ffff | ||
2157 | * Only used in compressed mode | ||
2158 | * Start address of video output buffer for write: drm_prm1-7 -> 0x00000 | ||
2159 | * End address of video output buffer for write: drm_prm1-8 -> 0x1ffff | ||
2160 | */ | ||
2161 | |||
2162 | if (!USBVISION_IS_OPERATIONAL(usbvision)) | ||
2163 | return 0; | ||
2164 | |||
2165 | rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), | ||
2166 | USBVISION_OP_CODE, /* USBVISION specific code */ | ||
2167 | USB_DIR_OUT | USB_TYPE_VENDOR | | ||
2168 | USB_RECIP_ENDPOINT, 0, | ||
2169 | (__u16) USBVISION_DRM_PRM1, value, 8, HZ); | ||
2170 | |||
2171 | if (rc < 0) { | ||
2172 | err("%sERROR=%d", __FUNCTION__, rc); | ||
2173 | return rc; | ||
2174 | } | ||
2175 | |||
2176 | /* Restart the video buffer logic */ | ||
2177 | if ((rc = usbvision_write_reg(usbvision, USBVISION_DRM_CONT, USBVISION_RES_UR | | ||
2178 | USBVISION_RES_FDL | USBVISION_RES_VDW)) < 0) | ||
2179 | return rc; | ||
2180 | rc = usbvision_write_reg(usbvision, USBVISION_DRM_CONT, 0x00); | ||
2181 | |||
2182 | return rc; | ||
2183 | } | ||
2184 | |||
2185 | /* | ||
2186 | * () | ||
2187 | * | ||
2188 | * Power on the device, enables suspend-resume logic | ||
2189 | * & reset the isoc End-Point | ||
2190 | * | ||
2191 | */ | ||
2192 | |||
2193 | int usbvision_power_on(struct usb_usbvision *usbvision) | ||
2194 | { | ||
2195 | int errCode = 0; | ||
2196 | |||
2197 | PDEBUG(DBG_FUNC, ""); | ||
2198 | |||
2199 | usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN); | ||
2200 | usbvision_write_reg(usbvision, USBVISION_PWR_REG, | ||
2201 | USBVISION_SSPND_EN | USBVISION_RES2); | ||
2202 | usbvision_write_reg(usbvision, USBVISION_PWR_REG, | ||
2203 | USBVISION_SSPND_EN | USBVISION_PWR_VID); | ||
2204 | errCode = usbvision_write_reg(usbvision, USBVISION_PWR_REG, | ||
2205 | USBVISION_SSPND_EN | USBVISION_PWR_VID | USBVISION_RES2); | ||
2206 | if (errCode == 1) { | ||
2207 | usbvision->power = 1; | ||
2208 | } | ||
2209 | PDEBUG(DBG_FUNC, "%s: errCode %d", (errCode<0)?"ERROR":"power is on", errCode); | ||
2210 | return errCode; | ||
2211 | } | ||
2212 | |||
2213 | |||
2214 | /* | ||
2215 | * usbvision timer stuff | ||
2216 | */ | ||
2217 | |||
2218 | // to call usbvision_power_off from task queue | ||
2219 | static void call_usbvision_power_off(struct work_struct *work) | ||
2220 | { | ||
2221 | struct usb_usbvision *usbvision = container_of(work, struct usb_usbvision, powerOffWork); | ||
2222 | |||
2223 | PDEBUG(DBG_FUNC, ""); | ||
2224 | down_interruptible(&usbvision->lock); | ||
2225 | if(usbvision->user == 0) { | ||
2226 | usbvision_i2c_usb_del_bus(&usbvision->i2c_adap); | ||
2227 | |||
2228 | usbvision_power_off(usbvision); | ||
2229 | usbvision->initialized = 0; | ||
2230 | } | ||
2231 | up(&usbvision->lock); | ||
2232 | } | ||
2233 | |||
2234 | static void usbvision_powerOffTimer(unsigned long data) | ||
2235 | { | ||
2236 | struct usb_usbvision *usbvision = (void *) data; | ||
2237 | |||
2238 | PDEBUG(DBG_FUNC, ""); | ||
2239 | del_timer(&usbvision->powerOffTimer); | ||
2240 | INIT_WORK(&usbvision->powerOffWork, call_usbvision_power_off); | ||
2241 | (void) schedule_work(&usbvision->powerOffWork); | ||
2242 | |||
2243 | } | ||
2244 | |||
2245 | void usbvision_init_powerOffTimer(struct usb_usbvision *usbvision) | ||
2246 | { | ||
2247 | init_timer(&usbvision->powerOffTimer); | ||
2248 | usbvision->powerOffTimer.data = (long) usbvision; | ||
2249 | usbvision->powerOffTimer.function = usbvision_powerOffTimer; | ||
2250 | } | ||
2251 | |||
2252 | void usbvision_set_powerOffTimer(struct usb_usbvision *usbvision) | ||
2253 | { | ||
2254 | mod_timer(&usbvision->powerOffTimer, jiffies + USBVISION_POWEROFF_TIME); | ||
2255 | } | ||
2256 | |||
2257 | void usbvision_reset_powerOffTimer(struct usb_usbvision *usbvision) | ||
2258 | { | ||
2259 | if (timer_pending(&usbvision->powerOffTimer)) { | ||
2260 | del_timer(&usbvision->powerOffTimer); | ||
2261 | } | ||
2262 | } | ||
2263 | |||
2264 | /* | ||
2265 | * usbvision_begin_streaming() | ||
2266 | * Sure you have to put bit 7 to 0, if not incoming frames are droped, but no | ||
2267 | * idea about the rest | ||
2268 | */ | ||
2269 | int usbvision_begin_streaming(struct usb_usbvision *usbvision) | ||
2270 | { | ||
2271 | int errCode = 0; | ||
2272 | |||
2273 | if (usbvision->isocMode == ISOC_MODE_COMPRESS) { | ||
2274 | usbvision_init_compression(usbvision); | ||
2275 | } | ||
2276 | errCode = usbvision_write_reg(usbvision, USBVISION_VIN_REG2, USBVISION_NOHVALID | | ||
2277 | usbvision->Vin_Reg2_Preset); | ||
2278 | return errCode; | ||
2279 | } | ||
2280 | |||
2281 | /* | ||
2282 | * usbvision_restart_isoc() | ||
2283 | * Not sure yet if touching here PWR_REG make loose the config | ||
2284 | */ | ||
2285 | |||
2286 | int usbvision_restart_isoc(struct usb_usbvision *usbvision) | ||
2287 | { | ||
2288 | int ret; | ||
2289 | |||
2290 | if ( | ||
2291 | (ret = | ||
2292 | usbvision_write_reg(usbvision, USBVISION_PWR_REG, | ||
2293 | USBVISION_SSPND_EN | USBVISION_PWR_VID)) < 0) | ||
2294 | return ret; | ||
2295 | if ( | ||
2296 | (ret = | ||
2297 | usbvision_write_reg(usbvision, USBVISION_PWR_REG, | ||
2298 | USBVISION_SSPND_EN | USBVISION_PWR_VID | | ||
2299 | USBVISION_RES2)) < 0) | ||
2300 | return ret; | ||
2301 | if ( | ||
2302 | (ret = | ||
2303 | usbvision_write_reg(usbvision, USBVISION_VIN_REG2, | ||
2304 | USBVISION_KEEP_BLANK | USBVISION_NOHVALID | | ||
2305 | usbvision->Vin_Reg2_Preset)) < 0) return ret; | ||
2306 | |||
2307 | /* TODO: schedule timeout */ | ||
2308 | while ((usbvision_read_reg(usbvision, USBVISION_STATUS_REG) && 0x01) != 1); | ||
2309 | |||
2310 | return 0; | ||
2311 | } | ||
2312 | |||
2313 | int usbvision_audio_off(struct usb_usbvision *usbvision) | ||
2314 | { | ||
2315 | if (usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, USBVISION_AUDIO_MUTE) < 0) { | ||
2316 | printk(KERN_ERR "usbvision_audio_off: can't wirte reg\n"); | ||
2317 | return -1; | ||
2318 | } | ||
2319 | usbvision->AudioMute = 0; | ||
2320 | usbvision->AudioChannel = USBVISION_AUDIO_MUTE; | ||
2321 | return 0; | ||
2322 | } | ||
2323 | |||
2324 | int usbvision_set_audio(struct usb_usbvision *usbvision, int AudioChannel) | ||
2325 | { | ||
2326 | if (!usbvision->AudioMute) { | ||
2327 | if (usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, AudioChannel) < 0) { | ||
2328 | printk(KERN_ERR "usbvision_set_audio: can't write iopin register for audio switching\n"); | ||
2329 | return -1; | ||
2330 | } | ||
2331 | } | ||
2332 | usbvision->AudioChannel = AudioChannel; | ||
2333 | return 0; | ||
2334 | } | ||
2335 | |||
2336 | int usbvision_setup(struct usb_usbvision *usbvision,int format) | ||
2337 | { | ||
2338 | usbvision_set_video_format(usbvision, format); | ||
2339 | usbvision_set_dram_settings(usbvision); | ||
2340 | usbvision_set_compress_params(usbvision); | ||
2341 | usbvision_set_input(usbvision); | ||
2342 | usbvision_set_output(usbvision, MAX_USB_WIDTH, MAX_USB_HEIGHT); | ||
2343 | usbvision_restart_isoc(usbvision); | ||
2344 | |||
2345 | /* cosas del PCM */ | ||
2346 | return USBVISION_IS_OPERATIONAL(usbvision); | ||
2347 | } | ||
2348 | |||
2349 | |||
2350 | int usbvision_sbuf_alloc(struct usb_usbvision *usbvision) | ||
2351 | { | ||
2352 | int i, errCode = 0; | ||
2353 | const int sb_size = USBVISION_URB_FRAMES * USBVISION_MAX_ISOC_PACKET_SIZE; | ||
2354 | |||
2355 | /* Clean pointers so we know if we allocated something */ | ||
2356 | for (i = 0; i < USBVISION_NUMSBUF; i++) | ||
2357 | usbvision->sbuf[i].data = NULL; | ||
2358 | |||
2359 | for (i = 0; i < USBVISION_NUMSBUF; i++) { | ||
2360 | usbvision->sbuf[i].data = kzalloc(sb_size, GFP_KERNEL); | ||
2361 | if (usbvision->sbuf[i].data == NULL) { | ||
2362 | err("%s: unable to allocate %d bytes for sbuf", __FUNCTION__, sb_size); | ||
2363 | errCode = -ENOMEM; | ||
2364 | break; | ||
2365 | } | ||
2366 | } | ||
2367 | return errCode; | ||
2368 | } | ||
2369 | |||
2370 | |||
2371 | void usbvision_sbuf_free(struct usb_usbvision *usbvision) | ||
2372 | { | ||
2373 | int i; | ||
2374 | |||
2375 | for (i = 0; i < USBVISION_NUMSBUF; i++) { | ||
2376 | if (usbvision->sbuf[i].data != NULL) { | ||
2377 | kfree(usbvision->sbuf[i].data); | ||
2378 | usbvision->sbuf[i].data = NULL; | ||
2379 | } | ||
2380 | } | ||
2381 | } | ||
2382 | |||
2383 | /* | ||
2384 | * usbvision_init_isoc() | ||
2385 | * | ||
2386 | */ | ||
2387 | int usbvision_init_isoc(struct usb_usbvision *usbvision) | ||
2388 | { | ||
2389 | struct usb_device *dev = usbvision->dev; | ||
2390 | int bufIdx, errCode, regValue; | ||
2391 | |||
2392 | if (!USBVISION_IS_OPERATIONAL(usbvision)) | ||
2393 | return -EFAULT; | ||
2394 | |||
2395 | usbvision->curFrame = NULL; | ||
2396 | scratch_reset(usbvision); | ||
2397 | |||
2398 | /* Alternate interface 1 is is the biggest frame size */ | ||
2399 | errCode = usb_set_interface(dev, usbvision->iface, usbvision->ifaceAltActive); | ||
2400 | if (errCode < 0) { | ||
2401 | usbvision->last_error = errCode; | ||
2402 | return -EBUSY; | ||
2403 | } | ||
2404 | |||
2405 | regValue = (16 - usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F; | ||
2406 | usbvision->isocPacketSize = (regValue == 0) ? 0 : (regValue * 64) - 1; | ||
2407 | PDEBUG(DBG_ISOC, "ISO Packet Length:%d", usbvision->isocPacketSize); | ||
2408 | |||
2409 | usbvision->usb_bandwidth = regValue >> 1; | ||
2410 | PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec", usbvision->usb_bandwidth); | ||
2411 | |||
2412 | |||
2413 | |||
2414 | /* We double buffer the Iso lists */ | ||
2415 | |||
2416 | for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) { | ||
2417 | int j, k; | ||
2418 | struct urb *urb; | ||
2419 | |||
2420 | urb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL); | ||
2421 | if (urb == NULL) { | ||
2422 | err("%s: usb_alloc_urb() failed", __FUNCTION__); | ||
2423 | return -ENOMEM; | ||
2424 | } | ||
2425 | usbvision->sbuf[bufIdx].urb = urb; | ||
2426 | urb->dev = dev; | ||
2427 | urb->context = usbvision; | ||
2428 | urb->pipe = usb_rcvisocpipe(dev, usbvision->video_endp); | ||
2429 | urb->transfer_flags = URB_ISO_ASAP; | ||
2430 | urb->interval = 1; | ||
2431 | urb->transfer_buffer = usbvision->sbuf[bufIdx].data; | ||
2432 | urb->complete = usbvision_isocIrq; | ||
2433 | urb->number_of_packets = USBVISION_URB_FRAMES; | ||
2434 | urb->transfer_buffer_length = | ||
2435 | usbvision->isocPacketSize * USBVISION_URB_FRAMES; | ||
2436 | for (j = k = 0; j < USBVISION_URB_FRAMES; j++, | ||
2437 | k += usbvision->isocPacketSize) { | ||
2438 | urb->iso_frame_desc[j].offset = k; | ||
2439 | urb->iso_frame_desc[j].length = usbvision->isocPacketSize; | ||
2440 | } | ||
2441 | } | ||
2442 | |||
2443 | |||
2444 | /* Submit all URBs */ | ||
2445 | for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) { | ||
2446 | errCode = usb_submit_urb(usbvision->sbuf[bufIdx].urb, GFP_KERNEL); | ||
2447 | if (errCode) { | ||
2448 | err("%s: usb_submit_urb(%d) failed: error %d", __FUNCTION__, bufIdx, errCode); | ||
2449 | } | ||
2450 | } | ||
2451 | |||
2452 | usbvision->streaming = Stream_Idle; | ||
2453 | PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x", __FUNCTION__, usbvision->video_endp); | ||
2454 | return 0; | ||
2455 | } | ||
2456 | |||
2457 | /* | ||
2458 | * usbvision_stop_isoc() | ||
2459 | * | ||
2460 | * This procedure stops streaming and deallocates URBs. Then it | ||
2461 | * activates zero-bandwidth alt. setting of the video interface. | ||
2462 | * | ||
2463 | */ | ||
2464 | void usbvision_stop_isoc(struct usb_usbvision *usbvision) | ||
2465 | { | ||
2466 | int bufIdx, errCode, regValue; | ||
2467 | |||
2468 | if ((usbvision->streaming == Stream_Off) || (usbvision->dev == NULL)) | ||
2469 | return; | ||
2470 | |||
2471 | /* Unschedule all of the iso td's */ | ||
2472 | for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) { | ||
2473 | usb_kill_urb(usbvision->sbuf[bufIdx].urb); | ||
2474 | usb_free_urb(usbvision->sbuf[bufIdx].urb); | ||
2475 | usbvision->sbuf[bufIdx].urb = NULL; | ||
2476 | } | ||
2477 | |||
2478 | |||
2479 | PDEBUG(DBG_ISOC, "%s: streaming=Stream_Off\n", __FUNCTION__); | ||
2480 | usbvision->streaming = Stream_Off; | ||
2481 | |||
2482 | if (!usbvision->remove_pending) { | ||
2483 | |||
2484 | /* Set packet size to 0 */ | ||
2485 | errCode = usb_set_interface(usbvision->dev, usbvision->iface, | ||
2486 | usbvision->ifaceAltInactive); | ||
2487 | if (errCode < 0) { | ||
2488 | err("%s: usb_set_interface() failed: error %d", __FUNCTION__, errCode); | ||
2489 | usbvision->last_error = errCode; | ||
2490 | } | ||
2491 | regValue = (16 - usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F; | ||
2492 | usbvision->isocPacketSize = (regValue == 0) ? 0 : (regValue * 64) - 1; | ||
2493 | PDEBUG(DBG_ISOC, "ISO Packet Length:%d", usbvision->isocPacketSize); | ||
2494 | |||
2495 | usbvision->usb_bandwidth = regValue >> 1; | ||
2496 | PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec", usbvision->usb_bandwidth); | ||
2497 | } | ||
2498 | } | ||
2499 | |||
2500 | int usbvision_muxsel(struct usb_usbvision *usbvision, int channel) | ||
2501 | { | ||
2502 | int mode[4]; | ||
2503 | int audio[]= {1, 0, 0, 0}; | ||
2504 | struct v4l2_routing route; | ||
2505 | //channel 0 is TV with audiochannel 1 (tuner mono) | ||
2506 | //channel 1 is Composite with audio channel 0 (line in) | ||
2507 | //channel 2 is S-Video with audio channel 0 (line in) | ||
2508 | //channel 3 is additional video inputs to the device with audio channel 0 (line in) | ||
2509 | |||
2510 | RESTRICT_TO_RANGE(channel, 0, usbvision->video_inputs); | ||
2511 | usbvision->ctl_input = channel; | ||
2512 | route.input = SAA7115_COMPOSITE1; | ||
2513 | call_i2c_clients(usbvision, VIDIOC_INT_S_VIDEO_ROUTING,&route); | ||
2514 | call_i2c_clients(usbvision, VIDIOC_S_INPUT, &usbvision->ctl_input); | ||
2515 | |||
2516 | // set the new channel | ||
2517 | // Regular USB TV Tuners -> channel: 0 = Television, 1 = Composite, 2 = S-Video | ||
2518 | // Four video input devices -> channel: 0 = Chan White, 1 = Chan Green, 2 = Chan Yellow, 3 = Chan Red | ||
2519 | |||
2520 | switch (usbvision_device_data[usbvision->DevModel].Codec) { | ||
2521 | case CODEC_SAA7113: | ||
2522 | if (SwitchSVideoInput) { // To handle problems with S-Video Input for some devices. Use SwitchSVideoInput parameter when loading the module. | ||
2523 | mode[2] = 1; | ||
2524 | } | ||
2525 | else { | ||
2526 | mode[2] = 7; | ||
2527 | } | ||
2528 | if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { | ||
2529 | mode[0] = 0; mode[1] = 2; mode[3] = 3; // Special for four input devices | ||
2530 | } | ||
2531 | else { | ||
2532 | mode[0] = 0; mode[1] = 2; //modes for regular saa7113 devices | ||
2533 | } | ||
2534 | break; | ||
2535 | case CODEC_SAA7111: | ||
2536 | mode[0] = 0; mode[1] = 1; mode[2] = 7; //modes for saa7111 | ||
2537 | break; | ||
2538 | default: | ||
2539 | mode[0] = 0; mode[1] = 1; mode[2] = 7; //default modes | ||
2540 | } | ||
2541 | route.input = mode[channel]; | ||
2542 | call_i2c_clients(usbvision, VIDIOC_INT_S_VIDEO_ROUTING,&route); | ||
2543 | usbvision->channel = channel; | ||
2544 | usbvision_set_audio(usbvision, audio[channel]); | ||
2545 | return 0; | ||
2546 | } | ||
2547 | |||
2548 | /* | ||
2549 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
2550 | * --------------------------------------------------------------------------- | ||
2551 | * Local variables: | ||
2552 | * c-basic-offset: 8 | ||
2553 | * End: | ||
2554 | */ | ||
diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c new file mode 100644 index 000000000000..92bf9a1f1e2c --- /dev/null +++ b/drivers/media/video/usbvision/usbvision-i2c.c | |||
@@ -0,0 +1,567 @@ | |||
1 | /* | ||
2 | * I2C_ALGO_USB.C | ||
3 | * i2c algorithm for USB-I2C Bridges | ||
4 | * | ||
5 | * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de> | ||
6 | * Dwaine Garden <dwainegarden@rogers.com> | ||
7 | * | ||
8 | * This module is part of usbvision driver project. | ||
9 | * Updates to driver completed by Dwaine P. Garden | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | */ | ||
25 | |||
26 | |||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/delay.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/version.h> | ||
32 | #include <linux/utsname.h> | ||
33 | #include <linux/init.h> | ||
34 | #include <asm/uaccess.h> | ||
35 | #include <linux/ioport.h> | ||
36 | #include <linux/errno.h> | ||
37 | #include <linux/sched.h> | ||
38 | #include <linux/usb.h> | ||
39 | #include <linux/i2c.h> | ||
40 | #include "usbvision.h" | ||
41 | |||
42 | #define DBG_I2C 1<<0 | ||
43 | #define DBG_ALGO 1<<1 | ||
44 | |||
45 | static int i2c_debug = 0; | ||
46 | |||
47 | module_param (i2c_debug, int, 0644); // debug_i2c_usb mode of the device driver | ||
48 | MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); | ||
49 | |||
50 | #define PDEBUG(level, fmt, args...) \ | ||
51 | if (i2c_debug & (level)) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , ## args) | ||
52 | |||
53 | static inline int try_write_address(struct i2c_adapter *i2c_adap, | ||
54 | unsigned char addr, int retries) | ||
55 | { | ||
56 | struct i2c_algo_usb_data *adap = i2c_adap->algo_data; | ||
57 | void *data; | ||
58 | int i, ret = -1; | ||
59 | char buf[4]; | ||
60 | |||
61 | data = i2c_get_adapdata(i2c_adap); | ||
62 | buf[0] = 0x00; | ||
63 | for (i = 0; i <= retries; i++) { | ||
64 | ret = (adap->outb(data, addr, buf, 1)); | ||
65 | if (ret == 1) | ||
66 | break; /* success! */ | ||
67 | udelay(5 /*adap->udelay */ ); | ||
68 | if (i == retries) /* no success */ | ||
69 | break; | ||
70 | udelay(adap->udelay); | ||
71 | } | ||
72 | if (i) { | ||
73 | PDEBUG(DBG_ALGO,"Needed %d retries for address %#2x", i, addr); | ||
74 | PDEBUG(DBG_ALGO,"Maybe there's no device at this address"); | ||
75 | } | ||
76 | return ret; | ||
77 | } | ||
78 | |||
79 | static inline int try_read_address(struct i2c_adapter *i2c_adap, | ||
80 | unsigned char addr, int retries) | ||
81 | { | ||
82 | struct i2c_algo_usb_data *adap = i2c_adap->algo_data; | ||
83 | void *data; | ||
84 | int i, ret = -1; | ||
85 | char buf[4]; | ||
86 | |||
87 | data = i2c_get_adapdata(i2c_adap); | ||
88 | for (i = 0; i <= retries; i++) { | ||
89 | ret = (adap->inb(data, addr, buf, 1)); | ||
90 | if (ret == 1) | ||
91 | break; /* success! */ | ||
92 | udelay(5 /*adap->udelay */ ); | ||
93 | if (i == retries) /* no success */ | ||
94 | break; | ||
95 | udelay(adap->udelay); | ||
96 | } | ||
97 | if (i) { | ||
98 | PDEBUG(DBG_ALGO,"Needed %d retries for address %#2x", i, addr); | ||
99 | PDEBUG(DBG_ALGO,"Maybe there's no device at this address"); | ||
100 | } | ||
101 | return ret; | ||
102 | } | ||
103 | |||
104 | static inline int usb_find_address(struct i2c_adapter *i2c_adap, | ||
105 | struct i2c_msg *msg, int retries, | ||
106 | unsigned char *add) | ||
107 | { | ||
108 | unsigned short flags = msg->flags; | ||
109 | |||
110 | unsigned char addr; | ||
111 | int ret; | ||
112 | if ((flags & I2C_M_TEN)) { | ||
113 | /* a ten bit address */ | ||
114 | addr = 0xf0 | ((msg->addr >> 7) & 0x03); | ||
115 | /* try extended address code... */ | ||
116 | ret = try_write_address(i2c_adap, addr, retries); | ||
117 | if (ret != 1) { | ||
118 | err("died at extended address code, while writing"); | ||
119 | return -EREMOTEIO; | ||
120 | } | ||
121 | add[0] = addr; | ||
122 | if (flags & I2C_M_RD) { | ||
123 | /* okay, now switch into reading mode */ | ||
124 | addr |= 0x01; | ||
125 | ret = try_read_address(i2c_adap, addr, retries); | ||
126 | if (ret != 1) { | ||
127 | err("died at extended address code, while reading"); | ||
128 | return -EREMOTEIO; | ||
129 | } | ||
130 | } | ||
131 | |||
132 | } else { /* normal 7bit address */ | ||
133 | addr = (msg->addr << 1); | ||
134 | if (flags & I2C_M_RD) | ||
135 | addr |= 1; | ||
136 | if (flags & I2C_M_REV_DIR_ADDR) | ||
137 | addr ^= 1; | ||
138 | |||
139 | add[0] = addr; | ||
140 | if (flags & I2C_M_RD) | ||
141 | ret = try_read_address(i2c_adap, addr, retries); | ||
142 | else | ||
143 | ret = try_write_address(i2c_adap, addr, retries); | ||
144 | |||
145 | if (ret != 1) { | ||
146 | return -EREMOTEIO; | ||
147 | } | ||
148 | } | ||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static int | ||
153 | usb_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) | ||
154 | { | ||
155 | struct i2c_msg *pmsg; | ||
156 | struct i2c_algo_usb_data *adap = i2c_adap->algo_data; | ||
157 | void *data; | ||
158 | int i, ret; | ||
159 | unsigned char addr; | ||
160 | |||
161 | data = i2c_get_adapdata(i2c_adap); | ||
162 | |||
163 | for (i = 0; i < num; i++) { | ||
164 | pmsg = &msgs[i]; | ||
165 | ret = usb_find_address(i2c_adap, pmsg, i2c_adap->retries, &addr); | ||
166 | if (ret != 0) { | ||
167 | PDEBUG(DBG_ALGO,"got NAK from device, message #%d", i); | ||
168 | return (ret < 0) ? ret : -EREMOTEIO; | ||
169 | } | ||
170 | |||
171 | if (pmsg->flags & I2C_M_RD) { | ||
172 | /* read bytes into buffer */ | ||
173 | ret = (adap->inb(data, addr, pmsg->buf, pmsg->len)); | ||
174 | if (ret < pmsg->len) { | ||
175 | return (ret < 0) ? ret : -EREMOTEIO; | ||
176 | } | ||
177 | } else { | ||
178 | /* write bytes from buffer */ | ||
179 | ret = (adap->outb(data, addr, pmsg->buf, pmsg->len)); | ||
180 | if (ret < pmsg->len) { | ||
181 | return (ret < 0) ? ret : -EREMOTEIO; | ||
182 | } | ||
183 | } | ||
184 | } | ||
185 | return num; | ||
186 | } | ||
187 | |||
188 | static int algo_control(struct i2c_adapter *adapter, unsigned int cmd, unsigned long arg) | ||
189 | { | ||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | static u32 usb_func(struct i2c_adapter *adap) | ||
194 | { | ||
195 | return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING; | ||
196 | } | ||
197 | |||
198 | |||
199 | /* -----exported algorithm data: ------------------------------------- */ | ||
200 | |||
201 | static struct i2c_algorithm i2c_usb_algo = { | ||
202 | .master_xfer = usb_xfer, | ||
203 | .smbus_xfer = NULL, | ||
204 | .algo_control = algo_control, | ||
205 | .functionality = usb_func, | ||
206 | }; | ||
207 | |||
208 | |||
209 | /* | ||
210 | * registering functions to load algorithms at runtime | ||
211 | */ | ||
212 | int usbvision_i2c_usb_add_bus(struct i2c_adapter *adap) | ||
213 | { | ||
214 | PDEBUG(DBG_I2C, "I2C debugging is enabled [i2c]"); | ||
215 | PDEBUG(DBG_ALGO, "ALGO debugging is enabled [i2c]"); | ||
216 | |||
217 | /* register new adapter to i2c module... */ | ||
218 | |||
219 | adap->algo = &i2c_usb_algo; | ||
220 | |||
221 | adap->timeout = 100; /* default values, should */ | ||
222 | adap->retries = 3; /* be replaced by defines */ | ||
223 | |||
224 | i2c_add_adapter(adap); | ||
225 | |||
226 | PDEBUG(DBG_ALGO,"i2c bus for %s registered", adap->name); | ||
227 | |||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | |||
232 | int usbvision_i2c_usb_del_bus(struct i2c_adapter *adap) | ||
233 | { | ||
234 | |||
235 | i2c_del_adapter(adap); | ||
236 | |||
237 | PDEBUG(DBG_ALGO,"i2c bus for %s unregistered", adap->name); | ||
238 | |||
239 | return 0; | ||
240 | } | ||
241 | |||
242 | |||
243 | /* ----------------------------------------------------------------------- */ | ||
244 | /* usbvision specific I2C functions */ | ||
245 | /* ----------------------------------------------------------------------- */ | ||
246 | static struct i2c_adapter i2c_adap_template; | ||
247 | static struct i2c_algo_usb_data i2c_algo_template; | ||
248 | static struct i2c_client i2c_client_template; | ||
249 | |||
250 | int usbvision_init_i2c(struct usb_usbvision *usbvision) | ||
251 | { | ||
252 | memcpy(&usbvision->i2c_adap, &i2c_adap_template, | ||
253 | sizeof(struct i2c_adapter)); | ||
254 | memcpy(&usbvision->i2c_algo, &i2c_algo_template, | ||
255 | sizeof(struct i2c_algo_usb_data)); | ||
256 | memcpy(&usbvision->i2c_client, &i2c_client_template, | ||
257 | sizeof(struct i2c_client)); | ||
258 | |||
259 | sprintf(usbvision->i2c_adap.name + strlen(usbvision->i2c_adap.name), | ||
260 | " #%d", usbvision->vdev->minor & 0x1f); | ||
261 | PDEBUG(DBG_I2C,"Adaptername: %s", usbvision->i2c_adap.name); | ||
262 | |||
263 | i2c_set_adapdata(&usbvision->i2c_adap, usbvision); | ||
264 | i2c_set_clientdata(&usbvision->i2c_client, usbvision); | ||
265 | i2c_set_algo_usb_data(&usbvision->i2c_algo, usbvision); | ||
266 | |||
267 | usbvision->i2c_adap.algo_data = &usbvision->i2c_algo; | ||
268 | usbvision->i2c_client.adapter = &usbvision->i2c_adap; | ||
269 | |||
270 | if (usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_IIC_LRNACK) < 0) { | ||
271 | printk(KERN_ERR "usbvision_init_i2c: can't write reg\n"); | ||
272 | return -EBUSY; | ||
273 | } | ||
274 | |||
275 | #ifdef CONFIG_MODULES | ||
276 | /* Request the load of the i2c modules we need */ | ||
277 | switch (usbvision_device_data[usbvision->DevModel].Codec) { | ||
278 | case CODEC_SAA7113: | ||
279 | request_module("saa7115"); | ||
280 | break; | ||
281 | case CODEC_SAA7111: | ||
282 | request_module("saa7115"); | ||
283 | break; | ||
284 | } | ||
285 | if (usbvision_device_data[usbvision->DevModel].Tuner == 1) { | ||
286 | request_module("tuner"); | ||
287 | } | ||
288 | #endif | ||
289 | |||
290 | return usbvision_i2c_usb_add_bus(&usbvision->i2c_adap); | ||
291 | } | ||
292 | |||
293 | void call_i2c_clients(struct usb_usbvision *usbvision, unsigned int cmd, | ||
294 | void *arg) | ||
295 | { | ||
296 | BUG_ON(NULL == usbvision->i2c_adap.algo_data); | ||
297 | i2c_clients_command(&usbvision->i2c_adap, cmd, arg); | ||
298 | } | ||
299 | |||
300 | static int attach_inform(struct i2c_client *client) | ||
301 | { | ||
302 | struct usb_usbvision *usbvision; | ||
303 | |||
304 | usbvision = (struct usb_usbvision *)i2c_get_adapdata(client->adapter); | ||
305 | |||
306 | switch (client->addr << 1) { | ||
307 | case 0x43: | ||
308 | case 0x4b: | ||
309 | { | ||
310 | struct tuner_setup tun_setup; | ||
311 | |||
312 | tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; | ||
313 | tun_setup.type = TUNER_TDA9887; | ||
314 | tun_setup.addr = client->addr; | ||
315 | |||
316 | call_i2c_clients(usbvision, TUNER_SET_TYPE_ADDR, &tun_setup); | ||
317 | |||
318 | break; | ||
319 | } | ||
320 | case 0x42: | ||
321 | PDEBUG(DBG_I2C,"attach_inform: saa7114 detected."); | ||
322 | break; | ||
323 | case 0x4a: | ||
324 | PDEBUG(DBG_I2C,"attach_inform: saa7113 detected."); | ||
325 | break; | ||
326 | case 0xa0: | ||
327 | PDEBUG(DBG_I2C,"attach_inform: eeprom detected."); | ||
328 | break; | ||
329 | |||
330 | default: | ||
331 | { | ||
332 | struct tuner_setup tun_setup; | ||
333 | |||
334 | PDEBUG(DBG_I2C,"attach inform: detected I2C address %x", client->addr << 1); | ||
335 | usbvision->tuner_addr = client->addr; | ||
336 | |||
337 | if ((usbvision->have_tuner) && (usbvision->tuner_type != -1)) { | ||
338 | tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; | ||
339 | tun_setup.type = usbvision->tuner_type; | ||
340 | tun_setup.addr = usbvision->tuner_addr; | ||
341 | call_i2c_clients(usbvision, TUNER_SET_TYPE_ADDR, &tun_setup); | ||
342 | } | ||
343 | } | ||
344 | break; | ||
345 | } | ||
346 | return 0; | ||
347 | } | ||
348 | |||
349 | static int detach_inform(struct i2c_client *client) | ||
350 | { | ||
351 | struct usb_usbvision *usbvision; | ||
352 | |||
353 | usbvision = (struct usb_usbvision *)i2c_get_adapdata(client->adapter); | ||
354 | |||
355 | PDEBUG(DBG_I2C,"usbvision[%d] detaches %s", usbvision->nr, client->name); | ||
356 | return 0; | ||
357 | } | ||
358 | |||
359 | static int | ||
360 | usbvision_i2c_read_max4(struct usb_usbvision *usbvision, unsigned char addr, | ||
361 | char *buf, short len) | ||
362 | { | ||
363 | int rc, retries; | ||
364 | |||
365 | for (retries = 5;;) { | ||
366 | rc = usbvision_write_reg(usbvision, USBVISION_SER_ADRS, addr); | ||
367 | if (rc < 0) | ||
368 | return rc; | ||
369 | |||
370 | /* Initiate byte read cycle */ | ||
371 | /* USBVISION_SER_CONT <- d0-d2 n. of bytes to r/w */ | ||
372 | /* d3 0=Wr 1=Rd */ | ||
373 | rc = usbvision_write_reg(usbvision, USBVISION_SER_CONT, | ||
374 | (len & 0x07) | 0x18); | ||
375 | if (rc < 0) | ||
376 | return rc; | ||
377 | |||
378 | /* Test for Busy and ACK */ | ||
379 | do { | ||
380 | /* USBVISION_SER_CONT -> d4 == 0 busy */ | ||
381 | rc = usbvision_read_reg(usbvision, USBVISION_SER_CONT); | ||
382 | } while (rc > 0 && ((rc & 0x10) != 0)); /* Retry while busy */ | ||
383 | if (rc < 0) | ||
384 | return rc; | ||
385 | |||
386 | /* USBVISION_SER_CONT -> d5 == 1 Not ack */ | ||
387 | if ((rc & 0x20) == 0) /* Ack? */ | ||
388 | break; | ||
389 | |||
390 | /* I2C abort */ | ||
391 | rc = usbvision_write_reg(usbvision, USBVISION_SER_CONT, 0x00); | ||
392 | if (rc < 0) | ||
393 | return rc; | ||
394 | |||
395 | if (--retries < 0) | ||
396 | return -1; | ||
397 | } | ||
398 | |||
399 | switch (len) { | ||
400 | case 4: | ||
401 | buf[3] = usbvision_read_reg(usbvision, USBVISION_SER_DAT4); | ||
402 | case 3: | ||
403 | buf[2] = usbvision_read_reg(usbvision, USBVISION_SER_DAT3); | ||
404 | case 2: | ||
405 | buf[1] = usbvision_read_reg(usbvision, USBVISION_SER_DAT2); | ||
406 | case 1: | ||
407 | buf[0] = usbvision_read_reg(usbvision, USBVISION_SER_DAT1); | ||
408 | break; | ||
409 | default: | ||
410 | printk(KERN_ERR | ||
411 | "usbvision_i2c_read_max4: buffer length > 4\n"); | ||
412 | } | ||
413 | |||
414 | if (i2c_debug & DBG_I2C) { | ||
415 | int idx; | ||
416 | for (idx = 0; idx < len; idx++) { | ||
417 | PDEBUG(DBG_I2C,"read %x from address %x", (unsigned char)buf[idx], addr); | ||
418 | } | ||
419 | } | ||
420 | return len; | ||
421 | } | ||
422 | |||
423 | |||
424 | static int usbvision_i2c_write_max4(struct usb_usbvision *usbvision, | ||
425 | unsigned char addr, const char *buf, | ||
426 | short len) | ||
427 | { | ||
428 | int rc, retries; | ||
429 | int i; | ||
430 | unsigned char value[6]; | ||
431 | unsigned char ser_cont; | ||
432 | |||
433 | ser_cont = (len & 0x07) | 0x10; | ||
434 | |||
435 | value[0] = addr; | ||
436 | value[1] = ser_cont; | ||
437 | for (i = 0; i < len; i++) | ||
438 | value[i + 2] = buf[i]; | ||
439 | |||
440 | for (retries = 5;;) { | ||
441 | rc = usb_control_msg(usbvision->dev, | ||
442 | usb_sndctrlpipe(usbvision->dev, 1), | ||
443 | USBVISION_OP_CODE, | ||
444 | USB_DIR_OUT | USB_TYPE_VENDOR | | ||
445 | USB_RECIP_ENDPOINT, 0, | ||
446 | (__u16) USBVISION_SER_ADRS, value, | ||
447 | len + 2, HZ); | ||
448 | |||
449 | if (rc < 0) | ||
450 | return rc; | ||
451 | |||
452 | rc = usbvision_write_reg(usbvision, USBVISION_SER_CONT, | ||
453 | (len & 0x07) | 0x10); | ||
454 | if (rc < 0) | ||
455 | return rc; | ||
456 | |||
457 | /* Test for Busy and ACK */ | ||
458 | do { | ||
459 | rc = usbvision_read_reg(usbvision, USBVISION_SER_CONT); | ||
460 | } while (rc > 0 && ((rc & 0x10) != 0)); /* Retry while busy */ | ||
461 | if (rc < 0) | ||
462 | return rc; | ||
463 | |||
464 | if ((rc & 0x20) == 0) /* Ack? */ | ||
465 | break; | ||
466 | |||
467 | /* I2C abort */ | ||
468 | usbvision_write_reg(usbvision, USBVISION_SER_CONT, 0x00); | ||
469 | |||
470 | if (--retries < 0) | ||
471 | return -1; | ||
472 | |||
473 | } | ||
474 | |||
475 | if (i2c_debug & DBG_I2C) { | ||
476 | int idx; | ||
477 | for (idx = 0; idx < len; idx++) { | ||
478 | PDEBUG(DBG_I2C,"wrote %x at address %x", (unsigned char)buf[idx], addr); | ||
479 | } | ||
480 | } | ||
481 | return len; | ||
482 | } | ||
483 | |||
484 | static int usbvision_i2c_write(void *data, unsigned char addr, char *buf, | ||
485 | short len) | ||
486 | { | ||
487 | char *bufPtr = buf; | ||
488 | int retval; | ||
489 | int wrcount = 0; | ||
490 | int count; | ||
491 | int maxLen = 4; | ||
492 | struct usb_usbvision *usbvision = (struct usb_usbvision *) data; | ||
493 | |||
494 | while (len > 0) { | ||
495 | count = (len > maxLen) ? maxLen : len; | ||
496 | retval = usbvision_i2c_write_max4(usbvision, addr, bufPtr, count); | ||
497 | if (retval > 0) { | ||
498 | len -= count; | ||
499 | bufPtr += count; | ||
500 | wrcount += count; | ||
501 | } else | ||
502 | return (retval < 0) ? retval : -EFAULT; | ||
503 | } | ||
504 | return wrcount; | ||
505 | } | ||
506 | |||
507 | static int usbvision_i2c_read(void *data, unsigned char addr, char *buf, | ||
508 | short len) | ||
509 | { | ||
510 | char temp[4]; | ||
511 | int retval, i; | ||
512 | int rdcount = 0; | ||
513 | int count; | ||
514 | struct usb_usbvision *usbvision = (struct usb_usbvision *) data; | ||
515 | |||
516 | while (len > 0) { | ||
517 | count = (len > 3) ? 4 : len; | ||
518 | retval = usbvision_i2c_read_max4(usbvision, addr, temp, count); | ||
519 | if (retval > 0) { | ||
520 | for (i = 0; i < len; i++) | ||
521 | buf[rdcount + i] = temp[i]; | ||
522 | len -= count; | ||
523 | rdcount += count; | ||
524 | } else | ||
525 | return (retval < 0) ? retval : -EFAULT; | ||
526 | } | ||
527 | return rdcount; | ||
528 | } | ||
529 | |||
530 | static struct i2c_algo_usb_data i2c_algo_template = { | ||
531 | .data = NULL, | ||
532 | .inb = usbvision_i2c_read, | ||
533 | .outb = usbvision_i2c_write, | ||
534 | .udelay = 10, | ||
535 | .mdelay = 10, | ||
536 | .timeout = 100, | ||
537 | }; | ||
538 | |||
539 | static struct i2c_adapter i2c_adap_template = { | ||
540 | .owner = THIS_MODULE, | ||
541 | .name = "usbvision", | ||
542 | .id = I2C_HW_B_BT848, /* FIXME */ | ||
543 | .algo = NULL, | ||
544 | .algo_data = NULL, | ||
545 | .client_register = attach_inform, | ||
546 | .client_unregister = detach_inform, | ||
547 | #ifdef I2C_ADAP_CLASS_TV_ANALOG | ||
548 | .class = I2C_ADAP_CLASS_TV_ANALOG, | ||
549 | #else | ||
550 | .class = I2C_CLASS_TV_ANALOG, | ||
551 | #endif | ||
552 | }; | ||
553 | |||
554 | static struct i2c_client i2c_client_template = { | ||
555 | .name = "usbvision internal", | ||
556 | }; | ||
557 | |||
558 | EXPORT_SYMBOL(usbvision_i2c_usb_add_bus); | ||
559 | EXPORT_SYMBOL(usbvision_i2c_usb_del_bus); | ||
560 | |||
561 | /* | ||
562 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
563 | * --------------------------------------------------------------------------- | ||
564 | * Local variables: | ||
565 | * c-basic-offset: 8 | ||
566 | * End: | ||
567 | */ | ||
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c new file mode 100644 index 000000000000..864446c012eb --- /dev/null +++ b/drivers/media/video/usbvision/usbvision-video.c | |||
@@ -0,0 +1,2051 @@ | |||
1 | /* | ||
2 | * USB USBVISION Video device driver 0.9.9 | ||
3 | * | ||
4 | * | ||
5 | * | ||
6 | * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de> | ||
7 | * | ||
8 | * This module is part of usbvision driver project. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | * | ||
24 | * Let's call the version 0.... until compression decoding is completely | ||
25 | * implemented. | ||
26 | * | ||
27 | * This driver is written by Jose Ignacio Gijon and Joerg Heckenbach. | ||
28 | * It was based on USB CPiA driver written by Peter Pregler, | ||
29 | * Scott J. Bertin and Johannes Erdfelt | ||
30 | * Ideas are taken from bttv driver by Ralph Metzler, Marcus Metzler & | ||
31 | * Gerd Knorr and zoran 36120/36125 driver by Pauline Middelink | ||
32 | * Updates to driver completed by Dwaine P. Garden | ||
33 | * | ||
34 | * | ||
35 | * TODO: | ||
36 | * - use submit_urb for all setup packets | ||
37 | * - Fix memory settings for nt1004. It is 4 times as big as the | ||
38 | * nt1003 memory. | ||
39 | * - Add audio on endpoint 3 for nt1004 chip. Seems impossible, needs a codec interface. Which one? | ||
40 | * - Clean up the driver. | ||
41 | * - optimization for performance. | ||
42 | * - Add Videotext capability (VBI). Working on it..... | ||
43 | * - Check audio for other devices | ||
44 | * | ||
45 | */ | ||
46 | |||
47 | #include <linux/version.h> | ||
48 | #include <linux/kernel.h> | ||
49 | #include <linux/sched.h> | ||
50 | #include <linux/list.h> | ||
51 | #include <linux/timer.h> | ||
52 | #include <linux/slab.h> | ||
53 | #include <linux/mm.h> | ||
54 | #include <linux/utsname.h> | ||
55 | #include <linux/highmem.h> | ||
56 | #include <linux/smp_lock.h> | ||
57 | #include <linux/videodev.h> | ||
58 | #include <linux/vmalloc.h> | ||
59 | #include <linux/module.h> | ||
60 | #include <linux/init.h> | ||
61 | #include <linux/spinlock.h> | ||
62 | #include <asm/io.h> | ||
63 | #include <linux/videodev2.h> | ||
64 | #include <linux/video_decoder.h> | ||
65 | #include <linux/i2c.h> | ||
66 | |||
67 | #include <media/saa7115.h> | ||
68 | #include <media/v4l2-common.h> | ||
69 | #include <media/tuner.h> | ||
70 | #include <media/audiochip.h> | ||
71 | |||
72 | #include <linux/moduleparam.h> | ||
73 | #include <linux/workqueue.h> | ||
74 | |||
75 | #ifdef CONFIG_KMOD | ||
76 | #include <linux/kmod.h> | ||
77 | #endif | ||
78 | |||
79 | #include "usbvision.h" | ||
80 | |||
81 | #define DRIVER_AUTHOR "Joerg Heckenbach <joerg@heckenbach-aw.de>, Dwaine Garden <DwaineGarden@rogers.com>" | ||
82 | #define DRIVER_NAME "usbvision" | ||
83 | #define DRIVER_ALIAS "USBVision" | ||
84 | #define DRIVER_DESC "USBVision USB Video Device Driver for Linux" | ||
85 | #define DRIVER_LICENSE "GPL" | ||
86 | #define USBVISION_DRIVER_VERSION_MAJOR 0 | ||
87 | #define USBVISION_DRIVER_VERSION_MINOR 9 | ||
88 | #define USBVISION_DRIVER_VERSION_PATCHLEVEL 9 | ||
89 | #define USBVISION_DRIVER_VERSION KERNEL_VERSION(USBVISION_DRIVER_VERSION_MAJOR,USBVISION_DRIVER_VERSION_MINOR,USBVISION_DRIVER_VERSION_PATCHLEVEL) | ||
90 | #define USBVISION_VERSION_STRING __stringify(USBVISION_DRIVER_VERSION_MAJOR) "." __stringify(USBVISION_DRIVER_VERSION_MINOR) "." __stringify(USBVISION_DRIVER_VERSION_PATCHLEVEL) | ||
91 | |||
92 | #define ENABLE_HEXDUMP 0 /* Enable if you need it */ | ||
93 | |||
94 | |||
95 | #ifdef USBVISION_DEBUG | ||
96 | #define PDEBUG(level, fmt, args...) \ | ||
97 | if (video_debug & (level)) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , ## args) | ||
98 | #else | ||
99 | #define PDEBUG(level, fmt, args...) do {} while(0) | ||
100 | #endif | ||
101 | |||
102 | #define DBG_IOCTL 1<<0 | ||
103 | #define DBG_IO 1<<1 | ||
104 | #define DBG_PROBE 1<<2 | ||
105 | #define DBG_MMAP 1<<3 | ||
106 | |||
107 | //String operations | ||
108 | #define rmspace(str) while(*str==' ') str++; | ||
109 | #define goto2next(str) while(*str!=' ') str++; while(*str==' ') str++; | ||
110 | |||
111 | |||
112 | static int usbvision_nr = 0; // sequential number of usbvision device | ||
113 | |||
114 | static struct usbvision_v4l2_format_st usbvision_v4l2_format[] = { | ||
115 | { 1, 1, 8, V4L2_PIX_FMT_GREY , "GREY" }, | ||
116 | { 1, 2, 16, V4L2_PIX_FMT_RGB565 , "RGB565" }, | ||
117 | { 1, 3, 24, V4L2_PIX_FMT_RGB24 , "RGB24" }, | ||
118 | { 1, 4, 32, V4L2_PIX_FMT_RGB32 , "RGB32" }, | ||
119 | { 1, 2, 16, V4L2_PIX_FMT_RGB555 , "RGB555" }, | ||
120 | { 1, 2, 16, V4L2_PIX_FMT_YUYV , "YUV422" }, | ||
121 | { 1, 2, 12, V4L2_PIX_FMT_YVU420 , "YUV420P" }, // 1.5 ! | ||
122 | { 1, 2, 16, V4L2_PIX_FMT_YUV422P , "YUV422P" } | ||
123 | }; | ||
124 | |||
125 | /* supported tv norms */ | ||
126 | static struct usbvision_tvnorm tvnorms[] = { | ||
127 | { | ||
128 | .name = "PAL", | ||
129 | .id = V4L2_STD_PAL, | ||
130 | }, { | ||
131 | .name = "NTSC", | ||
132 | .id = V4L2_STD_NTSC, | ||
133 | }, { | ||
134 | .name = "SECAM", | ||
135 | .id = V4L2_STD_SECAM, | ||
136 | }, { | ||
137 | .name = "PAL-M", | ||
138 | .id = V4L2_STD_PAL_M, | ||
139 | } | ||
140 | }; | ||
141 | |||
142 | #define TVNORMS ARRAY_SIZE(tvnorms) | ||
143 | |||
144 | // Function prototypes | ||
145 | static void usbvision_release(struct usb_usbvision *usbvision); | ||
146 | |||
147 | // Default initalization of device driver parameters | ||
148 | static int isocMode = ISOC_MODE_COMPRESS; // Set the default format for ISOC endpoint | ||
149 | static int video_debug = 0; // Set the default Debug Mode of the device driver | ||
150 | static int PowerOnAtOpen = 1; // Set the default device to power on at startup | ||
151 | static int video_nr = -1; // Sequential Number of Video Device | ||
152 | static int radio_nr = -1; // Sequential Number of Radio Device | ||
153 | static int vbi_nr = -1; // Sequential Number of VBI Device | ||
154 | static char *CustomDevice=NULL; // Set as nothing.... | ||
155 | |||
156 | // Grab parameters for the device driver | ||
157 | |||
158 | #if defined(module_param) // Showing parameters under SYSFS | ||
159 | module_param(isocMode, int, 0444); | ||
160 | module_param(video_debug, int, 0444); | ||
161 | module_param(PowerOnAtOpen, int, 0444); | ||
162 | module_param(video_nr, int, 0444); | ||
163 | module_param(radio_nr, int, 0444); | ||
164 | module_param(vbi_nr, int, 0444); | ||
165 | module_param(CustomDevice, charp, 0444); | ||
166 | #else // Old Style | ||
167 | MODULE_PARAM(isocMode, "i"); | ||
168 | MODULE_PARM(video_debug, "i"); // Grab the Debug Mode of the device driver | ||
169 | MODULE_PARM(adjustCompression, "i"); // Grab the compression to be adaptive | ||
170 | MODULE_PARM(PowerOnAtOpen, "i"); // Grab the device to power on at startup | ||
171 | MODULE_PARM(SwitchSVideoInput, "i"); // To help people with Black and White output with using s-video input. Some cables and input device are wired differently. | ||
172 | MODULE_PARM(video_nr, "i"); // video_nr option allows to specify a certain /dev/videoX device (like /dev/video0 or /dev/video1 ...) | ||
173 | MODULE_PARM(radio_nr, "i"); // radio_nr option allows to specify a certain /dev/radioX device (like /dev/radio0 or /dev/radio1 ...) | ||
174 | MODULE_PARM(vbi_nr, "i"); // vbi_nr option allows to specify a certain /dev/vbiX device (like /dev/vbi0 or /dev/vbi1 ...) | ||
175 | MODULE_PARM(CustomDevice, "s"); // .... CustomDevice | ||
176 | #endif | ||
177 | |||
178 | MODULE_PARM_DESC(isocMode, " Set the default format for ISOC endpoint. Default: 0x60 (Compression On)"); | ||
179 | MODULE_PARM_DESC(video_debug, " Set the default Debug Mode of the device driver. Default: 0 (Off)"); | ||
180 | MODULE_PARM_DESC(PowerOnAtOpen, " Set the default device to power on when device is opened. Default: 1 (On)"); | ||
181 | MODULE_PARM_DESC(video_nr, "Set video device number (/dev/videoX). Default: -1 (autodetect)"); | ||
182 | MODULE_PARM_DESC(radio_nr, "Set radio device number (/dev/radioX). Default: -1 (autodetect)"); | ||
183 | MODULE_PARM_DESC(vbi_nr, "Set vbi device number (/dev/vbiX). Default: -1 (autodetect)"); | ||
184 | MODULE_PARM_DESC(CustomDevice, " Define the fine tuning parameters for the device. Default: null"); | ||
185 | |||
186 | |||
187 | // Misc stuff | ||
188 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
189 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
190 | MODULE_LICENSE(DRIVER_LICENSE); | ||
191 | MODULE_VERSION(USBVISION_VERSION_STRING); | ||
192 | MODULE_ALIAS(DRIVER_ALIAS); | ||
193 | |||
194 | |||
195 | /****************************************************************************************/ | ||
196 | /* SYSFS Code - Copied from the stv680.c usb module. */ | ||
197 | /* Device information is located at /sys/class/video4linux/video0 */ | ||
198 | /* Device parameters information is located at /sys/module/usbvision */ | ||
199 | /* Device USB Information is located at /sys/bus/usb/drivers/USBVision Video Grabber */ | ||
200 | /****************************************************************************************/ | ||
201 | |||
202 | |||
203 | #define YES_NO(x) ((x) ? "Yes" : "No") | ||
204 | |||
205 | static inline struct usb_usbvision *cd_to_usbvision(struct class_device *cd) | ||
206 | { | ||
207 | struct video_device *vdev = to_video_device(cd); | ||
208 | return video_get_drvdata(vdev); | ||
209 | } | ||
210 | |||
211 | static ssize_t show_version(struct class_device *cd, char *buf) | ||
212 | { | ||
213 | return sprintf(buf, "%s\n", USBVISION_VERSION_STRING); | ||
214 | } | ||
215 | static CLASS_DEVICE_ATTR(version, S_IRUGO, show_version, NULL); | ||
216 | |||
217 | static ssize_t show_model(struct class_device *class_dev, char *buf) | ||
218 | { | ||
219 | struct video_device *vdev = to_video_device(class_dev); | ||
220 | struct usb_usbvision *usbvision = video_get_drvdata(vdev); | ||
221 | return sprintf(buf, "%s\n", usbvision_device_data[usbvision->DevModel].ModelString); | ||
222 | } | ||
223 | static CLASS_DEVICE_ATTR(model, S_IRUGO, show_model, NULL); | ||
224 | |||
225 | static ssize_t show_hue(struct class_device *class_dev, char *buf) | ||
226 | { | ||
227 | struct video_device *vdev = to_video_device(class_dev); | ||
228 | struct usb_usbvision *usbvision = video_get_drvdata(vdev); | ||
229 | struct v4l2_control ctrl; | ||
230 | ctrl.id = V4L2_CID_HUE; | ||
231 | ctrl.value = 0; | ||
232 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); | ||
233 | return sprintf(buf, "%d\n", ctrl.value >> 8); | ||
234 | } | ||
235 | static CLASS_DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL); | ||
236 | |||
237 | static ssize_t show_contrast(struct class_device *class_dev, char *buf) | ||
238 | { | ||
239 | struct video_device *vdev = to_video_device(class_dev); | ||
240 | struct usb_usbvision *usbvision = video_get_drvdata(vdev); | ||
241 | struct v4l2_control ctrl; | ||
242 | ctrl.id = V4L2_CID_CONTRAST; | ||
243 | ctrl.value = 0; | ||
244 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); | ||
245 | return sprintf(buf, "%d\n", ctrl.value >> 8); | ||
246 | } | ||
247 | static CLASS_DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL); | ||
248 | |||
249 | static ssize_t show_brightness(struct class_device *class_dev, char *buf) | ||
250 | { | ||
251 | struct video_device *vdev = to_video_device(class_dev); | ||
252 | struct usb_usbvision *usbvision = video_get_drvdata(vdev); | ||
253 | struct v4l2_control ctrl; | ||
254 | ctrl.id = V4L2_CID_BRIGHTNESS; | ||
255 | ctrl.value = 0; | ||
256 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); | ||
257 | return sprintf(buf, "%d\n", ctrl.value >> 8); | ||
258 | } | ||
259 | static CLASS_DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL); | ||
260 | |||
261 | static ssize_t show_saturation(struct class_device *class_dev, char *buf) | ||
262 | { | ||
263 | struct video_device *vdev = to_video_device(class_dev); | ||
264 | struct usb_usbvision *usbvision = video_get_drvdata(vdev); | ||
265 | struct v4l2_control ctrl; | ||
266 | ctrl.id = V4L2_CID_SATURATION; | ||
267 | ctrl.value = 0; | ||
268 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); | ||
269 | return sprintf(buf, "%d\n", ctrl.value >> 8); | ||
270 | } | ||
271 | static CLASS_DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL); | ||
272 | |||
273 | static ssize_t show_streaming(struct class_device *class_dev, char *buf) | ||
274 | { | ||
275 | struct video_device *vdev = to_video_device(class_dev); | ||
276 | struct usb_usbvision *usbvision = video_get_drvdata(vdev); | ||
277 | return sprintf(buf, "%s\n", YES_NO(usbvision->streaming==Stream_On?1:0)); | ||
278 | } | ||
279 | static CLASS_DEVICE_ATTR(streaming, S_IRUGO, show_streaming, NULL); | ||
280 | |||
281 | static ssize_t show_compression(struct class_device *class_dev, char *buf) | ||
282 | { | ||
283 | struct video_device *vdev = to_video_device(class_dev); | ||
284 | struct usb_usbvision *usbvision = video_get_drvdata(vdev); | ||
285 | return sprintf(buf, "%s\n", YES_NO(usbvision->isocMode==ISOC_MODE_COMPRESS)); | ||
286 | } | ||
287 | static CLASS_DEVICE_ATTR(compression, S_IRUGO, show_compression, NULL); | ||
288 | |||
289 | static ssize_t show_device_bridge(struct class_device *class_dev, char *buf) | ||
290 | { | ||
291 | struct video_device *vdev = to_video_device(class_dev); | ||
292 | struct usb_usbvision *usbvision = video_get_drvdata(vdev); | ||
293 | return sprintf(buf, "%d\n", usbvision->bridgeType); | ||
294 | } | ||
295 | static CLASS_DEVICE_ATTR(bridge, S_IRUGO, show_device_bridge, NULL); | ||
296 | |||
297 | static void usbvision_create_sysfs(struct video_device *vdev) | ||
298 | { | ||
299 | int res; | ||
300 | if (vdev) { | ||
301 | res=video_device_create_file(vdev, &class_device_attr_version); | ||
302 | res=video_device_create_file(vdev, &class_device_attr_model); | ||
303 | res=video_device_create_file(vdev, &class_device_attr_hue); | ||
304 | res=video_device_create_file(vdev, &class_device_attr_contrast); | ||
305 | res=video_device_create_file(vdev, &class_device_attr_brightness); | ||
306 | res=video_device_create_file(vdev, &class_device_attr_saturation); | ||
307 | res=video_device_create_file(vdev, &class_device_attr_streaming); | ||
308 | res=video_device_create_file(vdev, &class_device_attr_compression); | ||
309 | res=video_device_create_file(vdev, &class_device_attr_bridge); | ||
310 | } | ||
311 | } | ||
312 | |||
313 | static void usbvision_remove_sysfs(struct video_device *vdev) | ||
314 | { | ||
315 | if (vdev) { | ||
316 | video_device_remove_file(vdev, &class_device_attr_version); | ||
317 | video_device_remove_file(vdev, &class_device_attr_model); | ||
318 | video_device_remove_file(vdev, &class_device_attr_hue); | ||
319 | video_device_remove_file(vdev, &class_device_attr_contrast); | ||
320 | video_device_remove_file(vdev, &class_device_attr_brightness); | ||
321 | video_device_remove_file(vdev, &class_device_attr_saturation); | ||
322 | video_device_remove_file(vdev, &class_device_attr_streaming); | ||
323 | video_device_remove_file(vdev, &class_device_attr_compression); | ||
324 | video_device_remove_file(vdev, &class_device_attr_bridge); | ||
325 | } | ||
326 | } | ||
327 | |||
328 | |||
329 | /* | ||
330 | * usbvision_open() | ||
331 | * | ||
332 | * This is part of Video 4 Linux API. The driver can be opened by one | ||
333 | * client only (checks internal counter 'usbvision->user'). The procedure | ||
334 | * then allocates buffers needed for video processing. | ||
335 | * | ||
336 | */ | ||
337 | static int usbvision_v4l2_open(struct inode *inode, struct file *file) | ||
338 | { | ||
339 | struct video_device *dev = video_devdata(file); | ||
340 | struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); | ||
341 | int errCode = 0; | ||
342 | |||
343 | PDEBUG(DBG_IO, "open"); | ||
344 | |||
345 | |||
346 | usbvision_reset_powerOffTimer(usbvision); | ||
347 | |||
348 | if (usbvision->user) | ||
349 | errCode = -EBUSY; | ||
350 | else { | ||
351 | /* Allocate memory for the frame buffers */ | ||
352 | errCode = usbvision_frames_alloc(usbvision); | ||
353 | if(!errCode) { | ||
354 | /* Allocate memory for the scratch ring buffer */ | ||
355 | errCode = usbvision_scratch_alloc(usbvision); | ||
356 | if(!errCode) { | ||
357 | /* Allocate memory for the USB S buffers */ | ||
358 | errCode = usbvision_sbuf_alloc(usbvision); | ||
359 | if ((!errCode) && (usbvision->isocMode==ISOC_MODE_COMPRESS)) { | ||
360 | /* Allocate intermediate decompression buffers only if needed */ | ||
361 | errCode = usbvision_decompress_alloc(usbvision); | ||
362 | } | ||
363 | } | ||
364 | } | ||
365 | if (errCode) { | ||
366 | /* Deallocate all buffers if trouble */ | ||
367 | usbvision_frames_free(usbvision); | ||
368 | usbvision_scratch_free(usbvision); | ||
369 | usbvision_sbuf_free(usbvision); | ||
370 | usbvision_decompress_free(usbvision); | ||
371 | } | ||
372 | } | ||
373 | |||
374 | /* If so far no errors then we shall start the camera */ | ||
375 | if (!errCode) { | ||
376 | down(&usbvision->lock); | ||
377 | if (usbvision->power == 0) { | ||
378 | usbvision_power_on(usbvision); | ||
379 | usbvision_init_i2c(usbvision); | ||
380 | } | ||
381 | |||
382 | /* Send init sequence only once, it's large! */ | ||
383 | if (!usbvision->initialized) { | ||
384 | int setup_ok = 0; | ||
385 | setup_ok = usbvision_setup(usbvision,isocMode); | ||
386 | if (setup_ok) | ||
387 | usbvision->initialized = 1; | ||
388 | else | ||
389 | errCode = -EBUSY; | ||
390 | } | ||
391 | |||
392 | if (!errCode) { | ||
393 | usbvision_begin_streaming(usbvision); | ||
394 | errCode = usbvision_init_isoc(usbvision); | ||
395 | /* device needs to be initialized before isoc transfer */ | ||
396 | usbvision_muxsel(usbvision,0); | ||
397 | usbvision->user++; | ||
398 | } | ||
399 | else { | ||
400 | if (PowerOnAtOpen) { | ||
401 | usbvision_i2c_usb_del_bus(&usbvision->i2c_adap); | ||
402 | usbvision_power_off(usbvision); | ||
403 | usbvision->initialized = 0; | ||
404 | } | ||
405 | } | ||
406 | up(&usbvision->lock); | ||
407 | } | ||
408 | |||
409 | if (errCode) { | ||
410 | } | ||
411 | |||
412 | /* prepare queues */ | ||
413 | usbvision_empty_framequeues(usbvision); | ||
414 | |||
415 | PDEBUG(DBG_IO, "success"); | ||
416 | return errCode; | ||
417 | } | ||
418 | |||
419 | /* | ||
420 | * usbvision_v4l2_close() | ||
421 | * | ||
422 | * This is part of Video 4 Linux API. The procedure | ||
423 | * stops streaming and deallocates all buffers that were earlier | ||
424 | * allocated in usbvision_v4l2_open(). | ||
425 | * | ||
426 | */ | ||
427 | static int usbvision_v4l2_close(struct inode *inode, struct file *file) | ||
428 | { | ||
429 | struct video_device *dev = video_devdata(file); | ||
430 | struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); | ||
431 | |||
432 | PDEBUG(DBG_IO, "close"); | ||
433 | down(&usbvision->lock); | ||
434 | |||
435 | usbvision_audio_off(usbvision); | ||
436 | usbvision_restart_isoc(usbvision); | ||
437 | usbvision_stop_isoc(usbvision); | ||
438 | |||
439 | usbvision_decompress_free(usbvision); | ||
440 | usbvision_rvfree(usbvision->fbuf, usbvision->fbuf_size); | ||
441 | usbvision_scratch_free(usbvision); | ||
442 | usbvision_sbuf_free(usbvision); | ||
443 | |||
444 | usbvision->user--; | ||
445 | |||
446 | if (PowerOnAtOpen) { | ||
447 | /* power off in a little while to avoid off/on every close/open short sequences */ | ||
448 | usbvision_set_powerOffTimer(usbvision); | ||
449 | usbvision->initialized = 0; | ||
450 | } | ||
451 | |||
452 | up(&usbvision->lock); | ||
453 | |||
454 | if (usbvision->remove_pending) { | ||
455 | info("%s: Final disconnect", __FUNCTION__); | ||
456 | usbvision_release(usbvision); | ||
457 | } | ||
458 | |||
459 | PDEBUG(DBG_IO, "success"); | ||
460 | |||
461 | |||
462 | return 0; | ||
463 | } | ||
464 | |||
465 | |||
466 | /* | ||
467 | * usbvision_ioctl() | ||
468 | * | ||
469 | * This is part of Video 4 Linux API. The procedure handles ioctl() calls. | ||
470 | * | ||
471 | */ | ||
472 | static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, | ||
473 | unsigned int cmd, void *arg) | ||
474 | { | ||
475 | struct video_device *dev = video_devdata(file); | ||
476 | struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); | ||
477 | |||
478 | if (!USBVISION_IS_OPERATIONAL(usbvision)) | ||
479 | return -EFAULT; | ||
480 | |||
481 | switch (cmd) { | ||
482 | |||
483 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
484 | /* ioctls to allow direct acces to the NT100x registers */ | ||
485 | case VIDIOC_INT_G_REGISTER: | ||
486 | { | ||
487 | struct v4l2_register *reg = arg; | ||
488 | int errCode; | ||
489 | |||
490 | if (reg->i2c_id != 0) | ||
491 | return -EINVAL; | ||
492 | /* NT100x has a 8-bit register space */ | ||
493 | errCode = usbvision_read_reg(usbvision, reg->reg&0xff); | ||
494 | if (errCode < 0) { | ||
495 | err("%s: VIDIOC_INT_G_REGISTER failed: error %d", __FUNCTION__, errCode); | ||
496 | } | ||
497 | else { | ||
498 | reg->val=(unsigned char)errCode; | ||
499 | PDEBUG(DBG_IOCTL, "VIDIOC_INT_G_REGISTER reg=0x%02X, value=0x%02X", | ||
500 | (unsigned int)reg->reg, reg->val); | ||
501 | errCode = 0; // No error | ||
502 | } | ||
503 | return errCode; | ||
504 | } | ||
505 | case VIDIOC_INT_S_REGISTER: | ||
506 | { | ||
507 | struct v4l2_register *reg = arg; | ||
508 | int errCode; | ||
509 | |||
510 | if (reg->i2c_id != 0) | ||
511 | return -EINVAL; | ||
512 | if (!capable(CAP_SYS_ADMIN)) | ||
513 | return -EPERM; | ||
514 | errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val); | ||
515 | if (errCode < 0) { | ||
516 | err("%s: VIDIOC_INT_S_REGISTER failed: error %d", __FUNCTION__, errCode); | ||
517 | } | ||
518 | else { | ||
519 | PDEBUG(DBG_IOCTL, "VIDIOC_INT_S_REGISTER reg=0x%02X, value=0x%02X", | ||
520 | (unsigned int)reg->reg, reg->val); | ||
521 | errCode = 0; | ||
522 | } | ||
523 | return 0; | ||
524 | } | ||
525 | #endif | ||
526 | case VIDIOC_QUERYCAP: | ||
527 | { | ||
528 | struct v4l2_capability *vc=arg; | ||
529 | |||
530 | memset(vc, 0, sizeof(*vc)); | ||
531 | strlcpy(vc->driver, "USBVision", sizeof(vc->driver)); | ||
532 | strlcpy(vc->card, usbvision_device_data[usbvision->DevModel].ModelString, | ||
533 | sizeof(vc->card)); | ||
534 | strlcpy(vc->bus_info, usbvision->dev->dev.bus_id, | ||
535 | sizeof(vc->bus_info)); | ||
536 | vc->version = USBVISION_DRIVER_VERSION; | ||
537 | vc->capabilities = V4L2_CAP_VIDEO_CAPTURE | | ||
538 | V4L2_CAP_AUDIO | | ||
539 | V4L2_CAP_READWRITE | | ||
540 | V4L2_CAP_STREAMING | | ||
541 | (usbvision->have_tuner ? V4L2_CAP_TUNER : 0); | ||
542 | PDEBUG(DBG_IOCTL, "VIDIOC_QUERYCAP"); | ||
543 | return 0; | ||
544 | } | ||
545 | case VIDIOC_ENUMINPUT: | ||
546 | { | ||
547 | struct v4l2_input *vi = arg; | ||
548 | int chan; | ||
549 | |||
550 | if ((vi->index >= usbvision->video_inputs) || (vi->index < 0) ) | ||
551 | return -EINVAL; | ||
552 | if (usbvision->have_tuner) { | ||
553 | chan = vi->index; | ||
554 | } | ||
555 | else { | ||
556 | chan = vi->index + 1; //skip Television string | ||
557 | } | ||
558 | switch(chan) { | ||
559 | case 0: | ||
560 | if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { | ||
561 | strcpy(vi->name, "White Video Input"); | ||
562 | } | ||
563 | else { | ||
564 | strcpy(vi->name, "Television"); | ||
565 | vi->type = V4L2_INPUT_TYPE_TUNER; | ||
566 | vi->audioset = 1; | ||
567 | vi->tuner = chan; | ||
568 | vi->std = V4L2_STD_PAL | V4L2_STD_NTSC | V4L2_STD_SECAM; | ||
569 | } | ||
570 | break; | ||
571 | case 1: | ||
572 | vi->type = V4L2_INPUT_TYPE_CAMERA; | ||
573 | if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { | ||
574 | strcpy(vi->name, "Green Video Input"); | ||
575 | } | ||
576 | else { | ||
577 | strcpy(vi->name, "Composite Video Input"); | ||
578 | } | ||
579 | vi->std = V4L2_STD_PAL; | ||
580 | break; | ||
581 | case 2: | ||
582 | vi->type = V4L2_INPUT_TYPE_CAMERA; | ||
583 | if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { | ||
584 | strcpy(vi->name, "Yellow Video Input"); | ||
585 | } | ||
586 | else { | ||
587 | strcpy(vi->name, "S-Video Input"); | ||
588 | } | ||
589 | vi->std = V4L2_STD_PAL; | ||
590 | break; | ||
591 | case 3: | ||
592 | vi->type = V4L2_INPUT_TYPE_CAMERA; | ||
593 | strcpy(vi->name, "Red Video Input"); | ||
594 | vi->std = V4L2_STD_PAL; | ||
595 | break; | ||
596 | } | ||
597 | PDEBUG(DBG_IOCTL, "VIDIOC_ENUMINPUT name=%s:%d tuners=%d type=%d norm=%x", | ||
598 | vi->name, vi->index, vi->tuner,vi->type,(int)vi->std); | ||
599 | return 0; | ||
600 | } | ||
601 | case VIDIOC_ENUMSTD: | ||
602 | { | ||
603 | struct v4l2_standard *e = arg; | ||
604 | unsigned int i; | ||
605 | int ret; | ||
606 | |||
607 | i = e->index; | ||
608 | if (i >= TVNORMS) | ||
609 | return -EINVAL; | ||
610 | ret = v4l2_video_std_construct(e, tvnorms[e->index].id, | ||
611 | tvnorms[e->index].name); | ||
612 | e->index = i; | ||
613 | if (ret < 0) | ||
614 | return ret; | ||
615 | return 0; | ||
616 | } | ||
617 | case VIDIOC_G_INPUT: | ||
618 | { | ||
619 | int *input = arg; | ||
620 | *input = usbvision->ctl_input; | ||
621 | return 0; | ||
622 | } | ||
623 | case VIDIOC_S_INPUT: | ||
624 | { | ||
625 | int *input = arg; | ||
626 | if ((*input >= usbvision->video_inputs) || (*input < 0) ) | ||
627 | return -EINVAL; | ||
628 | usbvision->ctl_input = *input; | ||
629 | |||
630 | down(&usbvision->lock); | ||
631 | usbvision_muxsel(usbvision, usbvision->ctl_input); | ||
632 | usbvision_set_input(usbvision); | ||
633 | usbvision_set_output(usbvision, usbvision->curwidth, usbvision->curheight); | ||
634 | up(&usbvision->lock); | ||
635 | return 0; | ||
636 | } | ||
637 | case VIDIOC_G_STD: | ||
638 | { | ||
639 | v4l2_std_id *id = arg; | ||
640 | |||
641 | *id = usbvision->tvnorm->id; | ||
642 | |||
643 | PDEBUG(DBG_IOCTL, "VIDIOC_G_STD std_id=%s", usbvision->tvnorm->name); | ||
644 | return 0; | ||
645 | } | ||
646 | case VIDIOC_S_STD: | ||
647 | { | ||
648 | v4l2_std_id *id = arg; | ||
649 | unsigned int i; | ||
650 | |||
651 | for (i = 0; i < TVNORMS; i++) | ||
652 | if (*id == tvnorms[i].id) | ||
653 | break; | ||
654 | if (i == TVNORMS) | ||
655 | for (i = 0; i < TVNORMS; i++) | ||
656 | if (*id & tvnorms[i].id) | ||
657 | break; | ||
658 | if (i == TVNORMS) | ||
659 | return -EINVAL; | ||
660 | |||
661 | down(&usbvision->lock); | ||
662 | usbvision->tvnorm = &tvnorms[i]; | ||
663 | |||
664 | call_i2c_clients(usbvision, VIDIOC_S_STD, | ||
665 | &usbvision->tvnorm->id); | ||
666 | |||
667 | up(&usbvision->lock); | ||
668 | |||
669 | PDEBUG(DBG_IOCTL, "VIDIOC_S_STD std_id=%s", usbvision->tvnorm->name); | ||
670 | return 0; | ||
671 | } | ||
672 | case VIDIOC_G_TUNER: | ||
673 | { | ||
674 | struct v4l2_tuner *vt = arg; | ||
675 | |||
676 | if (!usbvision->have_tuner || vt->index) // Only tuner 0 | ||
677 | return -EINVAL; | ||
678 | strcpy(vt->name, "Television"); | ||
679 | /* Let clients fill in the remainder of this struct */ | ||
680 | call_i2c_clients(usbvision,VIDIOC_G_TUNER,vt); | ||
681 | |||
682 | PDEBUG(DBG_IOCTL, "VIDIOC_G_TUNER signal=%x, afc=%x",vt->signal,vt->afc); | ||
683 | return 0; | ||
684 | } | ||
685 | case VIDIOC_S_TUNER: | ||
686 | { | ||
687 | struct v4l2_tuner *vt = arg; | ||
688 | |||
689 | // Only no or one tuner for now | ||
690 | if (!usbvision->have_tuner || vt->index) | ||
691 | return -EINVAL; | ||
692 | /* let clients handle this */ | ||
693 | call_i2c_clients(usbvision,VIDIOC_S_TUNER,vt); | ||
694 | |||
695 | PDEBUG(DBG_IOCTL, "VIDIOC_S_TUNER"); | ||
696 | return 0; | ||
697 | } | ||
698 | case VIDIOC_G_FREQUENCY: | ||
699 | { | ||
700 | struct v4l2_frequency *freq = arg; | ||
701 | |||
702 | freq->tuner = 0; // Only one tuner | ||
703 | freq->type = V4L2_TUNER_ANALOG_TV; | ||
704 | freq->frequency = usbvision->freq; | ||
705 | PDEBUG(DBG_IOCTL, "VIDIOC_G_FREQUENCY freq=0x%X", (unsigned)freq->frequency); | ||
706 | return 0; | ||
707 | } | ||
708 | case VIDIOC_S_FREQUENCY: | ||
709 | { | ||
710 | struct v4l2_frequency *freq = arg; | ||
711 | |||
712 | // Only no or one tuner for now | ||
713 | if (!usbvision->have_tuner || freq->tuner) | ||
714 | return -EINVAL; | ||
715 | |||
716 | usbvision->freq = freq->frequency; | ||
717 | call_i2c_clients(usbvision, cmd, freq); | ||
718 | PDEBUG(DBG_IOCTL, "VIDIOC_S_FREQUENCY freq=0x%X", (unsigned)freq->frequency); | ||
719 | return 0; | ||
720 | } | ||
721 | case VIDIOC_G_AUDIO: | ||
722 | { | ||
723 | struct v4l2_audio *v = arg; | ||
724 | memset(v,0, sizeof(v)); | ||
725 | strcpy(v->name, "TV"); | ||
726 | PDEBUG(DBG_IOCTL, "VIDIOC_G_AUDIO"); | ||
727 | return 0; | ||
728 | } | ||
729 | case VIDIOC_S_AUDIO: | ||
730 | { | ||
731 | struct v4l2_audio *v = arg; | ||
732 | if(v->index) { | ||
733 | return -EINVAL; | ||
734 | } | ||
735 | PDEBUG(DBG_IOCTL, "VIDIOC_S_AUDIO"); | ||
736 | return 0; | ||
737 | } | ||
738 | case VIDIOC_QUERYCTRL: | ||
739 | { | ||
740 | struct v4l2_queryctrl *ctrl = arg; | ||
741 | int id=ctrl->id; | ||
742 | |||
743 | memset(ctrl,0,sizeof(*ctrl)); | ||
744 | ctrl->id=id; | ||
745 | |||
746 | call_i2c_clients(usbvision, cmd, arg); | ||
747 | |||
748 | if (ctrl->type) | ||
749 | return 0; | ||
750 | else | ||
751 | return -EINVAL; | ||
752 | |||
753 | PDEBUG(DBG_IOCTL,"VIDIOC_QUERYCTRL id=%x value=%x",ctrl->id,ctrl->type); | ||
754 | } | ||
755 | case VIDIOC_G_CTRL: | ||
756 | { | ||
757 | struct v4l2_control *ctrl = arg; | ||
758 | PDEBUG(DBG_IOCTL,"VIDIOC_G_CTRL id=%x value=%x",ctrl->id,ctrl->value); | ||
759 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl); | ||
760 | return 0; | ||
761 | } | ||
762 | case VIDIOC_S_CTRL: | ||
763 | { | ||
764 | struct v4l2_control *ctrl = arg; | ||
765 | |||
766 | PDEBUG(DBG_IOCTL, "VIDIOC_S_CTRL id=%x value=%x",ctrl->id,ctrl->value); | ||
767 | call_i2c_clients(usbvision, VIDIOC_S_CTRL, ctrl); | ||
768 | return 0; | ||
769 | } | ||
770 | case VIDIOC_REQBUFS: | ||
771 | { | ||
772 | struct v4l2_requestbuffers *vr = arg; | ||
773 | int ret; | ||
774 | |||
775 | RESTRICT_TO_RANGE(vr->count,1,USBVISION_NUMFRAMES); | ||
776 | |||
777 | // Check input validity : the user must do a VIDEO CAPTURE and MMAP method. | ||
778 | if((vr->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) || | ||
779 | (vr->memory != V4L2_MEMORY_MMAP)) | ||
780 | return -EINVAL; | ||
781 | |||
782 | if(usbvision->streaming == Stream_On) { | ||
783 | if ((ret = usbvision_stream_interrupt(usbvision))) | ||
784 | return ret; | ||
785 | } | ||
786 | |||
787 | usbvision_empty_framequeues(usbvision); | ||
788 | |||
789 | usbvision->curFrame = NULL; | ||
790 | |||
791 | PDEBUG(DBG_IOCTL, "VIDIOC_REQBUFS count=%d",vr->count); | ||
792 | return 0; | ||
793 | } | ||
794 | case VIDIOC_QUERYBUF: | ||
795 | { | ||
796 | struct v4l2_buffer *vb = arg; | ||
797 | struct usbvision_frame *frame; | ||
798 | |||
799 | // FIXME : must control that buffers are mapped (VIDIOC_REQBUFS has been called) | ||
800 | |||
801 | if(vb->type != V4L2_CAP_VIDEO_CAPTURE) { | ||
802 | return -EINVAL; | ||
803 | } | ||
804 | if(vb->index>=USBVISION_NUMFRAMES) { | ||
805 | return -EINVAL; | ||
806 | } | ||
807 | // Updating the corresponding frame state | ||
808 | vb->flags = 0; | ||
809 | frame = &usbvision->frame[vb->index]; | ||
810 | if(frame->grabstate >= FrameState_Ready) | ||
811 | vb->flags |= V4L2_BUF_FLAG_QUEUED; | ||
812 | if(frame->grabstate >= FrameState_Done) | ||
813 | vb->flags |= V4L2_BUF_FLAG_DONE; | ||
814 | if(frame->grabstate == FrameState_Unused) | ||
815 | vb->flags |= V4L2_BUF_FLAG_MAPPED; | ||
816 | vb->memory = V4L2_MEMORY_MMAP; | ||
817 | |||
818 | vb->m.offset = vb->index*usbvision->max_frame_size; | ||
819 | |||
820 | vb->memory = V4L2_MEMORY_MMAP; | ||
821 | vb->field = V4L2_FIELD_NONE; | ||
822 | vb->length = usbvision->curwidth*usbvision->curheight*usbvision->palette.bytes_per_pixel; | ||
823 | vb->timestamp = usbvision->frame[vb->index].timestamp; | ||
824 | vb->sequence = usbvision->frame[vb->index].sequence; | ||
825 | return 0; | ||
826 | } | ||
827 | case VIDIOC_QBUF: | ||
828 | { | ||
829 | struct v4l2_buffer *vb = arg; | ||
830 | struct usbvision_frame *frame; | ||
831 | unsigned long lock_flags; | ||
832 | |||
833 | // FIXME : works only on VIDEO_CAPTURE MODE, MMAP. | ||
834 | if(vb->type != V4L2_CAP_VIDEO_CAPTURE) { | ||
835 | return -EINVAL; | ||
836 | } | ||
837 | if(vb->index>=USBVISION_NUMFRAMES) { | ||
838 | return -EINVAL; | ||
839 | } | ||
840 | |||
841 | frame = &usbvision->frame[vb->index]; | ||
842 | |||
843 | if (frame->grabstate != FrameState_Unused) { | ||
844 | return -EAGAIN; | ||
845 | } | ||
846 | |||
847 | /* Mark it as ready and enqueue frame */ | ||
848 | frame->grabstate = FrameState_Ready; | ||
849 | frame->scanstate = ScanState_Scanning; | ||
850 | frame->scanlength = 0; /* Accumulated in usbvision_parse_data() */ | ||
851 | |||
852 | vb->flags &= ~V4L2_BUF_FLAG_DONE; | ||
853 | |||
854 | /* set v4l2_format index */ | ||
855 | frame->v4l2_format = usbvision->palette; | ||
856 | |||
857 | spin_lock_irqsave(&usbvision->queue_lock, lock_flags); | ||
858 | list_add_tail(&usbvision->frame[vb->index].frame, &usbvision->inqueue); | ||
859 | spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); | ||
860 | |||
861 | PDEBUG(DBG_IOCTL, "VIDIOC_QBUF frame #%d",vb->index); | ||
862 | return 0; | ||
863 | } | ||
864 | case VIDIOC_DQBUF: | ||
865 | { | ||
866 | struct v4l2_buffer *vb = arg; | ||
867 | int ret; | ||
868 | struct usbvision_frame *f; | ||
869 | unsigned long lock_flags; | ||
870 | |||
871 | if (vb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
872 | return -EINVAL; | ||
873 | |||
874 | if (list_empty(&(usbvision->outqueue))) { | ||
875 | if (usbvision->streaming == Stream_Idle) | ||
876 | return -EINVAL; | ||
877 | ret = wait_event_interruptible | ||
878 | (usbvision->wait_frame, | ||
879 | !list_empty(&(usbvision->outqueue))); | ||
880 | if (ret) | ||
881 | return ret; | ||
882 | } | ||
883 | |||
884 | spin_lock_irqsave(&usbvision->queue_lock, lock_flags); | ||
885 | f = list_entry(usbvision->outqueue.next, | ||
886 | struct usbvision_frame, frame); | ||
887 | list_del(usbvision->outqueue.next); | ||
888 | spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); | ||
889 | |||
890 | f->grabstate = FrameState_Unused; | ||
891 | |||
892 | vb->memory = V4L2_MEMORY_MMAP; | ||
893 | vb->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE; | ||
894 | vb->index = f->index; | ||
895 | vb->sequence = f->sequence; | ||
896 | vb->timestamp = f->timestamp; | ||
897 | vb->field = V4L2_FIELD_NONE; | ||
898 | vb->bytesused = f->scanlength; | ||
899 | |||
900 | return 0; | ||
901 | } | ||
902 | case VIDIOC_STREAMON: | ||
903 | { | ||
904 | int b=V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
905 | |||
906 | usbvision->streaming = Stream_On; | ||
907 | |||
908 | call_i2c_clients(usbvision,VIDIOC_STREAMON , &b); | ||
909 | |||
910 | PDEBUG(DBG_IOCTL, "VIDIOC_STREAMON"); | ||
911 | |||
912 | return 0; | ||
913 | } | ||
914 | case VIDIOC_STREAMOFF: | ||
915 | { | ||
916 | int *type = arg; | ||
917 | int b=V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
918 | |||
919 | if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
920 | return -EINVAL; | ||
921 | |||
922 | if(usbvision->streaming == Stream_On) { | ||
923 | usbvision_stream_interrupt(usbvision); | ||
924 | // Stop all video streamings | ||
925 | call_i2c_clients(usbvision,VIDIOC_STREAMOFF , &b); | ||
926 | } | ||
927 | usbvision_empty_framequeues(usbvision); | ||
928 | |||
929 | PDEBUG(DBG_IOCTL, "VIDIOC_STREAMOFF"); | ||
930 | return 0; | ||
931 | } | ||
932 | case VIDIOC_ENUM_FMT: | ||
933 | { | ||
934 | struct v4l2_fmtdesc *vfd = arg; | ||
935 | |||
936 | if(vfd->index>=USBVISION_SUPPORTED_PALETTES-1) { | ||
937 | return -EINVAL; | ||
938 | } | ||
939 | vfd->flags = 0; | ||
940 | vfd->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
941 | strcpy(vfd->description,usbvision_v4l2_format[vfd->index].desc); | ||
942 | vfd->pixelformat = usbvision_v4l2_format[vfd->index].format; | ||
943 | memset(vfd->reserved, 0, sizeof(vfd->reserved)); | ||
944 | return 0; | ||
945 | } | ||
946 | case VIDIOC_G_FMT: | ||
947 | { | ||
948 | struct v4l2_format *vf = arg; | ||
949 | |||
950 | switch (vf->type) { | ||
951 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
952 | { | ||
953 | vf->fmt.pix.width = usbvision->curwidth; | ||
954 | vf->fmt.pix.height = usbvision->curheight; | ||
955 | vf->fmt.pix.pixelformat = usbvision->palette.format; | ||
956 | vf->fmt.pix.bytesperline = usbvision->curwidth*usbvision->palette.bytes_per_pixel; | ||
957 | vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline*usbvision->curheight; | ||
958 | vf->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
959 | vf->fmt.pix.field = V4L2_FIELD_NONE; /* Always progressive image */ | ||
960 | PDEBUG(DBG_IOCTL, "VIDIOC_G_FMT w=%d, h=%d, format=%s", | ||
961 | vf->fmt.pix.width, vf->fmt.pix.height,usbvision->palette.desc); | ||
962 | return 0; | ||
963 | } | ||
964 | default: | ||
965 | PDEBUG(DBG_IOCTL, "VIDIOC_G_FMT invalid type %d",vf->type); | ||
966 | return -EINVAL; | ||
967 | } | ||
968 | return 0; | ||
969 | } | ||
970 | case VIDIOC_TRY_FMT: | ||
971 | case VIDIOC_S_FMT: | ||
972 | { | ||
973 | struct v4l2_format *vf = arg; | ||
974 | int formatIdx,ret; | ||
975 | |||
976 | switch(vf->type) { | ||
977 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
978 | { | ||
979 | /* Find requested format in available ones */ | ||
980 | for(formatIdx=0;formatIdx<USBVISION_SUPPORTED_PALETTES;formatIdx++) { | ||
981 | if(vf->fmt.pix.pixelformat == usbvision_v4l2_format[formatIdx].format) { | ||
982 | usbvision->palette = usbvision_v4l2_format[formatIdx]; | ||
983 | break; | ||
984 | } | ||
985 | } | ||
986 | /* robustness */ | ||
987 | if(formatIdx == USBVISION_SUPPORTED_PALETTES) { | ||
988 | return -EINVAL; | ||
989 | } | ||
990 | RESTRICT_TO_RANGE(vf->fmt.pix.width, MIN_FRAME_WIDTH, MAX_FRAME_WIDTH); | ||
991 | RESTRICT_TO_RANGE(vf->fmt.pix.height, MIN_FRAME_HEIGHT, MAX_FRAME_HEIGHT); | ||
992 | |||
993 | vf->fmt.pix.bytesperline = vf->fmt.pix.width*usbvision->palette.bytes_per_pixel; | ||
994 | vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline*vf->fmt.pix.height; | ||
995 | |||
996 | if(cmd == VIDIOC_TRY_FMT) { | ||
997 | PDEBUG(DBG_IOCTL, "VIDIOC_TRY_FMT grabdisplay w=%d, h=%d, format=%s", | ||
998 | vf->fmt.pix.width, vf->fmt.pix.height,usbvision->palette.desc); | ||
999 | return 0; | ||
1000 | } | ||
1001 | |||
1002 | /* stop io in case it is already in progress */ | ||
1003 | if(usbvision->streaming == Stream_On) { | ||
1004 | if ((ret = usbvision_stream_interrupt(usbvision))) | ||
1005 | return ret; | ||
1006 | } | ||
1007 | usbvision_empty_framequeues(usbvision); | ||
1008 | |||
1009 | usbvision->curFrame = NULL; | ||
1010 | |||
1011 | // by now we are committed to the new data... | ||
1012 | down(&usbvision->lock); | ||
1013 | usbvision_set_output(usbvision, vf->fmt.pix.width, vf->fmt.pix.height); | ||
1014 | up(&usbvision->lock); | ||
1015 | |||
1016 | PDEBUG(DBG_IOCTL, "VIDIOC_S_FMT grabdisplay w=%d, h=%d, format=%s", | ||
1017 | vf->fmt.pix.width, vf->fmt.pix.height,usbvision->palette.desc); | ||
1018 | return 0; | ||
1019 | } | ||
1020 | default: | ||
1021 | return -EINVAL; | ||
1022 | } | ||
1023 | } | ||
1024 | default: | ||
1025 | return -ENOIOCTLCMD; | ||
1026 | } | ||
1027 | return 0; | ||
1028 | } | ||
1029 | |||
1030 | static int usbvision_v4l2_ioctl(struct inode *inode, struct file *file, | ||
1031 | unsigned int cmd, unsigned long arg) | ||
1032 | { | ||
1033 | return video_usercopy(inode, file, cmd, arg, usbvision_v4l2_do_ioctl); | ||
1034 | } | ||
1035 | |||
1036 | |||
1037 | static ssize_t usbvision_v4l2_read(struct file *file, char *buf, | ||
1038 | size_t count, loff_t *ppos) | ||
1039 | { | ||
1040 | struct video_device *dev = video_devdata(file); | ||
1041 | struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); | ||
1042 | int noblock = file->f_flags & O_NONBLOCK; | ||
1043 | unsigned long lock_flags; | ||
1044 | |||
1045 | int frmx = -1; | ||
1046 | int ret,i; | ||
1047 | struct usbvision_frame *frame; | ||
1048 | |||
1049 | PDEBUG(DBG_IO, "%s: %ld bytes, noblock=%d", __FUNCTION__, (unsigned long)count, noblock); | ||
1050 | |||
1051 | if (!USBVISION_IS_OPERATIONAL(usbvision) || (buf == NULL)) | ||
1052 | return -EFAULT; | ||
1053 | |||
1054 | /* no stream is running, make it running ! */ | ||
1055 | usbvision->streaming = Stream_On; | ||
1056 | call_i2c_clients(usbvision,VIDIOC_STREAMON , NULL); | ||
1057 | |||
1058 | /* First, enqueue as many frames as possible (like a user of VIDIOC_QBUF would do) */ | ||
1059 | for(i=0;i<USBVISION_NUMFRAMES;i++) { | ||
1060 | frame = &usbvision->frame[i]; | ||
1061 | if(frame->grabstate == FrameState_Unused) { | ||
1062 | /* Mark it as ready and enqueue frame */ | ||
1063 | frame->grabstate = FrameState_Ready; | ||
1064 | frame->scanstate = ScanState_Scanning; | ||
1065 | frame->scanlength = 0; /* Accumulated in usbvision_parse_data() */ | ||
1066 | |||
1067 | /* set v4l2_format index */ | ||
1068 | frame->v4l2_format = usbvision->palette; | ||
1069 | |||
1070 | spin_lock_irqsave(&usbvision->queue_lock, lock_flags); | ||
1071 | list_add_tail(&frame->frame, &usbvision->inqueue); | ||
1072 | spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); | ||
1073 | } | ||
1074 | } | ||
1075 | |||
1076 | /* Then try to steal a frame (like a VIDIOC_DQBUF would do) */ | ||
1077 | if (list_empty(&(usbvision->outqueue))) { | ||
1078 | if(noblock) | ||
1079 | return -EAGAIN; | ||
1080 | |||
1081 | ret = wait_event_interruptible | ||
1082 | (usbvision->wait_frame, | ||
1083 | !list_empty(&(usbvision->outqueue))); | ||
1084 | if (ret) | ||
1085 | return ret; | ||
1086 | } | ||
1087 | |||
1088 | spin_lock_irqsave(&usbvision->queue_lock, lock_flags); | ||
1089 | frame = list_entry(usbvision->outqueue.next, | ||
1090 | struct usbvision_frame, frame); | ||
1091 | list_del(usbvision->outqueue.next); | ||
1092 | spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); | ||
1093 | |||
1094 | /* An error returns an empty frame */ | ||
1095 | if (frame->grabstate == FrameState_Error) { | ||
1096 | frame->bytes_read = 0; | ||
1097 | return 0; | ||
1098 | } | ||
1099 | |||
1100 | PDEBUG(DBG_IO, "%s: frmx=%d, bytes_read=%ld, scanlength=%ld", __FUNCTION__, | ||
1101 | frame->index, frame->bytes_read, frame->scanlength); | ||
1102 | |||
1103 | /* copy bytes to user space; we allow for partials reads */ | ||
1104 | if ((count + frame->bytes_read) > (unsigned long)frame->scanlength) | ||
1105 | count = frame->scanlength - frame->bytes_read; | ||
1106 | |||
1107 | if (copy_to_user(buf, frame->data + frame->bytes_read, count)) { | ||
1108 | return -EFAULT; | ||
1109 | } | ||
1110 | |||
1111 | frame->bytes_read += count; | ||
1112 | PDEBUG(DBG_IO, "%s: {copy} count used=%ld, new bytes_read=%ld", __FUNCTION__, | ||
1113 | (unsigned long)count, frame->bytes_read); | ||
1114 | |||
1115 | // For now, forget the frame if it has not been read in one shot. | ||
1116 | /* if (frame->bytes_read >= frame->scanlength) {// All data has been read */ | ||
1117 | frame->bytes_read = 0; | ||
1118 | |||
1119 | /* Mark it as available to be used again. */ | ||
1120 | usbvision->frame[frmx].grabstate = FrameState_Unused; | ||
1121 | /* } */ | ||
1122 | |||
1123 | return count; | ||
1124 | } | ||
1125 | |||
1126 | static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) | ||
1127 | { | ||
1128 | unsigned long size = vma->vm_end - vma->vm_start, | ||
1129 | start = vma->vm_start; | ||
1130 | void *pos; | ||
1131 | u32 i; | ||
1132 | |||
1133 | struct video_device *dev = video_devdata(file); | ||
1134 | struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); | ||
1135 | |||
1136 | down(&usbvision->lock); | ||
1137 | |||
1138 | if (!USBVISION_IS_OPERATIONAL(usbvision)) { | ||
1139 | up(&usbvision->lock); | ||
1140 | return -EFAULT; | ||
1141 | } | ||
1142 | |||
1143 | if (!(vma->vm_flags & VM_WRITE) || | ||
1144 | size != PAGE_ALIGN(usbvision->curwidth*usbvision->curheight*usbvision->palette.bytes_per_pixel)) { | ||
1145 | up(&usbvision->lock); | ||
1146 | return -EINVAL; | ||
1147 | } | ||
1148 | |||
1149 | for (i = 0; i < USBVISION_NUMFRAMES; i++) { | ||
1150 | if (((usbvision->max_frame_size*i) >> PAGE_SHIFT) == vma->vm_pgoff) | ||
1151 | break; | ||
1152 | } | ||
1153 | if (i == USBVISION_NUMFRAMES) { | ||
1154 | PDEBUG(DBG_MMAP, "mmap: user supplied mapping address is out of range"); | ||
1155 | up(&usbvision->lock); | ||
1156 | return -EINVAL; | ||
1157 | } | ||
1158 | |||
1159 | /* VM_IO is eventually going to replace PageReserved altogether */ | ||
1160 | vma->vm_flags |= VM_IO; | ||
1161 | vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */ | ||
1162 | |||
1163 | pos = usbvision->frame[i].data; | ||
1164 | while (size > 0) { | ||
1165 | |||
1166 | if (vm_insert_page(vma, start, vmalloc_to_page(pos))) { | ||
1167 | PDEBUG(DBG_MMAP, "mmap: vm_insert_page failed"); | ||
1168 | up(&usbvision->lock); | ||
1169 | return -EAGAIN; | ||
1170 | } | ||
1171 | start += PAGE_SIZE; | ||
1172 | pos += PAGE_SIZE; | ||
1173 | size -= PAGE_SIZE; | ||
1174 | } | ||
1175 | |||
1176 | up(&usbvision->lock); | ||
1177 | return 0; | ||
1178 | } | ||
1179 | |||
1180 | |||
1181 | /* | ||
1182 | * Here comes the stuff for radio on usbvision based devices | ||
1183 | * | ||
1184 | */ | ||
1185 | static int usbvision_radio_open(struct inode *inode, struct file *file) | ||
1186 | { | ||
1187 | struct video_device *dev = video_devdata(file); | ||
1188 | struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); | ||
1189 | struct v4l2_frequency freq; | ||
1190 | int errCode = 0; | ||
1191 | |||
1192 | PDEBUG(DBG_IO, "%s:", __FUNCTION__); | ||
1193 | |||
1194 | down(&usbvision->lock); | ||
1195 | |||
1196 | if (usbvision->user) { | ||
1197 | err("%s: Someone tried to open an already opened USBVision Radio!", __FUNCTION__); | ||
1198 | errCode = -EBUSY; | ||
1199 | } | ||
1200 | else { | ||
1201 | if(PowerOnAtOpen) { | ||
1202 | usbvision_reset_powerOffTimer(usbvision); | ||
1203 | if (usbvision->power == 0) { | ||
1204 | usbvision_power_on(usbvision); | ||
1205 | usbvision_init_i2c(usbvision); | ||
1206 | } | ||
1207 | } | ||
1208 | |||
1209 | // If so far no errors then we shall start the radio | ||
1210 | usbvision->radio = 1; | ||
1211 | call_i2c_clients(usbvision,AUDC_SET_RADIO,&usbvision->tuner_type); | ||
1212 | freq.frequency = 1517; //SWR3 @ 94.8MHz | ||
1213 | call_i2c_clients(usbvision, VIDIOC_S_FREQUENCY, &freq); | ||
1214 | usbvision_set_audio(usbvision, USBVISION_AUDIO_RADIO); | ||
1215 | usbvision->user++; | ||
1216 | } | ||
1217 | |||
1218 | if (errCode) { | ||
1219 | if (PowerOnAtOpen) { | ||
1220 | usbvision_i2c_usb_del_bus(&usbvision->i2c_adap); | ||
1221 | usbvision_power_off(usbvision); | ||
1222 | usbvision->initialized = 0; | ||
1223 | } | ||
1224 | } | ||
1225 | up(&usbvision->lock); | ||
1226 | return errCode; | ||
1227 | } | ||
1228 | |||
1229 | |||
1230 | static int usbvision_radio_close(struct inode *inode, struct file *file) | ||
1231 | { | ||
1232 | struct video_device *dev = video_devdata(file); | ||
1233 | struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); | ||
1234 | int errCode = 0; | ||
1235 | |||
1236 | PDEBUG(DBG_IO, ""); | ||
1237 | |||
1238 | down(&usbvision->lock); | ||
1239 | |||
1240 | usbvision_audio_off(usbvision); | ||
1241 | usbvision->radio=0; | ||
1242 | usbvision->user--; | ||
1243 | |||
1244 | if (PowerOnAtOpen) { | ||
1245 | usbvision_set_powerOffTimer(usbvision); | ||
1246 | usbvision->initialized = 0; | ||
1247 | } | ||
1248 | |||
1249 | up(&usbvision->lock); | ||
1250 | |||
1251 | if (usbvision->remove_pending) { | ||
1252 | info("%s: Final disconnect", __FUNCTION__); | ||
1253 | usbvision_release(usbvision); | ||
1254 | } | ||
1255 | |||
1256 | |||
1257 | PDEBUG(DBG_IO, "success"); | ||
1258 | |||
1259 | return errCode; | ||
1260 | } | ||
1261 | |||
1262 | static int usbvision_do_radio_ioctl(struct inode *inode, struct file *file, | ||
1263 | unsigned int cmd, void *arg) | ||
1264 | { | ||
1265 | struct video_device *dev = video_devdata(file); | ||
1266 | struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); | ||
1267 | |||
1268 | if (!USBVISION_IS_OPERATIONAL(usbvision)) | ||
1269 | return -EIO; | ||
1270 | |||
1271 | switch (cmd) { | ||
1272 | case VIDIOC_QUERYCAP: | ||
1273 | { | ||
1274 | struct v4l2_capability *vc=arg; | ||
1275 | |||
1276 | memset(vc, 0, sizeof(*vc)); | ||
1277 | strlcpy(vc->driver, "USBVision", sizeof(vc->driver)); | ||
1278 | strlcpy(vc->card, usbvision_device_data[usbvision->DevModel].ModelString, | ||
1279 | sizeof(vc->card)); | ||
1280 | strlcpy(vc->bus_info, usbvision->dev->dev.bus_id, | ||
1281 | sizeof(vc->bus_info)); | ||
1282 | vc->version = USBVISION_DRIVER_VERSION; | ||
1283 | vc->capabilities = (usbvision->have_tuner ? V4L2_CAP_TUNER : 0); | ||
1284 | PDEBUG(DBG_IO, "VIDIOC_QUERYCAP"); | ||
1285 | return 0; | ||
1286 | } | ||
1287 | case VIDIOC_QUERYCTRL: | ||
1288 | { | ||
1289 | struct v4l2_queryctrl *ctrl = arg; | ||
1290 | int id=ctrl->id; | ||
1291 | |||
1292 | memset(ctrl,0,sizeof(*ctrl)); | ||
1293 | ctrl->id=id; | ||
1294 | |||
1295 | call_i2c_clients(usbvision, cmd, arg); | ||
1296 | PDEBUG(DBG_IO,"VIDIOC_QUERYCTRL id=%x value=%x",ctrl->id,ctrl->type); | ||
1297 | |||
1298 | if (ctrl->type) | ||
1299 | return 0; | ||
1300 | else | ||
1301 | return -EINVAL; | ||
1302 | |||
1303 | } | ||
1304 | case VIDIOC_G_CTRL: | ||
1305 | { | ||
1306 | struct v4l2_control *ctrl = arg; | ||
1307 | |||
1308 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl); | ||
1309 | PDEBUG(DBG_IO,"VIDIOC_G_CTRL id=%x value=%x",ctrl->id,ctrl->value); | ||
1310 | return 0; | ||
1311 | } | ||
1312 | case VIDIOC_S_CTRL: | ||
1313 | { | ||
1314 | struct v4l2_control *ctrl = arg; | ||
1315 | |||
1316 | call_i2c_clients(usbvision, VIDIOC_S_CTRL, ctrl); | ||
1317 | PDEBUG(DBG_IO, "VIDIOC_S_CTRL id=%x value=%x",ctrl->id,ctrl->value); | ||
1318 | return 0; | ||
1319 | } | ||
1320 | case VIDIOC_G_TUNER: | ||
1321 | { | ||
1322 | struct v4l2_tuner *t = arg; | ||
1323 | |||
1324 | if (t->index > 0) | ||
1325 | return -EINVAL; | ||
1326 | |||
1327 | memset(t,0,sizeof(*t)); | ||
1328 | strcpy(t->name, "Radio"); | ||
1329 | t->type = V4L2_TUNER_RADIO; | ||
1330 | |||
1331 | /* Let clients fill in the remainder of this struct */ | ||
1332 | call_i2c_clients(usbvision,VIDIOC_G_TUNER,t); | ||
1333 | PDEBUG(DBG_IO, "VIDIOC_G_TUNER signal=%x, afc=%x",t->signal,t->afc); | ||
1334 | return 0; | ||
1335 | } | ||
1336 | case VIDIOC_S_TUNER: | ||
1337 | { | ||
1338 | struct v4l2_tuner *vt = arg; | ||
1339 | |||
1340 | // Only no or one tuner for now | ||
1341 | if (!usbvision->have_tuner || vt->index) | ||
1342 | return -EINVAL; | ||
1343 | /* let clients handle this */ | ||
1344 | call_i2c_clients(usbvision,VIDIOC_S_TUNER,vt); | ||
1345 | |||
1346 | PDEBUG(DBG_IO, "VIDIOC_S_TUNER"); | ||
1347 | return 0; | ||
1348 | } | ||
1349 | case VIDIOC_G_AUDIO: | ||
1350 | { | ||
1351 | struct v4l2_audio *a = arg; | ||
1352 | |||
1353 | memset(a,0,sizeof(*a)); | ||
1354 | strcpy(a->name,"Radio"); | ||
1355 | PDEBUG(DBG_IO, "VIDIOC_G_AUDIO"); | ||
1356 | return 0; | ||
1357 | } | ||
1358 | case VIDIOC_S_AUDIO: | ||
1359 | case VIDIOC_S_INPUT: | ||
1360 | case VIDIOC_S_STD: | ||
1361 | return 0; | ||
1362 | |||
1363 | case VIDIOC_G_FREQUENCY: | ||
1364 | { | ||
1365 | struct v4l2_frequency *f = arg; | ||
1366 | |||
1367 | memset(f,0,sizeof(*f)); | ||
1368 | |||
1369 | f->type = V4L2_TUNER_RADIO; | ||
1370 | f->frequency = usbvision->freq; | ||
1371 | call_i2c_clients(usbvision, cmd, f); | ||
1372 | PDEBUG(DBG_IO, "VIDIOC_G_FREQUENCY freq=0x%X", (unsigned)f->frequency); | ||
1373 | |||
1374 | return 0; | ||
1375 | } | ||
1376 | case VIDIOC_S_FREQUENCY: | ||
1377 | { | ||
1378 | struct v4l2_frequency *f = arg; | ||
1379 | |||
1380 | if (f->tuner != 0) | ||
1381 | return -EINVAL; | ||
1382 | usbvision->freq = f->frequency; | ||
1383 | call_i2c_clients(usbvision, cmd, f); | ||
1384 | PDEBUG(DBG_IO, "VIDIOC_S_FREQUENCY freq=0x%X", (unsigned)f->frequency); | ||
1385 | |||
1386 | return 0; | ||
1387 | } | ||
1388 | default: | ||
1389 | { | ||
1390 | PDEBUG(DBG_IO, "%s: Unknown command %x", __FUNCTION__, cmd); | ||
1391 | return -ENOIOCTLCMD; | ||
1392 | } | ||
1393 | } | ||
1394 | return 0; | ||
1395 | } | ||
1396 | |||
1397 | |||
1398 | static int usbvision_radio_ioctl(struct inode *inode, struct file *file, | ||
1399 | unsigned int cmd, unsigned long arg) | ||
1400 | { | ||
1401 | return video_usercopy(inode, file, cmd, arg, usbvision_do_radio_ioctl); | ||
1402 | } | ||
1403 | |||
1404 | |||
1405 | /* | ||
1406 | * Here comes the stuff for vbi on usbvision based devices | ||
1407 | * | ||
1408 | */ | ||
1409 | static int usbvision_vbi_open(struct inode *inode, struct file *file) | ||
1410 | { | ||
1411 | /* TODO */ | ||
1412 | return -EINVAL; | ||
1413 | |||
1414 | } | ||
1415 | |||
1416 | static int usbvision_vbi_close(struct inode *inode, struct file *file) | ||
1417 | { | ||
1418 | /* TODO */ | ||
1419 | return -EINVAL; | ||
1420 | } | ||
1421 | |||
1422 | static int usbvision_do_vbi_ioctl(struct inode *inode, struct file *file, | ||
1423 | unsigned int cmd, void *arg) | ||
1424 | { | ||
1425 | /* TODO */ | ||
1426 | return -EINVAL; | ||
1427 | } | ||
1428 | |||
1429 | static int usbvision_vbi_ioctl(struct inode *inode, struct file *file, | ||
1430 | unsigned int cmd, unsigned long arg) | ||
1431 | { | ||
1432 | return video_usercopy(inode, file, cmd, arg, usbvision_do_vbi_ioctl); | ||
1433 | } | ||
1434 | |||
1435 | |||
1436 | // | ||
1437 | // Video registration stuff | ||
1438 | // | ||
1439 | |||
1440 | // Video template | ||
1441 | static struct file_operations usbvision_fops = { | ||
1442 | .owner = THIS_MODULE, | ||
1443 | .open = usbvision_v4l2_open, | ||
1444 | .release = usbvision_v4l2_close, | ||
1445 | .read = usbvision_v4l2_read, | ||
1446 | .mmap = usbvision_v4l2_mmap, | ||
1447 | .ioctl = usbvision_v4l2_ioctl, | ||
1448 | .llseek = no_llseek, | ||
1449 | }; | ||
1450 | static struct video_device usbvision_video_template = { | ||
1451 | .owner = THIS_MODULE, | ||
1452 | .type = VID_TYPE_TUNER | VID_TYPE_CAPTURE, | ||
1453 | .hardware = VID_HARDWARE_USBVISION, | ||
1454 | .fops = &usbvision_fops, | ||
1455 | .name = "usbvision-video", | ||
1456 | .release = video_device_release, | ||
1457 | .minor = -1, | ||
1458 | }; | ||
1459 | |||
1460 | |||
1461 | // Radio template | ||
1462 | static struct file_operations usbvision_radio_fops = { | ||
1463 | .owner = THIS_MODULE, | ||
1464 | .open = usbvision_radio_open, | ||
1465 | .release = usbvision_radio_close, | ||
1466 | .ioctl = usbvision_radio_ioctl, | ||
1467 | .llseek = no_llseek, | ||
1468 | }; | ||
1469 | |||
1470 | static struct video_device usbvision_radio_template= | ||
1471 | { | ||
1472 | .owner = THIS_MODULE, | ||
1473 | .type = VID_TYPE_TUNER, | ||
1474 | .hardware = VID_HARDWARE_USBVISION, | ||
1475 | .fops = &usbvision_radio_fops, | ||
1476 | .release = video_device_release, | ||
1477 | .name = "usbvision-radio", | ||
1478 | .minor = -1, | ||
1479 | }; | ||
1480 | |||
1481 | |||
1482 | // vbi template | ||
1483 | static struct file_operations usbvision_vbi_fops = { | ||
1484 | .owner = THIS_MODULE, | ||
1485 | .open = usbvision_vbi_open, | ||
1486 | .release = usbvision_vbi_close, | ||
1487 | .ioctl = usbvision_vbi_ioctl, | ||
1488 | .llseek = no_llseek, | ||
1489 | }; | ||
1490 | |||
1491 | static struct video_device usbvision_vbi_template= | ||
1492 | { | ||
1493 | .owner = THIS_MODULE, | ||
1494 | .type = VID_TYPE_TUNER, | ||
1495 | .hardware = VID_HARDWARE_USBVISION, | ||
1496 | .fops = &usbvision_vbi_fops, | ||
1497 | .release = video_device_release, | ||
1498 | .name = "usbvision-vbi", | ||
1499 | .minor = -1, | ||
1500 | }; | ||
1501 | |||
1502 | |||
1503 | static struct video_device *usbvision_vdev_init(struct usb_usbvision *usbvision, | ||
1504 | struct video_device *vdev_template, | ||
1505 | char *name) | ||
1506 | { | ||
1507 | struct usb_device *usb_dev = usbvision->dev; | ||
1508 | struct video_device *vdev; | ||
1509 | |||
1510 | if (usb_dev == NULL) { | ||
1511 | err("%s: usbvision->dev is not set", __FUNCTION__); | ||
1512 | return NULL; | ||
1513 | } | ||
1514 | |||
1515 | vdev = video_device_alloc(); | ||
1516 | if (NULL == vdev) { | ||
1517 | return NULL; | ||
1518 | } | ||
1519 | *vdev = *vdev_template; | ||
1520 | // vdev->minor = -1; | ||
1521 | vdev->dev = &usb_dev->dev; | ||
1522 | snprintf(vdev->name, sizeof(vdev->name), "%s", name); | ||
1523 | video_set_drvdata(vdev, usbvision); | ||
1524 | return vdev; | ||
1525 | } | ||
1526 | |||
1527 | // unregister video4linux devices | ||
1528 | static void usbvision_unregister_video(struct usb_usbvision *usbvision) | ||
1529 | { | ||
1530 | // vbi Device: | ||
1531 | if (usbvision->vbi) { | ||
1532 | PDEBUG(DBG_PROBE, "unregister /dev/vbi%d [v4l2]", usbvision->vbi->minor & 0x1f); | ||
1533 | if (usbvision->vbi->minor != -1) { | ||
1534 | video_unregister_device(usbvision->vbi); | ||
1535 | } | ||
1536 | else { | ||
1537 | video_device_release(usbvision->vbi); | ||
1538 | } | ||
1539 | usbvision->vbi = NULL; | ||
1540 | } | ||
1541 | |||
1542 | // Radio Device: | ||
1543 | if (usbvision->rdev) { | ||
1544 | PDEBUG(DBG_PROBE, "unregister /dev/radio%d [v4l2]", usbvision->rdev->minor & 0x1f); | ||
1545 | if (usbvision->rdev->minor != -1) { | ||
1546 | video_unregister_device(usbvision->rdev); | ||
1547 | } | ||
1548 | else { | ||
1549 | video_device_release(usbvision->rdev); | ||
1550 | } | ||
1551 | usbvision->rdev = NULL; | ||
1552 | } | ||
1553 | |||
1554 | // Video Device: | ||
1555 | if (usbvision->vdev) { | ||
1556 | PDEBUG(DBG_PROBE, "unregister /dev/video%d [v4l2]", usbvision->vdev->minor & 0x1f); | ||
1557 | if (usbvision->vdev->minor != -1) { | ||
1558 | video_unregister_device(usbvision->vdev); | ||
1559 | } | ||
1560 | else { | ||
1561 | video_device_release(usbvision->vdev); | ||
1562 | } | ||
1563 | usbvision->vdev = NULL; | ||
1564 | } | ||
1565 | } | ||
1566 | |||
1567 | // register video4linux devices | ||
1568 | static int __devinit usbvision_register_video(struct usb_usbvision *usbvision) | ||
1569 | { | ||
1570 | // Video Device: | ||
1571 | usbvision->vdev = usbvision_vdev_init(usbvision, &usbvision_video_template, "USBVision Video"); | ||
1572 | if (usbvision->vdev == NULL) { | ||
1573 | goto err_exit; | ||
1574 | } | ||
1575 | if (video_register_device(usbvision->vdev, VFL_TYPE_GRABBER, video_nr)<0) { | ||
1576 | goto err_exit; | ||
1577 | } | ||
1578 | info("USBVision[%d]: registered USBVision Video device /dev/video%d [v4l2]", usbvision->nr,usbvision->vdev->minor & 0x1f); | ||
1579 | |||
1580 | // Radio Device: | ||
1581 | if (usbvision_device_data[usbvision->DevModel].Radio) { | ||
1582 | // usbvision has radio | ||
1583 | usbvision->rdev = usbvision_vdev_init(usbvision, &usbvision_radio_template, "USBVision Radio"); | ||
1584 | if (usbvision->rdev == NULL) { | ||
1585 | goto err_exit; | ||
1586 | } | ||
1587 | if (video_register_device(usbvision->rdev, VFL_TYPE_RADIO, radio_nr)<0) { | ||
1588 | goto err_exit; | ||
1589 | } | ||
1590 | info("USBVision[%d]: registered USBVision Radio device /dev/radio%d [v4l2]", usbvision->nr, usbvision->rdev->minor & 0x1f); | ||
1591 | } | ||
1592 | // vbi Device: | ||
1593 | if (usbvision_device_data[usbvision->DevModel].vbi) { | ||
1594 | usbvision->vbi = usbvision_vdev_init(usbvision, &usbvision_vbi_template, "USBVision VBI"); | ||
1595 | if (usbvision->vdev == NULL) { | ||
1596 | goto err_exit; | ||
1597 | } | ||
1598 | if (video_register_device(usbvision->vbi, VFL_TYPE_VBI, vbi_nr)<0) { | ||
1599 | goto err_exit; | ||
1600 | } | ||
1601 | info("USBVision[%d]: registered USBVision VBI device /dev/vbi%d [v4l2] (Not Working Yet!)", usbvision->nr,usbvision->vbi->minor & 0x1f); | ||
1602 | } | ||
1603 | // all done | ||
1604 | return 0; | ||
1605 | |||
1606 | err_exit: | ||
1607 | err("USBVision[%d]: video_register_device() failed", usbvision->nr); | ||
1608 | usbvision_unregister_video(usbvision); | ||
1609 | return -1; | ||
1610 | } | ||
1611 | |||
1612 | /* | ||
1613 | * usbvision_alloc() | ||
1614 | * | ||
1615 | * This code allocates the struct usb_usbvision. It is filled with default values. | ||
1616 | * | ||
1617 | * Returns NULL on error, a pointer to usb_usbvision else. | ||
1618 | * | ||
1619 | */ | ||
1620 | static struct usb_usbvision *usbvision_alloc(struct usb_device *dev) | ||
1621 | { | ||
1622 | struct usb_usbvision *usbvision; | ||
1623 | |||
1624 | if ((usbvision = kzalloc(sizeof(struct usb_usbvision), GFP_KERNEL)) == NULL) { | ||
1625 | goto err_exit; | ||
1626 | } | ||
1627 | |||
1628 | usbvision->dev = dev; | ||
1629 | |||
1630 | init_MUTEX(&usbvision->lock); /* to 1 == available */ | ||
1631 | |||
1632 | // prepare control urb for control messages during interrupts | ||
1633 | usbvision->ctrlUrb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL); | ||
1634 | if (usbvision->ctrlUrb == NULL) { | ||
1635 | goto err_exit; | ||
1636 | } | ||
1637 | init_waitqueue_head(&usbvision->ctrlUrb_wq); | ||
1638 | init_MUTEX(&usbvision->ctrlUrbLock); /* to 1 == available */ | ||
1639 | |||
1640 | usbvision_init_powerOffTimer(usbvision); | ||
1641 | |||
1642 | return usbvision; | ||
1643 | |||
1644 | err_exit: | ||
1645 | if (usbvision && usbvision->ctrlUrb) { | ||
1646 | usb_free_urb(usbvision->ctrlUrb); | ||
1647 | } | ||
1648 | if (usbvision) { | ||
1649 | kfree(usbvision); | ||
1650 | } | ||
1651 | return NULL; | ||
1652 | } | ||
1653 | |||
1654 | /* | ||
1655 | * usbvision_release() | ||
1656 | * | ||
1657 | * This code does final release of struct usb_usbvision. This happens | ||
1658 | * after the device is disconnected -and- all clients closed their files. | ||
1659 | * | ||
1660 | */ | ||
1661 | static void usbvision_release(struct usb_usbvision *usbvision) | ||
1662 | { | ||
1663 | PDEBUG(DBG_PROBE, ""); | ||
1664 | |||
1665 | down(&usbvision->lock); | ||
1666 | |||
1667 | usbvision_reset_powerOffTimer(usbvision); | ||
1668 | |||
1669 | usbvision->initialized = 0; | ||
1670 | |||
1671 | up(&usbvision->lock); | ||
1672 | |||
1673 | usbvision_remove_sysfs(usbvision->vdev); | ||
1674 | usbvision_unregister_video(usbvision); | ||
1675 | |||
1676 | if (usbvision->ctrlUrb) { | ||
1677 | usb_free_urb(usbvision->ctrlUrb); | ||
1678 | } | ||
1679 | |||
1680 | kfree(usbvision); | ||
1681 | |||
1682 | PDEBUG(DBG_PROBE, "success"); | ||
1683 | } | ||
1684 | |||
1685 | |||
1686 | /******************************** usb interface *****************************************/ | ||
1687 | |||
1688 | static void usbvision_configure_video(struct usb_usbvision *usbvision) | ||
1689 | { | ||
1690 | int model,i; | ||
1691 | |||
1692 | if (usbvision == NULL) | ||
1693 | return; | ||
1694 | |||
1695 | model = usbvision->DevModel; | ||
1696 | usbvision->palette = usbvision_v4l2_format[2]; // V4L2_PIX_FMT_RGB24; | ||
1697 | |||
1698 | if (usbvision_device_data[usbvision->DevModel].Vin_Reg2 >= 0) { | ||
1699 | usbvision->Vin_Reg2_Preset = usbvision_device_data[usbvision->DevModel].Vin_Reg2 & 0xff; | ||
1700 | } else { | ||
1701 | usbvision->Vin_Reg2_Preset = 0; | ||
1702 | } | ||
1703 | |||
1704 | for (i = 0; i < TVNORMS; i++) | ||
1705 | if (usbvision_device_data[model].VideoNorm == tvnorms[i].mode) | ||
1706 | break; | ||
1707 | if (i == TVNORMS) | ||
1708 | i = 0; | ||
1709 | usbvision->tvnorm = &tvnorms[i]; /* set default norm */ | ||
1710 | |||
1711 | usbvision->video_inputs = usbvision_device_data[model].VideoChannels; | ||
1712 | usbvision->ctl_input = 0; | ||
1713 | |||
1714 | /* This should be here to make i2c clients to be able to register */ | ||
1715 | usbvision_audio_off(usbvision); //first switch off audio | ||
1716 | if (!PowerOnAtOpen) { | ||
1717 | usbvision_power_on(usbvision); //and then power up the noisy tuner | ||
1718 | usbvision_init_i2c(usbvision); | ||
1719 | } | ||
1720 | } | ||
1721 | |||
1722 | /* | ||
1723 | * usbvision_probe() | ||
1724 | * | ||
1725 | * This procedure queries device descriptor and accepts the interface | ||
1726 | * if it looks like USBVISION video device | ||
1727 | * | ||
1728 | */ | ||
1729 | static int __devinit usbvision_probe(struct usb_interface *intf, const struct usb_device_id *devid) | ||
1730 | { | ||
1731 | struct usb_device *dev = interface_to_usbdev(intf); | ||
1732 | __u8 ifnum = intf->altsetting->desc.bInterfaceNumber; | ||
1733 | const struct usb_host_interface *interface; | ||
1734 | struct usb_usbvision *usbvision = NULL; | ||
1735 | const struct usb_endpoint_descriptor *endpoint; | ||
1736 | int model; | ||
1737 | |||
1738 | PDEBUG(DBG_PROBE, "VID=%#04x, PID=%#04x, ifnum=%u", | ||
1739 | dev->descriptor.idVendor, dev->descriptor.idProduct, ifnum); | ||
1740 | /* Is it an USBVISION video dev? */ | ||
1741 | model = 0; | ||
1742 | for(model = 0; usbvision_device_data[model].idVendor; model++) { | ||
1743 | if (le16_to_cpu(dev->descriptor.idVendor) != usbvision_device_data[model].idVendor) { | ||
1744 | continue; | ||
1745 | } | ||
1746 | if (le16_to_cpu(dev->descriptor.idProduct) != usbvision_device_data[model].idProduct) { | ||
1747 | continue; | ||
1748 | } | ||
1749 | |||
1750 | info("%s: %s found", __FUNCTION__, usbvision_device_data[model].ModelString); | ||
1751 | break; | ||
1752 | } | ||
1753 | |||
1754 | if (usbvision_device_data[model].idVendor == 0) { | ||
1755 | return -ENODEV; //no matching device | ||
1756 | } | ||
1757 | if (usbvision_device_data[model].Interface >= 0) { | ||
1758 | interface = &dev->actconfig->interface[usbvision_device_data[model].Interface]->altsetting[0]; | ||
1759 | } | ||
1760 | else { | ||
1761 | interface = &dev->actconfig->interface[ifnum]->altsetting[0]; | ||
1762 | } | ||
1763 | endpoint = &interface->endpoint[1].desc; | ||
1764 | if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC) { | ||
1765 | err("%s: interface %d. has non-ISO endpoint!", __FUNCTION__, ifnum); | ||
1766 | err("%s: Endpoint attribures %d", __FUNCTION__, endpoint->bmAttributes); | ||
1767 | return -ENODEV; | ||
1768 | } | ||
1769 | if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) { | ||
1770 | err("%s: interface %d. has ISO OUT endpoint!", __FUNCTION__, ifnum); | ||
1771 | return -ENODEV; | ||
1772 | } | ||
1773 | |||
1774 | usb_get_dev(dev); | ||
1775 | |||
1776 | if ((usbvision = usbvision_alloc(dev)) == NULL) { | ||
1777 | err("%s: couldn't allocate USBVision struct", __FUNCTION__); | ||
1778 | return -ENOMEM; | ||
1779 | } | ||
1780 | if (dev->descriptor.bNumConfigurations > 1) { | ||
1781 | usbvision->bridgeType = BRIDGE_NT1004; | ||
1782 | } | ||
1783 | else if (usbvision_device_data[model].ModelString == "Dazzle Fusion Model DVC-90 Rev 1 (SECAM)") { | ||
1784 | usbvision->bridgeType = BRIDGE_NT1005; | ||
1785 | } | ||
1786 | else { | ||
1787 | usbvision->bridgeType = BRIDGE_NT1003; | ||
1788 | } | ||
1789 | PDEBUG(DBG_PROBE, "bridgeType %d", usbvision->bridgeType); | ||
1790 | |||
1791 | down(&usbvision->lock); | ||
1792 | |||
1793 | usbvision->nr = usbvision_nr++; | ||
1794 | |||
1795 | usbvision->have_tuner = usbvision_device_data[model].Tuner; | ||
1796 | if (usbvision->have_tuner) { | ||
1797 | usbvision->tuner_type = usbvision_device_data[model].TunerType; | ||
1798 | } | ||
1799 | |||
1800 | usbvision->tuner_addr = ADDR_UNSET; | ||
1801 | |||
1802 | usbvision->DevModel = model; | ||
1803 | usbvision->remove_pending = 0; | ||
1804 | usbvision->iface = ifnum; | ||
1805 | usbvision->ifaceAltInactive = 0; | ||
1806 | usbvision->ifaceAltActive = 1; | ||
1807 | usbvision->video_endp = endpoint->bEndpointAddress; | ||
1808 | usbvision->isocPacketSize = 0; | ||
1809 | usbvision->usb_bandwidth = 0; | ||
1810 | usbvision->user = 0; | ||
1811 | usbvision->streaming = Stream_Off; | ||
1812 | usbvision_register_video(usbvision); | ||
1813 | usbvision_configure_video(usbvision); | ||
1814 | up(&usbvision->lock); | ||
1815 | |||
1816 | |||
1817 | usb_set_intfdata (intf, usbvision); | ||
1818 | usbvision_create_sysfs(usbvision->vdev); | ||
1819 | |||
1820 | PDEBUG(DBG_PROBE, "success"); | ||
1821 | return 0; | ||
1822 | } | ||
1823 | |||
1824 | |||
1825 | /* | ||
1826 | * usbvision_disconnect() | ||
1827 | * | ||
1828 | * This procedure stops all driver activity, deallocates interface-private | ||
1829 | * structure (pointed by 'ptr') and after that driver should be removable | ||
1830 | * with no ill consequences. | ||
1831 | * | ||
1832 | */ | ||
1833 | static void __devexit usbvision_disconnect(struct usb_interface *intf) | ||
1834 | { | ||
1835 | struct usb_usbvision *usbvision = usb_get_intfdata(intf); | ||
1836 | |||
1837 | PDEBUG(DBG_PROBE, ""); | ||
1838 | |||
1839 | if (usbvision == NULL) { | ||
1840 | err("%s: usb_get_intfdata() failed", __FUNCTION__); | ||
1841 | return; | ||
1842 | } | ||
1843 | usb_set_intfdata (intf, NULL); | ||
1844 | |||
1845 | down(&usbvision->lock); | ||
1846 | |||
1847 | // At this time we ask to cancel outstanding URBs | ||
1848 | usbvision_stop_isoc(usbvision); | ||
1849 | |||
1850 | if (usbvision->power) { | ||
1851 | usbvision_i2c_usb_del_bus(&usbvision->i2c_adap); | ||
1852 | usbvision_power_off(usbvision); | ||
1853 | } | ||
1854 | usbvision->remove_pending = 1; // Now all ISO data will be ignored | ||
1855 | |||
1856 | usb_put_dev(usbvision->dev); | ||
1857 | usbvision->dev = NULL; // USB device is no more | ||
1858 | |||
1859 | up(&usbvision->lock); | ||
1860 | |||
1861 | if (usbvision->user) { | ||
1862 | info("%s: In use, disconnect pending", __FUNCTION__); | ||
1863 | wake_up_interruptible(&usbvision->wait_frame); | ||
1864 | wake_up_interruptible(&usbvision->wait_stream); | ||
1865 | } | ||
1866 | else { | ||
1867 | usbvision_release(usbvision); | ||
1868 | } | ||
1869 | |||
1870 | PDEBUG(DBG_PROBE, "success"); | ||
1871 | |||
1872 | } | ||
1873 | |||
1874 | static struct usb_driver usbvision_driver = { | ||
1875 | .name = "usbvision", | ||
1876 | .id_table = usbvision_table, | ||
1877 | .probe = usbvision_probe, | ||
1878 | .disconnect = usbvision_disconnect | ||
1879 | }; | ||
1880 | |||
1881 | /* | ||
1882 | * customdevice_process() | ||
1883 | * | ||
1884 | * This procedure preprocesses CustomDevice parameter if any | ||
1885 | * | ||
1886 | */ | ||
1887 | void customdevice_process(void) | ||
1888 | { | ||
1889 | usbvision_device_data[0]=usbvision_device_data[1]; | ||
1890 | usbvision_table[0]=usbvision_table[1]; | ||
1891 | |||
1892 | if(CustomDevice) | ||
1893 | { | ||
1894 | char *parse=CustomDevice; | ||
1895 | |||
1896 | PDEBUG(DBG_PROBE, "CustomDevide=%s", CustomDevice); | ||
1897 | |||
1898 | /*format is CustomDevice="0x0573 0x4D31 0 7113 3 PAL 1 1 1 5 -1 -1 -1 -1 -1" | ||
1899 | usbvision_device_data[0].idVendor; | ||
1900 | usbvision_device_data[0].idProduct; | ||
1901 | usbvision_device_data[0].Interface; | ||
1902 | usbvision_device_data[0].Codec; | ||
1903 | usbvision_device_data[0].VideoChannels; | ||
1904 | usbvision_device_data[0].VideoNorm; | ||
1905 | usbvision_device_data[0].AudioChannels; | ||
1906 | usbvision_device_data[0].Radio; | ||
1907 | usbvision_device_data[0].Tuner; | ||
1908 | usbvision_device_data[0].TunerType; | ||
1909 | usbvision_device_data[0].Vin_Reg1; | ||
1910 | usbvision_device_data[0].Vin_Reg2; | ||
1911 | usbvision_device_data[0].X_Offset; | ||
1912 | usbvision_device_data[0].Y_Offset; | ||
1913 | usbvision_device_data[0].Dvi_yuv; | ||
1914 | usbvision_device_data[0].ModelString; | ||
1915 | */ | ||
1916 | |||
1917 | rmspace(parse); | ||
1918 | usbvision_device_data[0].ModelString="USBVISION Custom Device"; | ||
1919 | |||
1920 | parse+=2; | ||
1921 | sscanf(parse,"%x",&usbvision_device_data[0].idVendor); | ||
1922 | goto2next(parse); | ||
1923 | PDEBUG(DBG_PROBE, "idVendor=0x%.4X", usbvision_device_data[0].idVendor); | ||
1924 | parse+=2; | ||
1925 | sscanf(parse,"%x",&usbvision_device_data[0].idProduct); | ||
1926 | goto2next(parse); | ||
1927 | PDEBUG(DBG_PROBE, "idProduct=0x%.4X", usbvision_device_data[0].idProduct); | ||
1928 | sscanf(parse,"%d",&usbvision_device_data[0].Interface); | ||
1929 | goto2next(parse); | ||
1930 | PDEBUG(DBG_PROBE, "Interface=%d", usbvision_device_data[0].Interface); | ||
1931 | sscanf(parse,"%d",&usbvision_device_data[0].Codec); | ||
1932 | goto2next(parse); | ||
1933 | PDEBUG(DBG_PROBE, "Codec=%d", usbvision_device_data[0].Codec); | ||
1934 | sscanf(parse,"%d",&usbvision_device_data[0].VideoChannels); | ||
1935 | goto2next(parse); | ||
1936 | PDEBUG(DBG_PROBE, "VideoChannels=%d", usbvision_device_data[0].VideoChannels); | ||
1937 | |||
1938 | switch(*parse) | ||
1939 | { | ||
1940 | case 'P': | ||
1941 | PDEBUG(DBG_PROBE, "VideoNorm=PAL"); | ||
1942 | usbvision_device_data[0].VideoNorm=VIDEO_MODE_PAL; | ||
1943 | break; | ||
1944 | |||
1945 | case 'S': | ||
1946 | PDEBUG(DBG_PROBE, "VideoNorm=SECAM"); | ||
1947 | usbvision_device_data[0].VideoNorm=VIDEO_MODE_SECAM; | ||
1948 | break; | ||
1949 | |||
1950 | case 'N': | ||
1951 | PDEBUG(DBG_PROBE, "VideoNorm=NTSC"); | ||
1952 | usbvision_device_data[0].VideoNorm=VIDEO_MODE_NTSC; | ||
1953 | break; | ||
1954 | |||
1955 | default: | ||
1956 | PDEBUG(DBG_PROBE, "VideoNorm=PAL (by default)"); | ||
1957 | usbvision_device_data[0].VideoNorm=VIDEO_MODE_PAL; | ||
1958 | break; | ||
1959 | } | ||
1960 | goto2next(parse); | ||
1961 | |||
1962 | sscanf(parse,"%d",&usbvision_device_data[0].AudioChannels); | ||
1963 | goto2next(parse); | ||
1964 | PDEBUG(DBG_PROBE, "AudioChannels=%d", usbvision_device_data[0].AudioChannels); | ||
1965 | sscanf(parse,"%d",&usbvision_device_data[0].Radio); | ||
1966 | goto2next(parse); | ||
1967 | PDEBUG(DBG_PROBE, "Radio=%d", usbvision_device_data[0].Radio); | ||
1968 | sscanf(parse,"%d",&usbvision_device_data[0].Tuner); | ||
1969 | goto2next(parse); | ||
1970 | PDEBUG(DBG_PROBE, "Tuner=%d", usbvision_device_data[0].Tuner); | ||
1971 | sscanf(parse,"%d",&usbvision_device_data[0].TunerType); | ||
1972 | goto2next(parse); | ||
1973 | PDEBUG(DBG_PROBE, "TunerType=%d", usbvision_device_data[0].TunerType); | ||
1974 | sscanf(parse,"%d",&usbvision_device_data[0].Vin_Reg1); | ||
1975 | goto2next(parse); | ||
1976 | PDEBUG(DBG_PROBE, "Vin_Reg1=%d", usbvision_device_data[0].Vin_Reg1); | ||
1977 | sscanf(parse,"%d",&usbvision_device_data[0].Vin_Reg2); | ||
1978 | goto2next(parse); | ||
1979 | PDEBUG(DBG_PROBE, "Vin_Reg2=%d", usbvision_device_data[0].Vin_Reg2); | ||
1980 | sscanf(parse,"%d",&usbvision_device_data[0].X_Offset); | ||
1981 | goto2next(parse); | ||
1982 | PDEBUG(DBG_PROBE, "X_Offset=%d", usbvision_device_data[0].X_Offset); | ||
1983 | sscanf(parse,"%d",&usbvision_device_data[0].Y_Offset); | ||
1984 | goto2next(parse); | ||
1985 | PDEBUG(DBG_PROBE, "Y_Offset=%d", usbvision_device_data[0].Y_Offset); | ||
1986 | sscanf(parse,"%d",&usbvision_device_data[0].Dvi_yuv); | ||
1987 | PDEBUG(DBG_PROBE, "Dvi_yuv=%d", usbvision_device_data[0].Dvi_yuv); | ||
1988 | |||
1989 | //add to usbvision_table also | ||
1990 | usbvision_table[0].match_flags=USB_DEVICE_ID_MATCH_DEVICE; | ||
1991 | usbvision_table[0].idVendor=usbvision_device_data[0].idVendor; | ||
1992 | usbvision_table[0].idProduct=usbvision_device_data[0].idProduct; | ||
1993 | |||
1994 | } | ||
1995 | } | ||
1996 | |||
1997 | |||
1998 | |||
1999 | /* | ||
2000 | * usbvision_init() | ||
2001 | * | ||
2002 | * This code is run to initialize the driver. | ||
2003 | * | ||
2004 | */ | ||
2005 | static int __init usbvision_init(void) | ||
2006 | { | ||
2007 | int errCode; | ||
2008 | |||
2009 | PDEBUG(DBG_PROBE, ""); | ||
2010 | |||
2011 | PDEBUG(DBG_IOCTL, "IOCTL debugging is enabled [video]"); | ||
2012 | PDEBUG(DBG_IO, "IO debugging is enabled [video]"); | ||
2013 | PDEBUG(DBG_PROBE, "PROBE debugging is enabled [video]"); | ||
2014 | PDEBUG(DBG_MMAP, "MMAP debugging is enabled [video]"); | ||
2015 | |||
2016 | /* disable planar mode support unless compression enabled */ | ||
2017 | if (isocMode != ISOC_MODE_COMPRESS ) { | ||
2018 | // FIXME : not the right way to set supported flag | ||
2019 | usbvision_v4l2_format[6].supported = 0; // V4L2_PIX_FMT_YVU420 | ||
2020 | usbvision_v4l2_format[7].supported = 0; // V4L2_PIX_FMT_YUV422P | ||
2021 | } | ||
2022 | |||
2023 | customdevice_process(); | ||
2024 | |||
2025 | errCode = usb_register(&usbvision_driver); | ||
2026 | |||
2027 | if (errCode == 0) { | ||
2028 | info(DRIVER_DESC " : " USBVISION_VERSION_STRING); | ||
2029 | PDEBUG(DBG_PROBE, "success"); | ||
2030 | } | ||
2031 | return errCode; | ||
2032 | } | ||
2033 | |||
2034 | static void __exit usbvision_exit(void) | ||
2035 | { | ||
2036 | PDEBUG(DBG_PROBE, ""); | ||
2037 | |||
2038 | usb_deregister(&usbvision_driver); | ||
2039 | PDEBUG(DBG_PROBE, "success"); | ||
2040 | } | ||
2041 | |||
2042 | module_init(usbvision_init); | ||
2043 | module_exit(usbvision_exit); | ||
2044 | |||
2045 | /* | ||
2046 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
2047 | * --------------------------------------------------------------------------- | ||
2048 | * Local variables: | ||
2049 | * c-basic-offset: 8 | ||
2050 | * End: | ||
2051 | */ | ||
diff --git a/drivers/media/video/usbvision/usbvision.h b/drivers/media/video/usbvision/usbvision.h new file mode 100644 index 000000000000..0e7e3d653cac --- /dev/null +++ b/drivers/media/video/usbvision/usbvision.h | |||
@@ -0,0 +1,558 @@ | |||
1 | /* | ||
2 | * USBVISION.H | ||
3 | * usbvision header file | ||
4 | * | ||
5 | * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de> | ||
6 | * Dwaine Garden <dwainegarden@rogers.com> | ||
7 | * | ||
8 | * | ||
9 | * Report problems to v4l MailingList : http://www.redhat.com/mailman/listinfo/video4linux-list | ||
10 | * | ||
11 | * This module is part of usbvision driver project. | ||
12 | * Updates to driver completed by Dwaine P. Garden | ||
13 | * v4l2 conversion by Thierry Merle <thierry.merle@free.fr> | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or modify | ||
16 | * it under the terms of the GNU General Public License as published by | ||
17 | * the Free Software Foundation; either version 2 of the License, or | ||
18 | * (at your option) any later version. | ||
19 | * | ||
20 | * This program is distributed in the hope that it will be useful, | ||
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
23 | * GNU General Public License for more details. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License | ||
26 | * along with this program; if not, write to the Free Software | ||
27 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
28 | */ | ||
29 | |||
30 | |||
31 | #ifndef __LINUX_USBVISION_H | ||
32 | #define __LINUX_USBVISION_H | ||
33 | |||
34 | #include <linux/list.h> | ||
35 | #include <linux/usb.h> | ||
36 | #include <media/v4l2-common.h> | ||
37 | #include <media/tuner.h> | ||
38 | #include <linux/videodev2.h> | ||
39 | |||
40 | #define USBVISION_DEBUG /* Turn on debug messages */ | ||
41 | |||
42 | #ifndef VID_HARDWARE_USBVISION | ||
43 | #define VID_HARDWARE_USBVISION 34 /* USBVision Video Grabber */ | ||
44 | #endif | ||
45 | |||
46 | #define USBVISION_PWR_REG 0x00 | ||
47 | #define USBVISION_SSPND_EN (1 << 1) | ||
48 | #define USBVISION_RES2 (1 << 2) | ||
49 | #define USBVISION_PWR_VID (1 << 5) | ||
50 | #define USBVISION_E2_EN (1 << 7) | ||
51 | #define USBVISION_CONFIG_REG 0x01 | ||
52 | #define USBVISION_ADRS_REG 0x02 | ||
53 | #define USBVISION_ALTER_REG 0x03 | ||
54 | #define USBVISION_FORCE_ALTER_REG 0x04 | ||
55 | #define USBVISION_STATUS_REG 0x05 | ||
56 | #define USBVISION_IOPIN_REG 0x06 | ||
57 | #define USBVISION_IO_1 (1 << 0) | ||
58 | #define USBVISION_IO_2 (1 << 1) | ||
59 | #define USBVISION_AUDIO_IN 0 | ||
60 | #define USBVISION_AUDIO_TV 1 | ||
61 | #define USBVISION_AUDIO_RADIO 2 | ||
62 | #define USBVISION_AUDIO_MUTE 3 | ||
63 | #define USBVISION_SER_MODE 0x07 | ||
64 | #define USBVISION_SER_ADRS 0x08 | ||
65 | #define USBVISION_SER_CONT 0x09 | ||
66 | #define USBVISION_SER_DAT1 0x0A | ||
67 | #define USBVISION_SER_DAT2 0x0B | ||
68 | #define USBVISION_SER_DAT3 0x0C | ||
69 | #define USBVISION_SER_DAT4 0x0D | ||
70 | #define USBVISION_EE_DATA 0x0E | ||
71 | #define USBVISION_EE_LSBAD 0x0F | ||
72 | #define USBVISION_EE_CONT 0x10 | ||
73 | #define USBVISION_DRM_CONT 0x12 | ||
74 | #define USBVISION_REF (1 << 0) | ||
75 | #define USBVISION_RES_UR (1 << 2) | ||
76 | #define USBVISION_RES_FDL (1 << 3) | ||
77 | #define USBVISION_RES_VDW (1 << 4) | ||
78 | #define USBVISION_DRM_PRM1 0x13 | ||
79 | #define USBVISION_DRM_PRM2 0x14 | ||
80 | #define USBVISION_DRM_PRM3 0x15 | ||
81 | #define USBVISION_DRM_PRM4 0x16 | ||
82 | #define USBVISION_DRM_PRM5 0x17 | ||
83 | #define USBVISION_DRM_PRM6 0x18 | ||
84 | #define USBVISION_DRM_PRM7 0x19 | ||
85 | #define USBVISION_DRM_PRM8 0x1A | ||
86 | #define USBVISION_VIN_REG1 0x1B | ||
87 | #define USBVISION_8_422_SYNC 0x01 | ||
88 | #define USBVISION_16_422_SYNC 0x02 | ||
89 | #define USBVISION_VSNC_POL (1 << 3) | ||
90 | #define USBVISION_HSNC_POL (1 << 4) | ||
91 | #define USBVISION_FID_POL (1 << 5) | ||
92 | #define USBVISION_HVALID_PO (1 << 6) | ||
93 | #define USBVISION_VCLK_POL (1 << 7) | ||
94 | #define USBVISION_VIN_REG2 0x1C | ||
95 | #define USBVISION_AUTO_FID (1 << 0) | ||
96 | #define USBVISION_NONE_INTER (1 << 1) | ||
97 | #define USBVISION_NOHVALID (1 << 2) | ||
98 | #define USBVISION_UV_ID (1 << 3) | ||
99 | #define USBVISION_FIX_2C (1 << 4) | ||
100 | #define USBVISION_SEND_FID (1 << 5) | ||
101 | #define USBVISION_KEEP_BLANK (1 << 7) | ||
102 | #define USBVISION_LXSIZE_I 0x1D | ||
103 | #define USBVISION_MXSIZE_I 0x1E | ||
104 | #define USBVISION_LYSIZE_I 0x1F | ||
105 | #define USBVISION_MYSIZE_I 0x20 | ||
106 | #define USBVISION_LX_OFFST 0x21 | ||
107 | #define USBVISION_MX_OFFST 0x22 | ||
108 | #define USBVISION_LY_OFFST 0x23 | ||
109 | #define USBVISION_MY_OFFST 0x24 | ||
110 | #define USBVISION_FRM_RATE 0x25 | ||
111 | #define USBVISION_LXSIZE_O 0x26 | ||
112 | #define USBVISION_MXSIZE_O 0x27 | ||
113 | #define USBVISION_LYSIZE_O 0x28 | ||
114 | #define USBVISION_MYSIZE_O 0x29 | ||
115 | #define USBVISION_FILT_CONT 0x2A | ||
116 | #define USBVISION_VO_MODE 0x2B | ||
117 | #define USBVISION_INTRA_CYC 0x2C | ||
118 | #define USBVISION_STRIP_SZ 0x2D | ||
119 | #define USBVISION_FORCE_INTRA 0x2E | ||
120 | #define USBVISION_FORCE_UP 0x2F | ||
121 | #define USBVISION_BUF_THR 0x30 | ||
122 | #define USBVISION_DVI_YUV 0x31 | ||
123 | #define USBVISION_AUDIO_CONT 0x32 | ||
124 | #define USBVISION_AUD_PK_LEN 0x33 | ||
125 | #define USBVISION_BLK_PK_LEN 0x34 | ||
126 | #define USBVISION_PCM_THR1 0x38 | ||
127 | #define USBVISION_PCM_THR2 0x39 | ||
128 | #define USBVISION_DIST_THR_L 0x3A | ||
129 | #define USBVISION_DIST_THR_H 0x3B | ||
130 | #define USBVISION_MAX_DIST_L 0x3C | ||
131 | #define USBVISION_MAX_DIST_H 0x3D | ||
132 | #define USBVISION_OP_CODE 0x33 | ||
133 | |||
134 | #define MAX_BYTES_PER_PIXEL 4 | ||
135 | |||
136 | #define MIN_FRAME_WIDTH 64 | ||
137 | #define MAX_USB_WIDTH 320 //384 | ||
138 | #define MAX_FRAME_WIDTH 320 //384 /*streching sometimes causes crashes*/ | ||
139 | |||
140 | #define MIN_FRAME_HEIGHT 48 | ||
141 | #define MAX_USB_HEIGHT 240 //288 | ||
142 | #define MAX_FRAME_HEIGHT 240 //288 /*Streching sometimes causes crashes*/ | ||
143 | |||
144 | #define MAX_FRAME_SIZE (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * MAX_BYTES_PER_PIXEL) | ||
145 | #define USBVISION_CLIPMASK_SIZE (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT / 8) //bytesize of clipmask | ||
146 | |||
147 | #define USBVISION_URB_FRAMES 32 | ||
148 | #define USBVISION_MAX_ISOC_PACKET_SIZE 959 // NT1003 Specs Document says 1023 | ||
149 | |||
150 | #define USBVISION_NUM_HEADERMARKER 20 | ||
151 | #define USBVISION_NUMFRAMES 3 /* Maximum number of frames an application can get */ | ||
152 | #define USBVISION_NUMSBUF 2 /* Dimensioning the USB S buffering */ | ||
153 | |||
154 | #define USBVISION_POWEROFF_TIME 3 * (HZ) // 3 seconds | ||
155 | |||
156 | |||
157 | #define FRAMERATE_MIN 0 | ||
158 | #define FRAMERATE_MAX 31 | ||
159 | |||
160 | enum { | ||
161 | ISOC_MODE_YUV422 = 0x03, | ||
162 | ISOC_MODE_YUV420 = 0x14, | ||
163 | ISOC_MODE_COMPRESS = 0x60, | ||
164 | }; | ||
165 | |||
166 | /* This macro restricts an int variable to an inclusive range */ | ||
167 | #define RESTRICT_TO_RANGE(v,mi,ma) { if ((v) < (mi)) (v) = (mi); else if ((v) > (ma)) (v) = (ma); } | ||
168 | |||
169 | /* | ||
170 | * We use macros to do YUV -> RGB conversion because this is | ||
171 | * very important for speed and totally unimportant for size. | ||
172 | * | ||
173 | * YUV -> RGB Conversion | ||
174 | * --------------------- | ||
175 | * | ||
176 | * B = 1.164*(Y-16) + 2.018*(V-128) | ||
177 | * G = 1.164*(Y-16) - 0.813*(U-128) - 0.391*(V-128) | ||
178 | * R = 1.164*(Y-16) + 1.596*(U-128) | ||
179 | * | ||
180 | * If you fancy integer arithmetics (as you should), hear this: | ||
181 | * | ||
182 | * 65536*B = 76284*(Y-16) + 132252*(V-128) | ||
183 | * 65536*G = 76284*(Y-16) - 53281*(U-128) - 25625*(V-128) | ||
184 | * 65536*R = 76284*(Y-16) + 104595*(U-128) | ||
185 | * | ||
186 | * Make sure the output values are within [0..255] range. | ||
187 | */ | ||
188 | #define LIMIT_RGB(x) (((x) < 0) ? 0 : (((x) > 255) ? 255 : (x))) | ||
189 | #define YUV_TO_RGB_BY_THE_BOOK(my,mu,mv,mr,mg,mb) { \ | ||
190 | int mm_y, mm_yc, mm_u, mm_v, mm_r, mm_g, mm_b; \ | ||
191 | mm_y = (my) - 16; \ | ||
192 | mm_u = (mu) - 128; \ | ||
193 | mm_v = (mv) - 128; \ | ||
194 | mm_yc= mm_y * 76284; \ | ||
195 | mm_b = (mm_yc + 132252*mm_v ) >> 16; \ | ||
196 | mm_g = (mm_yc - 53281*mm_u - 25625*mm_v ) >> 16; \ | ||
197 | mm_r = (mm_yc + 104595*mm_u ) >> 16; \ | ||
198 | mb = LIMIT_RGB(mm_b); \ | ||
199 | mg = LIMIT_RGB(mm_g); \ | ||
200 | mr = LIMIT_RGB(mm_r); \ | ||
201 | } | ||
202 | |||
203 | /* Debugging aid */ | ||
204 | #define USBVISION_SAY_AND_WAIT(what) { \ | ||
205 | wait_queue_head_t wq; \ | ||
206 | init_waitqueue_head(&wq); \ | ||
207 | printk(KERN_INFO "Say: %s\n", what); \ | ||
208 | interruptible_sleep_on_timeout (&wq, HZ*3); \ | ||
209 | } | ||
210 | |||
211 | /* | ||
212 | * This macro checks if usbvision is still operational. The 'usbvision' | ||
213 | * pointer must be valid, usbvision->dev must be valid, we are not | ||
214 | * removing the device and the device has not erred on us. | ||
215 | */ | ||
216 | #define USBVISION_IS_OPERATIONAL(udevice) (\ | ||
217 | (udevice != NULL) && \ | ||
218 | ((udevice)->dev != NULL) && \ | ||
219 | ((udevice)->last_error == 0) && \ | ||
220 | (!(udevice)->remove_pending)) | ||
221 | |||
222 | /* I2C structures */ | ||
223 | struct i2c_algo_usb_data { | ||
224 | void *data; /* private data for lowlevel routines */ | ||
225 | int (*inb) (void *data, unsigned char addr, char *buf, short len); | ||
226 | int (*outb) (void *data, unsigned char addr, char *buf, short len); | ||
227 | |||
228 | /* local settings */ | ||
229 | int udelay; | ||
230 | int mdelay; | ||
231 | int timeout; | ||
232 | }; | ||
233 | |||
234 | #define I2C_USB_ADAP_MAX 16 | ||
235 | |||
236 | /* ----------------------------------------------------------------- */ | ||
237 | /* usbvision video structures */ | ||
238 | /* ----------------------------------------------------------------- */ | ||
239 | enum ScanState { | ||
240 | ScanState_Scanning, /* Scanning for header */ | ||
241 | ScanState_Lines /* Parsing lines */ | ||
242 | }; | ||
243 | |||
244 | /* Completion states of the data parser */ | ||
245 | enum ParseState { | ||
246 | ParseState_Continue, /* Just parse next item */ | ||
247 | ParseState_NextFrame, /* Frame done, send it to V4L */ | ||
248 | ParseState_Out, /* Not enough data for frame */ | ||
249 | ParseState_EndParse /* End parsing */ | ||
250 | }; | ||
251 | |||
252 | enum FrameState { | ||
253 | FrameState_Unused, /* Unused (no MCAPTURE) */ | ||
254 | FrameState_Ready, /* Ready to start grabbing */ | ||
255 | FrameState_Grabbing, /* In the process of being grabbed into */ | ||
256 | FrameState_Done, /* Finished grabbing, but not been synced yet */ | ||
257 | FrameState_DoneHold, /* Are syncing or reading */ | ||
258 | FrameState_Error, /* Something bad happened while processing */ | ||
259 | }; | ||
260 | |||
261 | /* stream states */ | ||
262 | enum StreamState { | ||
263 | Stream_Off, /* Driver streaming is completely OFF */ | ||
264 | Stream_Idle, /* Driver streaming is ready to be put ON by the application */ | ||
265 | Stream_Interrupt, /* Driver streaming must be interrupted */ | ||
266 | Stream_On, /* Driver streaming is put ON by the application */ | ||
267 | }; | ||
268 | |||
269 | enum IsocState { | ||
270 | IsocState_InFrame, /* Isoc packet is member of frame */ | ||
271 | IsocState_NoFrame, /* Isoc packet is not member of any frame */ | ||
272 | }; | ||
273 | |||
274 | struct usb_device; | ||
275 | |||
276 | struct usbvision_sbuf { | ||
277 | char *data; | ||
278 | struct urb *urb; | ||
279 | }; | ||
280 | |||
281 | #define USBVISION_MAGIC_1 0x55 | ||
282 | #define USBVISION_MAGIC_2 0xAA | ||
283 | #define USBVISION_HEADER_LENGTH 0x0c | ||
284 | #define USBVISION_SAA7111_ADDR 0x48 | ||
285 | #define USBVISION_SAA7113_ADDR 0x4a | ||
286 | #define USBVISION_IIC_LRACK 0x20 | ||
287 | #define USBVISION_IIC_LRNACK 0x30 | ||
288 | #define USBVISION_FRAME_FORMAT_PARAM_INTRA (1<<7) | ||
289 | |||
290 | struct usbvision_v4l2_format_st { | ||
291 | int supported; | ||
292 | int bytes_per_pixel; | ||
293 | int depth; | ||
294 | int format; | ||
295 | char *desc; | ||
296 | }; | ||
297 | #define USBVISION_SUPPORTED_PALETTES ARRAY_SIZE(usbvision_v4l2_format) | ||
298 | |||
299 | struct usbvision_frame_header { | ||
300 | unsigned char magic_1; /* 0 magic */ | ||
301 | unsigned char magic_2; /* 1 magic */ | ||
302 | unsigned char headerLength; /* 2 */ | ||
303 | unsigned char frameNum; /* 3 */ | ||
304 | unsigned char framePhase; /* 4 */ | ||
305 | unsigned char frameLatency; /* 5 */ | ||
306 | unsigned char dataFormat; /* 6 */ | ||
307 | unsigned char formatParam; /* 7 */ | ||
308 | unsigned char frameWidthLo; /* 8 */ | ||
309 | unsigned char frameWidthHi; /* 9 */ | ||
310 | unsigned char frameHeightLo; /* 10 */ | ||
311 | unsigned char frameHeightHi; /* 11 */ | ||
312 | __u16 frameWidth; /* 8 - 9 after endian correction*/ | ||
313 | __u16 frameHeight; /* 10 - 11 after endian correction*/ | ||
314 | }; | ||
315 | |||
316 | /* tvnorms */ | ||
317 | struct usbvision_tvnorm { | ||
318 | char *name; | ||
319 | v4l2_std_id id; | ||
320 | /* mode for saa7113h */ | ||
321 | int mode; | ||
322 | }; | ||
323 | |||
324 | struct usbvision_frame { | ||
325 | char *data; /* Frame buffer */ | ||
326 | struct usbvision_frame_header isocHeader; /* Header from stream */ | ||
327 | |||
328 | int width; /* Width application is expecting */ | ||
329 | int height; /* Height */ | ||
330 | int index; /* Frame index */ | ||
331 | int frmwidth; /* Width the frame actually is */ | ||
332 | int frmheight; /* Height */ | ||
333 | |||
334 | volatile int grabstate; /* State of grabbing */ | ||
335 | int scanstate; /* State of scanning */ | ||
336 | |||
337 | struct list_head frame; | ||
338 | |||
339 | int curline; /* Line of frame we're working on */ | ||
340 | |||
341 | long scanlength; /* uncompressed, raw data length of frame */ | ||
342 | long bytes_read; /* amount of scanlength that has been read from data */ | ||
343 | struct usbvision_v4l2_format_st v4l2_format; /* format the user needs*/ | ||
344 | int v4l2_linesize; /* bytes for one videoline*/ | ||
345 | struct timeval timestamp; | ||
346 | int sequence; // How many video frames we send to user | ||
347 | }; | ||
348 | |||
349 | #define CODEC_SAA7113 7113 | ||
350 | #define CODEC_SAA7111 7111 | ||
351 | #define BRIDGE_NT1003 1003 | ||
352 | #define BRIDGE_NT1004 1004 | ||
353 | #define BRIDGE_NT1005 1005 | ||
354 | |||
355 | struct usbvision_device_data_st { | ||
356 | int idVendor; | ||
357 | int idProduct; | ||
358 | int Interface; /* to handle special interface number like BELKIN and Hauppauge WinTV-USB II */ | ||
359 | int Codec; | ||
360 | int VideoChannels; | ||
361 | __u64 VideoNorm; | ||
362 | int AudioChannels; | ||
363 | int Radio; | ||
364 | int vbi; | ||
365 | int Tuner; | ||
366 | int TunerType; | ||
367 | int Vin_Reg1; | ||
368 | int Vin_Reg2; | ||
369 | int X_Offset; | ||
370 | int Y_Offset; | ||
371 | int Dvi_yuv; | ||
372 | char *ModelString; | ||
373 | }; | ||
374 | |||
375 | /* Declared on usbvision-cards.c */ | ||
376 | extern struct usbvision_device_data_st usbvision_device_data[]; | ||
377 | extern struct usb_device_id usbvision_table[]; | ||
378 | |||
379 | struct usb_usbvision { | ||
380 | struct video_device *vdev; /* Video Device */ | ||
381 | struct video_device *rdev; /* Radio Device */ | ||
382 | struct video_device *vbi; /* VBI Device */ | ||
383 | |||
384 | /* i2c Declaration Section*/ | ||
385 | struct i2c_adapter i2c_adap; | ||
386 | struct i2c_algo_usb_data i2c_algo; | ||
387 | struct i2c_client i2c_client; | ||
388 | |||
389 | struct urb *ctrlUrb; | ||
390 | unsigned char ctrlUrbBuffer[8]; | ||
391 | int ctrlUrbBusy; | ||
392 | struct usb_ctrlrequest ctrlUrbSetup; | ||
393 | wait_queue_head_t ctrlUrb_wq; // Processes waiting | ||
394 | struct semaphore ctrlUrbLock; | ||
395 | |||
396 | /* configuration part */ | ||
397 | int have_tuner; | ||
398 | int tuner_type; | ||
399 | int tuner_addr; | ||
400 | int bridgeType; // NT1003, NT1004, NT1005 | ||
401 | int channel; | ||
402 | int radio; | ||
403 | int video_inputs; // # of inputs | ||
404 | unsigned long freq; | ||
405 | int AudioMute; | ||
406 | int AudioChannel; | ||
407 | int isocMode; // format of video data for the usb isoc-transfer | ||
408 | unsigned int nr; // Number of the device | ||
409 | |||
410 | /* Device structure */ | ||
411 | struct usb_device *dev; | ||
412 | unsigned char iface; /* Video interface number */ | ||
413 | unsigned char ifaceAltActive, ifaceAltInactive; /* Alt settings */ | ||
414 | unsigned char Vin_Reg2_Preset; | ||
415 | struct semaphore lock; | ||
416 | struct timer_list powerOffTimer; | ||
417 | struct work_struct powerOffWork; | ||
418 | int power; /* is the device powered on? */ | ||
419 | int user; /* user count for exclusive use */ | ||
420 | int initialized; /* Had we already sent init sequence? */ | ||
421 | int DevModel; /* What type of USBVISION device we got? */ | ||
422 | enum StreamState streaming; /* Are we streaming Isochronous? */ | ||
423 | int last_error; /* What calamity struck us? */ | ||
424 | int curwidth; /* width of the frame the device is currently set to*/ | ||
425 | int curheight; /* height of the frame the device is currently set to*/ | ||
426 | int stretch_width; /* stretch-factor for frame width (from usb to screen)*/ | ||
427 | int stretch_height; /* stretch-factor for frame height (from usb to screen)*/ | ||
428 | char *fbuf; /* Videodev buffer area for mmap*/ | ||
429 | int max_frame_size; /* Bytes in one video frame */ | ||
430 | int fbuf_size; /* Videodev buffer size */ | ||
431 | spinlock_t queue_lock; /* spinlock for protecting mods on inqueue and outqueue */ | ||
432 | struct list_head inqueue, outqueue; /* queued frame list and ready to dequeue frame list */ | ||
433 | wait_queue_head_t wait_frame; /* Processes waiting */ | ||
434 | wait_queue_head_t wait_stream; /* Processes waiting */ | ||
435 | struct usbvision_frame *curFrame; // pointer to current frame, set by usbvision_find_header | ||
436 | struct usbvision_frame frame[USBVISION_NUMFRAMES]; // frame buffer | ||
437 | struct usbvision_sbuf sbuf[USBVISION_NUMSBUF]; // S buffering | ||
438 | volatile int remove_pending; /* If set then about to exit */ | ||
439 | |||
440 | /* Scratch space from the Isochronous Pipe.*/ | ||
441 | unsigned char *scratch; | ||
442 | int scratch_read_ptr; | ||
443 | int scratch_write_ptr; | ||
444 | int scratch_headermarker[USBVISION_NUM_HEADERMARKER]; | ||
445 | int scratch_headermarker_read_ptr; | ||
446 | int scratch_headermarker_write_ptr; | ||
447 | enum IsocState isocstate; | ||
448 | struct usbvision_v4l2_format_st palette; | ||
449 | |||
450 | struct v4l2_capability vcap; /* Video capabilities */ | ||
451 | unsigned int ctl_input; /* selected input */ | ||
452 | struct usbvision_tvnorm *tvnorm; /* selected tv norm */ | ||
453 | unsigned char video_endp; /* 0x82 for USBVISION devices based */ | ||
454 | |||
455 | // Decompression stuff: | ||
456 | unsigned char *IntraFrameBuffer; /* Buffer for reference frame */ | ||
457 | int BlockPos; //for test only | ||
458 | int requestIntra; // 0 = normal; 1 = intra frame is requested; | ||
459 | int lastIsocFrameNum; // check for lost isoc frames | ||
460 | int isocPacketSize; // need to calculate usedBandwidth | ||
461 | int usedBandwidth; // used bandwidth 0-100%, need to set comprLevel | ||
462 | int comprLevel; // How strong (100) or weak (0) is compression | ||
463 | int lastComprLevel; // How strong (100) or weak (0) was compression | ||
464 | int usb_bandwidth; /* Mbit/s */ | ||
465 | |||
466 | /* Statistics that can be overlayed on the screen */ | ||
467 | unsigned long isocUrbCount; // How many URBs we received so far | ||
468 | unsigned long urb_length; /* Length of last URB */ | ||
469 | unsigned long isocDataCount; /* How many bytes we received */ | ||
470 | unsigned long header_count; /* How many frame headers we found */ | ||
471 | unsigned long scratch_ovf_count; /* How many times we overflowed scratch */ | ||
472 | unsigned long isocSkipCount; /* How many empty ISO packets received */ | ||
473 | unsigned long isocErrCount; /* How many bad ISO packets received */ | ||
474 | unsigned long isocPacketCount; // How many packets we totally got | ||
475 | unsigned long timeInIrq; // How long do we need for interrupt | ||
476 | int isocMeasureBandwidthCount; | ||
477 | int frame_num; // How many video frames we send to user | ||
478 | int maxStripLen; // How big is the biggest strip | ||
479 | int comprBlockPos; | ||
480 | int stripLenErrors; // How many times was BlockPos greater than StripLen | ||
481 | int stripMagicErrors; | ||
482 | int stripLineNumberErrors; | ||
483 | int ComprBlockTypes[4]; | ||
484 | }; | ||
485 | |||
486 | |||
487 | /* --------------------------------------------------------------- */ | ||
488 | /* defined in usbvision-i2c.c */ | ||
489 | /* i2c-algo-usb declaration */ | ||
490 | /* --------------------------------------------------------------- */ | ||
491 | |||
492 | int usbvision_i2c_usb_add_bus(struct i2c_adapter *); | ||
493 | int usbvision_i2c_usb_del_bus(struct i2c_adapter *); | ||
494 | |||
495 | static inline void *i2c_get_algo_usb_data (struct i2c_algo_usb_data *dev) | ||
496 | { | ||
497 | return dev->data; | ||
498 | } | ||
499 | |||
500 | static inline void i2c_set_algo_usb_data (struct i2c_algo_usb_data *dev, void *data) | ||
501 | { | ||
502 | dev->data = data; | ||
503 | } | ||
504 | |||
505 | |||
506 | /* ----------------------------------------------------------------------- */ | ||
507 | /* usbvision specific I2C functions */ | ||
508 | /* ----------------------------------------------------------------------- */ | ||
509 | int usbvision_init_i2c(struct usb_usbvision *usbvision); | ||
510 | void call_i2c_clients(struct usb_usbvision *usbvision, unsigned int cmd,void *arg); | ||
511 | |||
512 | /* defined in usbvision-core.c */ | ||
513 | void *usbvision_rvmalloc(unsigned long size); | ||
514 | void usbvision_rvfree(void *mem, unsigned long size); | ||
515 | int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg); | ||
516 | int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg, | ||
517 | unsigned char value); | ||
518 | |||
519 | int usbvision_frames_alloc(struct usb_usbvision *usbvision); | ||
520 | void usbvision_frames_free(struct usb_usbvision *usbvision); | ||
521 | int usbvision_scratch_alloc(struct usb_usbvision *usbvision); | ||
522 | void usbvision_scratch_free(struct usb_usbvision *usbvision); | ||
523 | int usbvision_sbuf_alloc(struct usb_usbvision *usbvision); | ||
524 | void usbvision_sbuf_free(struct usb_usbvision *usbvision); | ||
525 | int usbvision_decompress_alloc(struct usb_usbvision *usbvision); | ||
526 | void usbvision_decompress_free(struct usb_usbvision *usbvision); | ||
527 | |||
528 | int usbvision_setup(struct usb_usbvision *usbvision,int format); | ||
529 | int usbvision_init_isoc(struct usb_usbvision *usbvision); | ||
530 | int usbvision_restart_isoc(struct usb_usbvision *usbvision); | ||
531 | void usbvision_stop_isoc(struct usb_usbvision *usbvision); | ||
532 | |||
533 | int usbvision_set_audio(struct usb_usbvision *usbvision, int AudioChannel); | ||
534 | int usbvision_audio_off(struct usb_usbvision *usbvision); | ||
535 | |||
536 | int usbvision_begin_streaming(struct usb_usbvision *usbvision); | ||
537 | void usbvision_empty_framequeues(struct usb_usbvision *dev); | ||
538 | int usbvision_stream_interrupt(struct usb_usbvision *dev); | ||
539 | |||
540 | int usbvision_muxsel(struct usb_usbvision *usbvision, int channel); | ||
541 | int usbvision_set_input(struct usb_usbvision *usbvision); | ||
542 | int usbvision_set_output(struct usb_usbvision *usbvision, int width, int height); | ||
543 | |||
544 | void usbvision_init_powerOffTimer(struct usb_usbvision *usbvision); | ||
545 | void usbvision_set_powerOffTimer(struct usb_usbvision *usbvision); | ||
546 | void usbvision_reset_powerOffTimer(struct usb_usbvision *usbvision); | ||
547 | int usbvision_power_off(struct usb_usbvision *usbvision); | ||
548 | int usbvision_power_on(struct usb_usbvision *usbvision); | ||
549 | |||
550 | #endif /* __LINUX_USBVISION_H */ | ||
551 | |||
552 | /* | ||
553 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
554 | * --------------------------------------------------------------------------- | ||
555 | * Local variables: | ||
556 | * c-basic-offset: 8 | ||
557 | * End: | ||
558 | */ | ||
diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c index 1d899e2db394..8a13e595304e 100644 --- a/drivers/media/video/v4l1-compat.c +++ b/drivers/media/video/v4l1-compat.c | |||
@@ -350,6 +350,7 @@ v4l_compat_translate_ioctl(struct inode *inode, | |||
350 | struct video_buffer *buffer = arg; | 350 | struct video_buffer *buffer = arg; |
351 | 351 | ||
352 | memset(buffer, 0, sizeof(*buffer)); | 352 | memset(buffer, 0, sizeof(*buffer)); |
353 | memset(&fbuf2, 0, sizeof(fbuf2)); | ||
353 | 354 | ||
354 | err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2); | 355 | err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2); |
355 | if (err < 0) { | 356 | if (err < 0) { |
@@ -616,6 +617,7 @@ v4l_compat_translate_ioctl(struct inode *inode, | |||
616 | case VIDIOCSPICT: /* set tone controls & partial capture format */ | 617 | case VIDIOCSPICT: /* set tone controls & partial capture format */ |
617 | { | 618 | { |
618 | struct video_picture *pict = arg; | 619 | struct video_picture *pict = arg; |
620 | memset(&fbuf2, 0, sizeof(fbuf2)); | ||
619 | 621 | ||
620 | set_v4l_control(inode, file, | 622 | set_v4l_control(inode, file, |
621 | V4L2_CID_BRIGHTNESS, pict->brightness, drv); | 623 | V4L2_CID_BRIGHTNESS, pict->brightness, drv); |
@@ -708,12 +710,22 @@ v4l_compat_translate_ioctl(struct inode *inode, | |||
708 | } | 710 | } |
709 | case VIDIOCSTUNER: /* select a tuner input */ | 711 | case VIDIOCSTUNER: /* select a tuner input */ |
710 | { | 712 | { |
711 | err = 0; | 713 | struct video_tuner *tun = arg; |
714 | struct v4l2_tuner t; | ||
715 | memset(&t,0,sizeof(t)); | ||
716 | |||
717 | t.index=tun->tuner; | ||
718 | |||
719 | err = drv(inode, file, VIDIOC_S_INPUT, &t); | ||
720 | if (err < 0) | ||
721 | dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n",err); | ||
722 | |||
712 | break; | 723 | break; |
713 | } | 724 | } |
714 | case VIDIOCGFREQ: /* get frequency */ | 725 | case VIDIOCGFREQ: /* get frequency */ |
715 | { | 726 | { |
716 | unsigned long *freq = arg; | 727 | unsigned long *freq = arg; |
728 | memset(&freq2,0,sizeof(freq2)); | ||
717 | 729 | ||
718 | freq2.tuner = 0; | 730 | freq2.tuner = 0; |
719 | err = drv(inode, file, VIDIOC_G_FREQUENCY, &freq2); | 731 | err = drv(inode, file, VIDIOC_G_FREQUENCY, &freq2); |
@@ -726,8 +738,8 @@ v4l_compat_translate_ioctl(struct inode *inode, | |||
726 | case VIDIOCSFREQ: /* set frequency */ | 738 | case VIDIOCSFREQ: /* set frequency */ |
727 | { | 739 | { |
728 | unsigned long *freq = arg; | 740 | unsigned long *freq = arg; |
741 | memset(&freq2,0,sizeof(freq2)); | ||
729 | 742 | ||
730 | freq2.tuner = 0; | ||
731 | drv(inode, file, VIDIOC_G_FREQUENCY, &freq2); | 743 | drv(inode, file, VIDIOC_G_FREQUENCY, &freq2); |
732 | freq2.frequency = *freq; | 744 | freq2.frequency = *freq; |
733 | err = drv(inode, file, VIDIOC_S_FREQUENCY, &freq2); | 745 | err = drv(inode, file, VIDIOC_S_FREQUENCY, &freq2); |
@@ -738,6 +750,7 @@ v4l_compat_translate_ioctl(struct inode *inode, | |||
738 | case VIDIOCGAUDIO: /* get audio properties/controls */ | 750 | case VIDIOCGAUDIO: /* get audio properties/controls */ |
739 | { | 751 | { |
740 | struct video_audio *aud = arg; | 752 | struct video_audio *aud = arg; |
753 | memset(&aud2,0,sizeof(aud2)); | ||
741 | 754 | ||
742 | err = drv(inode, file, VIDIOC_G_AUDIO, &aud2); | 755 | err = drv(inode, file, VIDIOC_G_AUDIO, &aud2); |
743 | if (err < 0) { | 756 | if (err < 0) { |
@@ -898,6 +911,7 @@ v4l_compat_translate_ioctl(struct inode *inode, | |||
898 | { | 911 | { |
899 | int *i = arg; | 912 | int *i = arg; |
900 | 913 | ||
914 | memset(&buf2,0,sizeof(buf2)); | ||
901 | buf2.index = *i; | 915 | buf2.index = *i; |
902 | buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 916 | buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
903 | err = drv(inode, file, VIDIOC_QUERYBUF, &buf2); | 917 | err = drv(inode, file, VIDIOC_QUERYBUF, &buf2); |
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 78d28b03ec93..752c82c37f55 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c | |||
@@ -87,6 +87,78 @@ MODULE_LICENSE("GPL"); | |||
87 | */ | 87 | */ |
88 | 88 | ||
89 | 89 | ||
90 | char *v4l2_norm_to_name(v4l2_std_id id) | ||
91 | { | ||
92 | char *name; | ||
93 | |||
94 | switch (id) { | ||
95 | case V4L2_STD_PAL: | ||
96 | name="PAL"; break; | ||
97 | case V4L2_STD_PAL_BG: | ||
98 | name="PAL-BG"; break; | ||
99 | case V4L2_STD_PAL_DK: | ||
100 | name="PAL-DK"; break; | ||
101 | case V4L2_STD_PAL_B: | ||
102 | name="PAL-B"; break; | ||
103 | case V4L2_STD_PAL_B1: | ||
104 | name="PAL-B1"; break; | ||
105 | case V4L2_STD_PAL_G: | ||
106 | name="PAL-G"; break; | ||
107 | case V4L2_STD_PAL_H: | ||
108 | name="PAL-H"; break; | ||
109 | case V4L2_STD_PAL_I: | ||
110 | name="PAL-I"; break; | ||
111 | case V4L2_STD_PAL_D: | ||
112 | name="PAL-D"; break; | ||
113 | case V4L2_STD_PAL_D1: | ||
114 | name="PAL-D1"; break; | ||
115 | case V4L2_STD_PAL_K: | ||
116 | name="PAL-K"; break; | ||
117 | case V4L2_STD_PAL_M: | ||
118 | name="PAL-M"; break; | ||
119 | case V4L2_STD_PAL_N: | ||
120 | name="PAL-N"; break; | ||
121 | case V4L2_STD_PAL_Nc: | ||
122 | name="PAL-Nc"; break; | ||
123 | case V4L2_STD_PAL_60: | ||
124 | name="PAL-60"; break; | ||
125 | case V4L2_STD_NTSC: | ||
126 | name="NTSC"; break; | ||
127 | case V4L2_STD_NTSC_M: | ||
128 | name="NTSC-M"; break; | ||
129 | case V4L2_STD_NTSC_M_JP: | ||
130 | name="NTSC-M-JP"; break; | ||
131 | case V4L2_STD_NTSC_443: | ||
132 | name="NTSC-443"; break; | ||
133 | case V4L2_STD_NTSC_M_KR: | ||
134 | name="NTSC-M-KR"; break; | ||
135 | case V4L2_STD_SECAM: | ||
136 | name="SECAM"; break; | ||
137 | case V4L2_STD_SECAM_DK: | ||
138 | name="SECAM-DK"; break; | ||
139 | case V4L2_STD_SECAM_B: | ||
140 | name="SECAM-B"; break; | ||
141 | case V4L2_STD_SECAM_D: | ||
142 | name="SECAM-D"; break; | ||
143 | case V4L2_STD_SECAM_G: | ||
144 | name="SECAM-G"; break; | ||
145 | case V4L2_STD_SECAM_H: | ||
146 | name="SECAM-H"; break; | ||
147 | case V4L2_STD_SECAM_K: | ||
148 | name="SECAM-K"; break; | ||
149 | case V4L2_STD_SECAM_K1: | ||
150 | name="SECAM-K1"; break; | ||
151 | case V4L2_STD_SECAM_L: | ||
152 | name="SECAM-L"; break; | ||
153 | case V4L2_STD_SECAM_LC: | ||
154 | name="SECAM-LC"; break; | ||
155 | default: | ||
156 | name="Unknown"; break; | ||
157 | } | ||
158 | |||
159 | return name; | ||
160 | } | ||
161 | |||
90 | /* Fill in the fields of a v4l2_standard structure according to the | 162 | /* Fill in the fields of a v4l2_standard structure according to the |
91 | 'id' and 'transmission' parameters. Returns negative on error. */ | 163 | 'id' and 'transmission' parameters. Returns negative on error. */ |
92 | int v4l2_video_std_construct(struct v4l2_standard *vs, | 164 | int v4l2_video_std_construct(struct v4l2_standard *vs, |
@@ -184,11 +256,13 @@ char *v4l2_field_names[] = { | |||
184 | }; | 256 | }; |
185 | 257 | ||
186 | char *v4l2_type_names[] = { | 258 | char *v4l2_type_names[] = { |
187 | [V4L2_BUF_TYPE_VIDEO_CAPTURE] = "video-cap", | 259 | [V4L2_BUF_TYPE_VIDEO_CAPTURE] = "video-cap", |
188 | [V4L2_BUF_TYPE_VIDEO_OVERLAY] = "video-over", | 260 | [V4L2_BUF_TYPE_VIDEO_OVERLAY] = "video-over", |
189 | [V4L2_BUF_TYPE_VIDEO_OUTPUT] = "video-out", | 261 | [V4L2_BUF_TYPE_VIDEO_OUTPUT] = "video-out", |
190 | [V4L2_BUF_TYPE_VBI_CAPTURE] = "vbi-cap", | 262 | [V4L2_BUF_TYPE_VBI_CAPTURE] = "vbi-cap", |
191 | [V4L2_BUF_TYPE_VBI_OUTPUT] = "vbi-out", | 263 | [V4L2_BUF_TYPE_VBI_OUTPUT] = "vbi-out", |
264 | [V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-cap", | ||
265 | [V4L2_BUF_TYPE_SLICED_VBI_OUTPUT] = "slicec-vbi-out", | ||
192 | }; | 266 | }; |
193 | 267 | ||
194 | static char *v4l2_memory_names[] = { | 268 | static char *v4l2_memory_names[] = { |
@@ -1451,6 +1525,7 @@ u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id) | |||
1451 | 1525 | ||
1452 | /* ----------------------------------------------------------------- */ | 1526 | /* ----------------------------------------------------------------- */ |
1453 | 1527 | ||
1528 | EXPORT_SYMBOL(v4l2_norm_to_name); | ||
1454 | EXPORT_SYMBOL(v4l2_video_std_construct); | 1529 | EXPORT_SYMBOL(v4l2_video_std_construct); |
1455 | 1530 | ||
1456 | EXPORT_SYMBOL(v4l2_prio_init); | 1531 | EXPORT_SYMBOL(v4l2_prio_init); |
diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index 41ec0c4b35a2..6a0e8ca72948 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c | |||
@@ -342,7 +342,7 @@ static void dbgbuf(unsigned int cmd, struct video_device *vfd, | |||
342 | 342 | ||
343 | dbgarg (cmd, "%02ld:%02d:%02d.%08ld index=%d, type=%s, " | 343 | dbgarg (cmd, "%02ld:%02d:%02d.%08ld index=%d, type=%s, " |
344 | "bytesused=%d, flags=0x%08d, " | 344 | "bytesused=%d, flags=0x%08d, " |
345 | "field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx\n", | 345 | "field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx, length=%d\n", |
346 | (p->timestamp.tv_sec/3600), | 346 | (p->timestamp.tv_sec/3600), |
347 | (int)(p->timestamp.tv_sec/60)%60, | 347 | (int)(p->timestamp.tv_sec/60)%60, |
348 | (int)(p->timestamp.tv_sec%60), | 348 | (int)(p->timestamp.tv_sec%60), |
@@ -352,7 +352,7 @@ static void dbgbuf(unsigned int cmd, struct video_device *vfd, | |||
352 | p->bytesused,p->flags, | 352 | p->bytesused,p->flags, |
353 | p->field,p->sequence, | 353 | p->field,p->sequence, |
354 | prt_names(p->memory,v4l2_memory_names), | 354 | prt_names(p->memory,v4l2_memory_names), |
355 | p->m.userptr); | 355 | p->m.userptr, p->length); |
356 | dbgarg2 ("timecode= %02d:%02d:%02d type=%d, " | 356 | dbgarg2 ("timecode= %02d:%02d:%02d type=%d, " |
357 | "flags=0x%08d, frames=%d, userbits=0x%08x\n", | 357 | "flags=0x%08d, frames=%d, userbits=0x%08x\n", |
358 | tc->hours,tc->minutes,tc->seconds, | 358 | tc->hours,tc->minutes,tc->seconds, |
@@ -369,9 +369,13 @@ static inline void dbgrect(struct video_device *vfd, char *s, | |||
369 | static inline void v4l_print_pix_fmt (struct video_device *vfd, | 369 | static inline void v4l_print_pix_fmt (struct video_device *vfd, |
370 | struct v4l2_pix_format *fmt) | 370 | struct v4l2_pix_format *fmt) |
371 | { | 371 | { |
372 | dbgarg2 ("width=%d, height=%d, format=0x%08x, field=%s, " | 372 | dbgarg2 ("width=%d, height=%d, format=%c%c%c%c, field=%s, " |
373 | "bytesperline=%d sizeimage=%d, colorspace=%d\n", | 373 | "bytesperline=%d sizeimage=%d, colorspace=%d\n", |
374 | fmt->width,fmt->height,fmt->pixelformat, | 374 | fmt->width,fmt->height, |
375 | (fmt->pixelformat & 0xff), | ||
376 | (fmt->pixelformat >> 8) & 0xff, | ||
377 | (fmt->pixelformat >> 16) & 0xff, | ||
378 | (fmt->pixelformat >> 24) & 0xff, | ||
375 | prt_names(fmt->field,v4l2_field_names_FIXME), | 379 | prt_names(fmt->field,v4l2_field_names_FIXME), |
376 | fmt->bytesperline,fmt->sizeimage,fmt->colorspace); | 380 | fmt->bytesperline,fmt->sizeimage,fmt->colorspace); |
377 | }; | 381 | }; |
@@ -428,6 +432,10 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
428 | v4l_print_ioctl(vfd->name, cmd); | 432 | v4l_print_ioctl(vfd->name, cmd); |
429 | } | 433 | } |
430 | 434 | ||
435 | if (_IOC_TYPE(cmd)=='v') | ||
436 | return v4l_compat_translate_ioctl(inode,file,cmd,arg, | ||
437 | __video_do_ioctl); | ||
438 | |||
431 | switch(cmd) { | 439 | switch(cmd) { |
432 | /* --- capabilities ------------------------------------------ */ | 440 | /* --- capabilities ------------------------------------------ */ |
433 | case VIDIOC_QUERYCAP: | 441 | case VIDIOC_QUERYCAP: |
@@ -526,12 +534,13 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
526 | } | 534 | } |
527 | if (!ret) | 535 | if (!ret) |
528 | dbgarg (cmd, "index=%d, type=%d, flags=%d, " | 536 | dbgarg (cmd, "index=%d, type=%d, flags=%d, " |
529 | "description=%s," | 537 | "pixelformat=%c%c%c%c, description='%s'\n", |
530 | " pixelformat=0x%8x\n", | ||
531 | f->index, f->type, f->flags, | 538 | f->index, f->type, f->flags, |
532 | f->description, | 539 | (f->pixelformat & 0xff), |
533 | f->pixelformat); | 540 | (f->pixelformat >> 8) & 0xff, |
534 | 541 | (f->pixelformat >> 16) & 0xff, | |
542 | (f->pixelformat >> 24) & 0xff, | ||
543 | f->description); | ||
535 | break; | 544 | break; |
536 | } | 545 | } |
537 | case VIDIOC_G_FMT: | 546 | case VIDIOC_G_FMT: |
@@ -829,20 +838,85 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
829 | case VIDIOC_ENUMSTD: | 838 | case VIDIOC_ENUMSTD: |
830 | { | 839 | { |
831 | struct v4l2_standard *p = arg; | 840 | struct v4l2_standard *p = arg; |
832 | unsigned int index = p->index; | 841 | v4l2_std_id id = vfd->tvnorms,curr_id=0; |
842 | unsigned int index = p->index,i; | ||
833 | 843 | ||
834 | if (!vfd->tvnormsize) { | 844 | if (index<0) { |
835 | printk (KERN_WARNING "%s: no TV norms defined!\n", | 845 | ret=-EINVAL; |
836 | vfd->name); | ||
837 | break; | 846 | break; |
838 | } | 847 | } |
839 | 848 | ||
840 | if (index<0 || index >= vfd->tvnormsize) { | 849 | /* Return norm array on a canonical way */ |
841 | ret=-EINVAL; | 850 | for (i=0;i<= index && id; i++) { |
842 | break; | 851 | if ( (id & V4L2_STD_PAL) == V4L2_STD_PAL) { |
852 | curr_id = V4L2_STD_PAL; | ||
853 | } else if ( (id & V4L2_STD_PAL_BG) == V4L2_STD_PAL_BG) { | ||
854 | curr_id = V4L2_STD_PAL_BG; | ||
855 | } else if ( (id & V4L2_STD_PAL_DK) == V4L2_STD_PAL_DK) { | ||
856 | curr_id = V4L2_STD_PAL_DK; | ||
857 | } else if ( (id & V4L2_STD_PAL_B) == V4L2_STD_PAL_B) { | ||
858 | curr_id = V4L2_STD_PAL_B; | ||
859 | } else if ( (id & V4L2_STD_PAL_B1) == V4L2_STD_PAL_B1) { | ||
860 | curr_id = V4L2_STD_PAL_B1; | ||
861 | } else if ( (id & V4L2_STD_PAL_G) == V4L2_STD_PAL_G) { | ||
862 | curr_id = V4L2_STD_PAL_G; | ||
863 | } else if ( (id & V4L2_STD_PAL_H) == V4L2_STD_PAL_H) { | ||
864 | curr_id = V4L2_STD_PAL_H; | ||
865 | } else if ( (id & V4L2_STD_PAL_I) == V4L2_STD_PAL_I) { | ||
866 | curr_id = V4L2_STD_PAL_I; | ||
867 | } else if ( (id & V4L2_STD_PAL_D) == V4L2_STD_PAL_D) { | ||
868 | curr_id = V4L2_STD_PAL_D; | ||
869 | } else if ( (id & V4L2_STD_PAL_D1) == V4L2_STD_PAL_D1) { | ||
870 | curr_id = V4L2_STD_PAL_D1; | ||
871 | } else if ( (id & V4L2_STD_PAL_K) == V4L2_STD_PAL_K) { | ||
872 | curr_id = V4L2_STD_PAL_K; | ||
873 | } else if ( (id & V4L2_STD_PAL_M) == V4L2_STD_PAL_M) { | ||
874 | curr_id = V4L2_STD_PAL_M; | ||
875 | } else if ( (id & V4L2_STD_PAL_N) == V4L2_STD_PAL_N) { | ||
876 | curr_id = V4L2_STD_PAL_N; | ||
877 | } else if ( (id & V4L2_STD_PAL_Nc) == V4L2_STD_PAL_Nc) { | ||
878 | curr_id = V4L2_STD_PAL_Nc; | ||
879 | } else if ( (id & V4L2_STD_PAL_60) == V4L2_STD_PAL_60) { | ||
880 | curr_id = V4L2_STD_PAL_60; | ||
881 | } else if ( (id & V4L2_STD_NTSC) == V4L2_STD_NTSC) { | ||
882 | curr_id = V4L2_STD_NTSC; | ||
883 | } else if ( (id & V4L2_STD_NTSC_M) == V4L2_STD_NTSC_M) { | ||
884 | curr_id = V4L2_STD_NTSC_M; | ||
885 | } else if ( (id & V4L2_STD_NTSC_M_JP) == V4L2_STD_NTSC_M_JP) { | ||
886 | curr_id = V4L2_STD_NTSC_M_JP; | ||
887 | } else if ( (id & V4L2_STD_NTSC_443) == V4L2_STD_NTSC_443) { | ||
888 | curr_id = V4L2_STD_NTSC_443; | ||
889 | } else if ( (id & V4L2_STD_NTSC_M_KR) == V4L2_STD_NTSC_M_KR) { | ||
890 | curr_id = V4L2_STD_NTSC_M_KR; | ||
891 | } else if ( (id & V4L2_STD_SECAM) == V4L2_STD_SECAM) { | ||
892 | curr_id = V4L2_STD_SECAM; | ||
893 | } else if ( (id & V4L2_STD_SECAM_DK) == V4L2_STD_SECAM_DK) { | ||
894 | curr_id = V4L2_STD_SECAM_DK; | ||
895 | } else if ( (id & V4L2_STD_SECAM_B) == V4L2_STD_SECAM_B) { | ||
896 | curr_id = V4L2_STD_SECAM_B; | ||
897 | } else if ( (id & V4L2_STD_SECAM_D) == V4L2_STD_SECAM_D) { | ||
898 | curr_id = V4L2_STD_SECAM_D; | ||
899 | } else if ( (id & V4L2_STD_SECAM_G) == V4L2_STD_SECAM_G) { | ||
900 | curr_id = V4L2_STD_SECAM_G; | ||
901 | } else if ( (id & V4L2_STD_SECAM_H) == V4L2_STD_SECAM_H) { | ||
902 | curr_id = V4L2_STD_SECAM_H; | ||
903 | } else if ( (id & V4L2_STD_SECAM_K) == V4L2_STD_SECAM_K) { | ||
904 | curr_id = V4L2_STD_SECAM_K; | ||
905 | } else if ( (id & V4L2_STD_SECAM_K1) == V4L2_STD_SECAM_K1) { | ||
906 | curr_id = V4L2_STD_SECAM_K1; | ||
907 | } else if ( (id & V4L2_STD_SECAM_L) == V4L2_STD_SECAM_L) { | ||
908 | curr_id = V4L2_STD_SECAM_L; | ||
909 | } else if ( (id & V4L2_STD_SECAM_LC) == V4L2_STD_SECAM_LC) { | ||
910 | curr_id = V4L2_STD_SECAM_LC; | ||
911 | } else { | ||
912 | break; | ||
913 | } | ||
914 | id &= ~curr_id; | ||
843 | } | 915 | } |
844 | v4l2_video_std_construct(p, vfd->tvnorms[p->index].id, | 916 | if (i<=index) |
845 | vfd->tvnorms[p->index].name); | 917 | return -EINVAL; |
918 | |||
919 | v4l2_video_std_construct(p, curr_id,v4l2_norm_to_name(curr_id)); | ||
846 | p->index = index; | 920 | p->index = index; |
847 | 921 | ||
848 | dbgarg (cmd, "index=%d, id=%Ld, name=%s, fps=%d/%d, " | 922 | dbgarg (cmd, "index=%d, id=%Ld, name=%s, fps=%d/%d, " |
@@ -868,39 +942,23 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
868 | } | 942 | } |
869 | case VIDIOC_S_STD: | 943 | case VIDIOC_S_STD: |
870 | { | 944 | { |
871 | v4l2_std_id *id = arg; | 945 | v4l2_std_id *id = arg,norm; |
872 | unsigned int i; | ||
873 | |||
874 | if (!vfd->tvnormsize) { | ||
875 | printk (KERN_WARNING "%s: no TV norms defined!\n", | ||
876 | vfd->name); | ||
877 | break; | ||
878 | } | ||
879 | 946 | ||
880 | dbgarg (cmd, "value=%Lu\n", (long long unsigned) *id); | 947 | dbgarg (cmd, "value=%Lu\n", (long long unsigned) *id); |
881 | 948 | ||
882 | /* First search for exact match */ | 949 | norm = (*id) & vfd->tvnorms; |
883 | for (i = 0; i < vfd->tvnormsize; i++) | 950 | if ( vfd->tvnorms && !norm) /* Check if std is supported */ |
884 | if (*id == vfd->tvnorms[i].id) | ||
885 | break; | ||
886 | /* Then for a generic video std that contains desired std */ | ||
887 | if (i == vfd->tvnormsize) | ||
888 | for (i = 0; i < vfd->tvnormsize; i++) | ||
889 | if (*id & vfd->tvnorms[i].id) | ||
890 | break; | ||
891 | if (i == vfd->tvnormsize) { | ||
892 | break; | 951 | break; |
893 | } | ||
894 | 952 | ||
895 | /* Calls the specific handler */ | 953 | /* Calls the specific handler */ |
896 | if (vfd->vidioc_s_std) | 954 | if (vfd->vidioc_s_std) |
897 | ret=vfd->vidioc_s_std(file, fh, i); | 955 | ret=vfd->vidioc_s_std(file, fh, &norm); |
898 | else | 956 | else |
899 | ret=-EINVAL; | 957 | ret=-EINVAL; |
900 | 958 | ||
901 | /* Updates standard information */ | 959 | /* Updates standard information */ |
902 | if (!ret) | 960 | if (ret>=0) |
903 | vfd->current_norm=*id; | 961 | vfd->current_norm=norm; |
904 | 962 | ||
905 | break; | 963 | break; |
906 | } | 964 | } |
@@ -1088,9 +1146,13 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
1088 | case VIDIOC_G_AUDIO: | 1146 | case VIDIOC_G_AUDIO: |
1089 | { | 1147 | { |
1090 | struct v4l2_audio *p=arg; | 1148 | struct v4l2_audio *p=arg; |
1149 | __u32 index=p->index; | ||
1091 | 1150 | ||
1092 | if (!vfd->vidioc_g_audio) | 1151 | if (!vfd->vidioc_g_audio) |
1093 | break; | 1152 | break; |
1153 | |||
1154 | memset(p,0,sizeof(*p)); | ||
1155 | p->index=index; | ||
1094 | dbgarg(cmd, "Get for index=%d\n", p->index); | 1156 | dbgarg(cmd, "Get for index=%d\n", p->index); |
1095 | ret=vfd->vidioc_g_audio(file, fh, p); | 1157 | ret=vfd->vidioc_g_audio(file, fh, p); |
1096 | if (!ret) | 1158 | if (!ret) |
@@ -1288,25 +1350,12 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
1288 | ret=vfd->vidioc_g_parm(file, fh, p); | 1350 | ret=vfd->vidioc_g_parm(file, fh, p); |
1289 | } else { | 1351 | } else { |
1290 | struct v4l2_standard s; | 1352 | struct v4l2_standard s; |
1291 | int i; | ||
1292 | |||
1293 | if (!vfd->tvnormsize) { | ||
1294 | printk (KERN_WARNING "%s: no TV norms defined!\n", | ||
1295 | vfd->name); | ||
1296 | break; | ||
1297 | } | ||
1298 | 1353 | ||
1299 | if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 1354 | if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1300 | return -EINVAL; | 1355 | return -EINVAL; |
1301 | 1356 | ||
1302 | for (i = 0; i < vfd->tvnormsize; i++) | ||
1303 | if (vfd->tvnorms[i].id == vfd->current_norm) | ||
1304 | break; | ||
1305 | if (i >= vfd->tvnormsize) | ||
1306 | return -EINVAL; | ||
1307 | |||
1308 | v4l2_video_std_construct(&s, vfd->current_norm, | 1357 | v4l2_video_std_construct(&s, vfd->current_norm, |
1309 | vfd->tvnorms[i].name); | 1358 | v4l2_norm_to_name(vfd->current_norm)); |
1310 | 1359 | ||
1311 | memset(p,0,sizeof(*p)); | 1360 | memset(p,0,sizeof(*p)); |
1312 | 1361 | ||
@@ -1329,8 +1378,14 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
1329 | case VIDIOC_G_TUNER: | 1378 | case VIDIOC_G_TUNER: |
1330 | { | 1379 | { |
1331 | struct v4l2_tuner *p=arg; | 1380 | struct v4l2_tuner *p=arg; |
1381 | __u32 index=p->index; | ||
1382 | |||
1332 | if (!vfd->vidioc_g_tuner) | 1383 | if (!vfd->vidioc_g_tuner) |
1333 | break; | 1384 | break; |
1385 | |||
1386 | memset(p,0,sizeof(*p)); | ||
1387 | p->index=index; | ||
1388 | |||
1334 | ret=vfd->vidioc_g_tuner(file, fh, p); | 1389 | ret=vfd->vidioc_g_tuner(file, fh, p); |
1335 | if (!ret) | 1390 | if (!ret) |
1336 | dbgarg (cmd, "index=%d, name=%s, type=%d, " | 1391 | dbgarg (cmd, "index=%d, name=%s, type=%d, " |
@@ -1363,6 +1418,9 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
1363 | struct v4l2_frequency *p=arg; | 1418 | struct v4l2_frequency *p=arg; |
1364 | if (!vfd->vidioc_g_frequency) | 1419 | if (!vfd->vidioc_g_frequency) |
1365 | break; | 1420 | break; |
1421 | |||
1422 | memset(p,0,sizeof(*p)); | ||
1423 | |||
1366 | ret=vfd->vidioc_g_frequency(file, fh, p); | 1424 | ret=vfd->vidioc_g_frequency(file, fh, p); |
1367 | if (!ret) | 1425 | if (!ret) |
1368 | dbgarg (cmd, "tuner=%d, type=%d, frequency=%d\n", | 1426 | dbgarg (cmd, "tuner=%d, type=%d, frequency=%d\n", |
@@ -1396,12 +1454,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
1396 | ret=vfd->vidioc_log_status(file, fh); | 1454 | ret=vfd->vidioc_log_status(file, fh); |
1397 | break; | 1455 | break; |
1398 | } | 1456 | } |
1399 | 1457 | } /* switch */ | |
1400 | /* --- Others --------------------------------------------- */ | ||
1401 | |||
1402 | default: | ||
1403 | ret=v4l_compat_translate_ioctl(inode,file,cmd,arg,__video_do_ioctl); | ||
1404 | } | ||
1405 | 1458 | ||
1406 | if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) { | 1459 | if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) { |
1407 | if (ret<0) { | 1460 | if (ret<0) { |
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 9986de5cb3d6..474ddb779643 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c | |||
@@ -1044,16 +1044,8 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | |||
1044 | return (0); | 1044 | return (0); |
1045 | } | 1045 | } |
1046 | 1046 | ||
1047 | static struct v4l2_tvnorm tvnorms[] = { | 1047 | static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *i) |
1048 | { | ||
1049 | .name = "NTSC-M", | ||
1050 | .id = V4L2_STD_NTSC_M, | ||
1051 | } | ||
1052 | }; | ||
1053 | |||
1054 | static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id a) | ||
1055 | { | 1048 | { |
1056 | |||
1057 | return 0; | 1049 | return 0; |
1058 | } | 1050 | } |
1059 | 1051 | ||
@@ -1333,8 +1325,8 @@ static struct video_device vivi = { | |||
1333 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | 1325 | #ifdef CONFIG_VIDEO_V4L1_COMPAT |
1334 | .vidiocgmbuf = vidiocgmbuf, | 1326 | .vidiocgmbuf = vidiocgmbuf, |
1335 | #endif | 1327 | #endif |
1336 | .tvnorms = tvnorms, | 1328 | .tvnorms = V4L2_STD_NTSC_M, |
1337 | .tvnormsize = ARRAY_SIZE(tvnorms), | 1329 | .current_norm = V4L2_STD_NTSC_M, |
1338 | }; | 1330 | }; |
1339 | /* ----------------------------------------------------------------- | 1331 | /* ----------------------------------------------------------------- |
1340 | Initialization and module stuff | 1332 | Initialization and module stuff |
@@ -1361,8 +1353,6 @@ static int __init vivi_init(void) | |||
1361 | dev->vidq.timeout.data = (unsigned long)dev; | 1353 | dev->vidq.timeout.data = (unsigned long)dev; |
1362 | init_timer(&dev->vidq.timeout); | 1354 | init_timer(&dev->vidq.timeout); |
1363 | 1355 | ||
1364 | vivi.current_norm = tvnorms[0].id; | ||
1365 | |||
1366 | ret = video_register_device(&vivi, VFL_TYPE_GRABBER, video_nr); | 1356 | ret = video_register_device(&vivi, VFL_TYPE_GRABBER, video_nr); |
1367 | printk(KERN_INFO "Video Technology Magazine Virtual Video Capture Board (Load status: %d)\n", ret); | 1357 | printk(KERN_INFO "Video Technology Magazine Virtual Video Capture Board (Load status: %d)\n", ret); |
1368 | return ret; | 1358 | return ret; |
diff --git a/drivers/media/video/zr36120.c b/drivers/media/video/zr36120.c deleted file mode 100644 index 0cbf564388a6..000000000000 --- a/drivers/media/video/zr36120.c +++ /dev/null | |||
@@ -1,2079 +0,0 @@ | |||
1 | /* | ||
2 | zr36120.c - Zoran 36120/36125 based framegrabbers | ||
3 | |||
4 | Copyright (C) 1998-1999 Pauline Middelink <middelin@polyware.nl> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/errno.h> | ||
25 | #include <linux/fs.h> | ||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/major.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/vmalloc.h> | ||
30 | #include <linux/mm.h> | ||
31 | #include <linux/pci.h> | ||
32 | #include <linux/signal.h> | ||
33 | #include <linux/wait.h> | ||
34 | #include <asm/io.h> | ||
35 | #include <asm/pgtable.h> | ||
36 | #include <asm/page.h> | ||
37 | #include <linux/sched.h> | ||
38 | #include <linux/video_decoder.h> | ||
39 | |||
40 | #include <asm/uaccess.h> | ||
41 | |||
42 | #include "tuner.h" | ||
43 | #include "zr36120.h" | ||
44 | #include "zr36120_mem.h" | ||
45 | |||
46 | /* mark an required function argument unused - lintism */ | ||
47 | #define UNUSED(x) (void)(x) | ||
48 | |||
49 | /* sensible default */ | ||
50 | #ifndef CARDTYPE | ||
51 | #define CARDTYPE 0 | ||
52 | #endif | ||
53 | |||
54 | /* Anybody who uses more than four? */ | ||
55 | #define ZORAN_MAX 4 | ||
56 | |||
57 | static unsigned int triton1=0; /* triton1 chipset? */ | ||
58 | static unsigned int cardtype[ZORAN_MAX]={ [ 0 ... ZORAN_MAX-1 ] = CARDTYPE }; | ||
59 | static int video_nr = -1; | ||
60 | static int vbi_nr = -1; | ||
61 | |||
62 | static struct pci_device_id zr36120_pci_tbl[] = { | ||
63 | { PCI_VENDOR_ID_ZORAN,PCI_DEVICE_ID_ZORAN_36120, | ||
64 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | ||
65 | { 0 } | ||
66 | }; | ||
67 | MODULE_DEVICE_TABLE(pci, zr36120_pci_tbl); | ||
68 | |||
69 | MODULE_AUTHOR("Pauline Middelink <middelin@polyware.nl>"); | ||
70 | MODULE_DESCRIPTION("Zoran ZR36120 based framegrabber"); | ||
71 | MODULE_LICENSE("GPL"); | ||
72 | |||
73 | module_param(triton1, uint, 0); | ||
74 | module_param_array(cardtype, uint, NULL, 0); | ||
75 | module_param(video_nr, int, 0); | ||
76 | module_param(vbi_nr, int, 0); | ||
77 | |||
78 | static int zoran_cards; | ||
79 | static struct zoran zorans[ZORAN_MAX]; | ||
80 | |||
81 | /* | ||
82 | * the meaning of each element can be found in zr36120.h | ||
83 | * Determining the value of gpdir/gpval can be tricky. The | ||
84 | * best way is to run the card under the original software | ||
85 | * and read the values from the general purpose registers | ||
86 | * 0x28 and 0x2C. How you do that is left as an exercise | ||
87 | * to the impatient reader :) | ||
88 | */ | ||
89 | #define T 1 /* to separate the bools from the ints */ | ||
90 | #define F 0 | ||
91 | static struct tvcard tvcards[] = { | ||
92 | /* reported working by <middelin@polyware.nl> */ | ||
93 | /*0*/ { "Trust Victor II", | ||
94 | 2, 0, T, T, T, T, 0x7F, 0x80, { 1, SVHS(6) }, { 0 } }, | ||
95 | /* reported working by <Michael.Paxton@aihw.gov.au> */ | ||
96 | /*1*/ { "Aitech WaveWatcher TV-PCI", | ||
97 | 3, 0, T, F, T, T, 0x7F, 0x80, { 1, TUNER(3), SVHS(6) }, { 0 } }, | ||
98 | /* reported working by ? */ | ||
99 | /*2*/ { "Genius Video Wonder PCI Video Capture Card", | ||
100 | 2, 0, T, T, T, T, 0x7F, 0x80, { 1, SVHS(6) }, { 0 } }, | ||
101 | /* reported working by <Pascal.Gabriel@wanadoo.fr> */ | ||
102 | /*3*/ { "Guillemot Maxi-TV PCI", | ||
103 | 2, 0, T, T, T, T, 0x7F, 0x80, { 1, SVHS(6) }, { 0 } }, | ||
104 | /* reported working by "Craig Whitmore <lennon@igrin.co.nz> */ | ||
105 | /*4*/ { "Quadrant Buster", | ||
106 | 3, 3, T, F, T, T, 0x7F, 0x80, { SVHS(1), TUNER(2), 3 }, { 1, 2, 3 } }, | ||
107 | /* a debug entry which has all inputs mapped */ | ||
108 | /*5*/ { "ZR36120 based framegrabber (all inputs enabled)", | ||
109 | 6, 0, T, T, T, T, 0x7F, 0x80, { 1, 2, 3, 4, 5, 6 }, { 0 } } | ||
110 | }; | ||
111 | #undef T | ||
112 | #undef F | ||
113 | #define NRTVCARDS (sizeof(tvcards)/sizeof(tvcards[0])) | ||
114 | |||
115 | #ifdef __sparc__ | ||
116 | #define ENDIANESS 0 | ||
117 | #else | ||
118 | #define ENDIANESS ZORAN_VFEC_LE | ||
119 | #endif | ||
120 | |||
121 | static struct { const char name[8]; uint mode; uint bpp; } palette2fmt[] = { | ||
122 | /* n/a */ { "n/a", 0, 0 }, | ||
123 | /* GREY */ { "GRAY", 0, 0 }, | ||
124 | /* HI240 */ { "HI240", 0, 0 }, | ||
125 | /* RGB565 */ { "RGB565", ZORAN_VFEC_RGB_RGB565|ENDIANESS, 2 }, | ||
126 | /* RGB24 */ { "RGB24", ZORAN_VFEC_RGB_RGB888|ENDIANESS|ZORAN_VFEC_PACK24, 3 }, | ||
127 | /* RGB32 */ { "RGB32", ZORAN_VFEC_RGB_RGB888|ENDIANESS, 4 }, | ||
128 | /* RGB555 */ { "RGB555", ZORAN_VFEC_RGB_RGB555|ENDIANESS, 2 }, | ||
129 | /* YUV422 */ { "YUV422", ZORAN_VFEC_RGB_YUV422|ENDIANESS, 2 }, | ||
130 | /* YUYV */ { "YUYV", 0, 0 }, | ||
131 | /* UYVY */ { "UYVY", 0, 0 }, | ||
132 | /* YUV420 */ { "YUV420", 0, 0 }, | ||
133 | /* YUV411 */ { "YUV411", 0, 0 }, | ||
134 | /* RAW */ { "RAW", 0, 0 }, | ||
135 | /* YUV422P */ { "YUV422P", 0, 0 }, | ||
136 | /* YUV411P */ { "YUV411P", 0, 0 }}; | ||
137 | #define NRPALETTES (sizeof(palette2fmt)/sizeof(palette2fmt[0])) | ||
138 | #undef ENDIANESS | ||
139 | |||
140 | /* ----------------------------------------------------------------------- */ | ||
141 | /* ZORAN chipset detector */ | ||
142 | /* shamelessly stolen from bttv.c */ | ||
143 | /* Reason for beeing here: we need to detect if we are running on a */ | ||
144 | /* Triton based chipset, and if so, enable a certain bit */ | ||
145 | /* ----------------------------------------------------------------------- */ | ||
146 | static | ||
147 | void __init handle_chipset(void) | ||
148 | { | ||
149 | /* Just in case some nut set this to something dangerous */ | ||
150 | if (triton1) | ||
151 | triton1 = ZORAN_VDC_TRICOM; | ||
152 | |||
153 | if (pci_pci_problems & PCIPCI_TRITON) { | ||
154 | printk(KERN_INFO "zoran: Host bridge 82437FX Triton PIIX\n"); | ||
155 | triton1 = ZORAN_VDC_TRICOM; | ||
156 | } | ||
157 | } | ||
158 | |||
159 | /* ----------------------------------------------------------------------- */ | ||
160 | /* ZORAN functions */ | ||
161 | /* ----------------------------------------------------------------------- */ | ||
162 | |||
163 | static void zoran_set_geo(struct zoran* ztv, struct vidinfo* i); | ||
164 | |||
165 | #if 0 /* unused */ | ||
166 | static | ||
167 | void zoran_dump(struct zoran *ztv) | ||
168 | { | ||
169 | char str[256]; | ||
170 | char *p=str; /* shut up, gcc! */ | ||
171 | int i; | ||
172 | |||
173 | for (i=0; i<0x60; i+=4) { | ||
174 | if ((i % 16) == 0) { | ||
175 | if (i) printk("%s\n",str); | ||
176 | p = str; | ||
177 | p+= sprintf(str, KERN_DEBUG " %04x: ",i); | ||
178 | } | ||
179 | p += sprintf(p, "%08x ",zrread(i)); | ||
180 | } | ||
181 | } | ||
182 | #endif /* unused */ | ||
183 | |||
184 | static | ||
185 | void reap_states(struct zoran* ztv) | ||
186 | { | ||
187 | /* count frames */ | ||
188 | ztv->fieldnr++; | ||
189 | |||
190 | /* | ||
191 | * Are we busy at all? | ||
192 | * This depends on if there is a workqueue AND the | ||
193 | * videotransfer is enabled on the chip... | ||
194 | */ | ||
195 | if (ztv->workqueue && (zrread(ZORAN_VDC) & ZORAN_VDC_VIDEN)) | ||
196 | { | ||
197 | struct vidinfo* newitem; | ||
198 | |||
199 | /* did we get a complete frame? */ | ||
200 | if (zrread(ZORAN_VSTR) & ZORAN_VSTR_GRAB) | ||
201 | return; | ||
202 | |||
203 | DEBUG(printk(CARD_DEBUG "completed %s at %p\n",CARD,ztv->workqueue->kindof==FBUFFER_GRAB?"grab":"read",ztv->workqueue)); | ||
204 | |||
205 | /* we are done with this buffer, tell everyone */ | ||
206 | ztv->workqueue->status = FBUFFER_DONE; | ||
207 | ztv->workqueue->fieldnr = ztv->fieldnr; | ||
208 | /* not good, here for BTTV_FIELDNR reasons */ | ||
209 | ztv->lastfieldnr = ztv->fieldnr; | ||
210 | |||
211 | switch (ztv->workqueue->kindof) { | ||
212 | case FBUFFER_GRAB: | ||
213 | wake_up_interruptible(&ztv->grabq); | ||
214 | break; | ||
215 | case FBUFFER_VBI: | ||
216 | wake_up_interruptible(&ztv->vbiq); | ||
217 | break; | ||
218 | default: | ||
219 | printk(CARD_INFO "somebody killed the workqueue (kindof=%d)!\n",CARD,ztv->workqueue->kindof); | ||
220 | } | ||
221 | |||
222 | /* item completed, skip to next item in queue */ | ||
223 | write_lock(&ztv->lock); | ||
224 | newitem = ztv->workqueue->next; | ||
225 | ztv->workqueue->next = 0; /* mark completed */ | ||
226 | ztv->workqueue = newitem; | ||
227 | write_unlock(&ztv->lock); | ||
228 | } | ||
229 | |||
230 | /* | ||
231 | * ok, so it seems we have nothing in progress right now. | ||
232 | * Lets see if we can find some work. | ||
233 | */ | ||
234 | if (ztv->workqueue) | ||
235 | { | ||
236 | struct vidinfo* newitem; | ||
237 | again: | ||
238 | |||
239 | DEBUG(printk(CARD_DEBUG "starting %s at %p\n",CARD,ztv->workqueue->kindof==FBUFFER_GRAB?"grab":"read",ztv->workqueue)); | ||
240 | |||
241 | /* loadup the frame settings */ | ||
242 | read_lock(&ztv->lock); | ||
243 | zoran_set_geo(ztv,ztv->workqueue); | ||
244 | read_unlock(&ztv->lock); | ||
245 | |||
246 | switch (ztv->workqueue->kindof) { | ||
247 | case FBUFFER_GRAB: | ||
248 | case FBUFFER_VBI: | ||
249 | zrand(~ZORAN_OCR_OVLEN, ZORAN_OCR); | ||
250 | zror(ZORAN_VSTR_SNAPSHOT,ZORAN_VSTR); | ||
251 | zror(ZORAN_VDC_VIDEN,ZORAN_VDC); | ||
252 | |||
253 | /* start single-shot grab */ | ||
254 | zror(ZORAN_VSTR_GRAB, ZORAN_VSTR); | ||
255 | break; | ||
256 | default: | ||
257 | printk(CARD_INFO "what is this doing on the queue? (kindof=%d)\n",CARD,ztv->workqueue->kindof); | ||
258 | write_lock(&ztv->lock); | ||
259 | newitem = ztv->workqueue->next; | ||
260 | ztv->workqueue->next = 0; | ||
261 | ztv->workqueue = newitem; | ||
262 | write_unlock(&ztv->lock); | ||
263 | if (newitem) | ||
264 | goto again; /* yeah, sure.. */ | ||
265 | } | ||
266 | /* bye for now */ | ||
267 | return; | ||
268 | } | ||
269 | DEBUG(printk(CARD_DEBUG "nothing in queue\n",CARD)); | ||
270 | |||
271 | /* | ||
272 | * What? Even the workqueue is empty? Am i really here | ||
273 | * for nothing? Did i come all that way to... do nothing? | ||
274 | */ | ||
275 | |||
276 | /* do we need to overlay? */ | ||
277 | if (test_bit(STATE_OVERLAY, &ztv->state)) | ||
278 | { | ||
279 | /* are we already overlaying? */ | ||
280 | if (!(zrread(ZORAN_OCR) & ZORAN_OCR_OVLEN) || | ||
281 | !(zrread(ZORAN_VDC) & ZORAN_VDC_VIDEN)) | ||
282 | { | ||
283 | DEBUG(printk(CARD_DEBUG "starting overlay\n",CARD)); | ||
284 | |||
285 | read_lock(&ztv->lock); | ||
286 | zoran_set_geo(ztv,&ztv->overinfo); | ||
287 | read_unlock(&ztv->lock); | ||
288 | |||
289 | zror(ZORAN_OCR_OVLEN, ZORAN_OCR); | ||
290 | zrand(~ZORAN_VSTR_SNAPSHOT,ZORAN_VSTR); | ||
291 | zror(ZORAN_VDC_VIDEN,ZORAN_VDC); | ||
292 | } | ||
293 | |||
294 | /* | ||
295 | * leave overlaying on, but turn interrupts off. | ||
296 | */ | ||
297 | zrand(~ZORAN_ICR_EN,ZORAN_ICR); | ||
298 | return; | ||
299 | } | ||
300 | |||
301 | /* do we have any VBI idle time processing? */ | ||
302 | if (test_bit(STATE_VBI, &ztv->state)) | ||
303 | { | ||
304 | struct vidinfo* item; | ||
305 | struct vidinfo* lastitem; | ||
306 | |||
307 | /* protect the workqueue */ | ||
308 | write_lock(&ztv->lock); | ||
309 | lastitem = ztv->workqueue; | ||
310 | if (lastitem) | ||
311 | while (lastitem->next) lastitem = lastitem->next; | ||
312 | for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++) | ||
313 | if (item->next == 0 && item->status == FBUFFER_FREE) | ||
314 | { | ||
315 | DEBUG(printk(CARD_DEBUG "%p added to queue\n",CARD,item)); | ||
316 | item->status = FBUFFER_BUSY; | ||
317 | if (!lastitem) | ||
318 | ztv->workqueue = item; | ||
319 | else | ||
320 | lastitem->next = item; | ||
321 | lastitem = item; | ||
322 | } | ||
323 | write_unlock(&ztv->lock); | ||
324 | if (ztv->workqueue) | ||
325 | goto again; /* hey, _i_ graduated :) */ | ||
326 | } | ||
327 | |||
328 | /* | ||
329 | * Then we must be realy IDLE | ||
330 | */ | ||
331 | DEBUG(printk(CARD_DEBUG "turning off\n",CARD)); | ||
332 | /* nothing further to do, disable DMA and further IRQs */ | ||
333 | zrand(~ZORAN_VDC_VIDEN,ZORAN_VDC); | ||
334 | zrand(~ZORAN_ICR_EN,ZORAN_ICR); | ||
335 | } | ||
336 | |||
337 | static | ||
338 | void zoran_irq(int irq, void *dev_id) | ||
339 | { | ||
340 | u32 stat,estat; | ||
341 | int count = 0; | ||
342 | struct zoran *ztv = dev_id; | ||
343 | |||
344 | UNUSED(irq); | ||
345 | for (;;) { | ||
346 | /* get/clear interrupt status bits */ | ||
347 | stat=zrread(ZORAN_ISR); | ||
348 | estat=stat & zrread(ZORAN_ICR); | ||
349 | if (!estat) | ||
350 | return; | ||
351 | zrwrite(estat,ZORAN_ISR); | ||
352 | IDEBUG(printk(CARD_DEBUG "estat %08x\n",CARD,estat)); | ||
353 | IDEBUG(printk(CARD_DEBUG " stat %08x\n",CARD,stat)); | ||
354 | |||
355 | if (estat & ZORAN_ISR_CODE) | ||
356 | { | ||
357 | IDEBUG(printk(CARD_DEBUG "CodReplIRQ\n",CARD)); | ||
358 | } | ||
359 | if (estat & ZORAN_ISR_GIRQ0) | ||
360 | { | ||
361 | IDEBUG(printk(CARD_DEBUG "GIRQ0\n",CARD)); | ||
362 | if (!ztv->card->usegirq1) | ||
363 | reap_states(ztv); | ||
364 | } | ||
365 | if (estat & ZORAN_ISR_GIRQ1) | ||
366 | { | ||
367 | IDEBUG(printk(CARD_DEBUG "GIRQ1\n",CARD)); | ||
368 | if (ztv->card->usegirq1) | ||
369 | reap_states(ztv); | ||
370 | } | ||
371 | |||
372 | count++; | ||
373 | if (count > 10) | ||
374 | printk(CARD_ERR "irq loop %d (%x)\n",CARD,count,estat); | ||
375 | if (count > 20) | ||
376 | { | ||
377 | zrwrite(0, ZORAN_ICR); | ||
378 | printk(CARD_ERR "IRQ lockup, cleared int mask\n",CARD); | ||
379 | } | ||
380 | } | ||
381 | } | ||
382 | |||
383 | static | ||
384 | int zoran_muxsel(struct zoran* ztv, int channel, int norm) | ||
385 | { | ||
386 | int rv; | ||
387 | |||
388 | /* set the new video norm */ | ||
389 | rv = i2c_control_device(&(ztv->i2c), I2C_DRIVERID_VIDEODECODER, DECODER_SET_NORM, &norm); | ||
390 | if (rv) | ||
391 | return rv; | ||
392 | ztv->norm = norm; | ||
393 | |||
394 | /* map the given channel to the cards decoder's channel */ | ||
395 | channel = ztv->card->video_mux[channel] & CHANNEL_MASK; | ||
396 | |||
397 | /* set the new channel */ | ||
398 | rv = i2c_control_device(&(ztv->i2c), I2C_DRIVERID_VIDEODECODER, DECODER_SET_INPUT, &channel); | ||
399 | return rv; | ||
400 | } | ||
401 | |||
402 | /* Tell the interrupt handler what to to. */ | ||
403 | static | ||
404 | void zoran_cap(struct zoran* ztv, int on) | ||
405 | { | ||
406 | DEBUG(printk(CARD_DEBUG "zoran_cap(%d) state=%x\n",CARD,on,ztv->state)); | ||
407 | |||
408 | if (on) { | ||
409 | ztv->running = 1; | ||
410 | |||
411 | /* | ||
412 | * turn interrupts (back) on. The DMA will be enabled | ||
413 | * inside the irq handler when it detects a restart. | ||
414 | */ | ||
415 | zror(ZORAN_ICR_EN,ZORAN_ICR); | ||
416 | } | ||
417 | else { | ||
418 | /* | ||
419 | * turn both interrupts and DMA off | ||
420 | */ | ||
421 | zrand(~ZORAN_VDC_VIDEN,ZORAN_VDC); | ||
422 | zrand(~ZORAN_ICR_EN,ZORAN_ICR); | ||
423 | |||
424 | ztv->running = 0; | ||
425 | } | ||
426 | } | ||
427 | |||
428 | static ulong dmask[] = { | ||
429 | 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFC, 0xFFFFFFF8, | ||
430 | 0xFFFFFFF0, 0xFFFFFFE0, 0xFFFFFFC0, 0xFFFFFF80, | ||
431 | 0xFFFFFF00, 0xFFFFFE00, 0xFFFFFC00, 0xFFFFF800, | ||
432 | 0xFFFFF000, 0xFFFFE000, 0xFFFFC000, 0xFFFF8000, | ||
433 | 0xFFFF0000, 0xFFFE0000, 0xFFFC0000, 0xFFF80000, | ||
434 | 0xFFF00000, 0xFFE00000, 0xFFC00000, 0xFF800000, | ||
435 | 0xFF000000, 0xFE000000, 0xFC000000, 0xF8000000, | ||
436 | 0xF0000000, 0xE0000000, 0xC0000000, 0x80000000 | ||
437 | }; | ||
438 | |||
439 | static | ||
440 | void zoran_built_overlay(struct zoran* ztv, int count, struct video_clip *vcp) | ||
441 | { | ||
442 | ulong* mtop; | ||
443 | int ystep = (ztv->vidXshift + ztv->vidWidth+31)/32; /* next DWORD */ | ||
444 | int i; | ||
445 | |||
446 | DEBUG(printk(KERN_DEBUG " overlay at %p, ystep=%d, clips=%d\n",ztv->overinfo.overlay,ystep,count)); | ||
447 | |||
448 | for (i=0; i<count; i++) { | ||
449 | struct video_clip *vp = vcp+i; | ||
450 | UNUSED(vp); | ||
451 | DEBUG(printk(KERN_DEBUG " %d: clip(%d,%d,%d,%d)\n", i,vp->x,vp->y,vp->width,vp->height)); | ||
452 | } | ||
453 | |||
454 | /* | ||
455 | * activate the visible portion of the screen | ||
456 | * Note we take some shortcuts here, because we | ||
457 | * know the width can never be < 32. (I.e. a DWORD) | ||
458 | * We also assume the overlay starts somewhere in | ||
459 | * the FIRST dword. | ||
460 | */ | ||
461 | { | ||
462 | int start = ztv->vidXshift; | ||
463 | ulong firstd = dmask[start]; | ||
464 | ulong lastd = ~dmask[(start + ztv->overinfo.w) & 31]; | ||
465 | mtop = ztv->overinfo.overlay; | ||
466 | for (i=0; i<ztv->overinfo.h; i++) { | ||
467 | int w = ztv->vidWidth; | ||
468 | ulong* line = mtop; | ||
469 | if (start & 31) { | ||
470 | *line++ = firstd; | ||
471 | w -= 32-(start&31); | ||
472 | } | ||
473 | memset(line, ~0, w/8); | ||
474 | if (w & 31) | ||
475 | line[w/32] = lastd; | ||
476 | mtop += ystep; | ||
477 | } | ||
478 | } | ||
479 | |||
480 | /* process clipping regions */ | ||
481 | for (i=0; i<count; i++) { | ||
482 | int h; | ||
483 | if (vcp->x < 0 || (uint)vcp->x > ztv->overinfo.w || | ||
484 | vcp->y < 0 || vcp->y > ztv->overinfo.h || | ||
485 | vcp->width < 0 || (uint)(vcp->x+vcp->width) > ztv->overinfo.w || | ||
486 | vcp->height < 0 || (vcp->y+vcp->height) > ztv->overinfo.h) | ||
487 | { | ||
488 | DEBUG(printk(CARD_DEBUG "invalid clipzone (%d,%d,%d,%d) not in (0,0,%d,%d), adapting\n",CARD,vcp->x,vcp->y,vcp->width,vcp->height,ztv->overinfo.w,ztv->overinfo.h)); | ||
489 | if (vcp->x < 0) vcp->x = 0; | ||
490 | if ((uint)vcp->x > ztv->overinfo.w) vcp->x = ztv->overinfo.w; | ||
491 | if (vcp->y < 0) vcp->y = 0; | ||
492 | if (vcp->y > ztv->overinfo.h) vcp->y = ztv->overinfo.h; | ||
493 | if (vcp->width < 0) vcp->width = 0; | ||
494 | if ((uint)(vcp->x+vcp->width) > ztv->overinfo.w) vcp->width = ztv->overinfo.w - vcp->x; | ||
495 | if (vcp->height < 0) vcp->height = 0; | ||
496 | if (vcp->y+vcp->height > ztv->overinfo.h) vcp->height = ztv->overinfo.h - vcp->y; | ||
497 | // continue; | ||
498 | } | ||
499 | |||
500 | mtop = &ztv->overinfo.overlay[vcp->y*ystep]; | ||
501 | for (h=0; h<=vcp->height; h++) { | ||
502 | int w; | ||
503 | int x = ztv->vidXshift + vcp->x; | ||
504 | for (w=0; w<=vcp->width; w++) { | ||
505 | clear_bit(x&31, &mtop[x/32]); | ||
506 | x++; | ||
507 | } | ||
508 | mtop += ystep; | ||
509 | } | ||
510 | ++vcp; | ||
511 | } | ||
512 | |||
513 | mtop = ztv->overinfo.overlay; | ||
514 | zrwrite(virt_to_bus(mtop), ZORAN_MTOP); | ||
515 | zrwrite(virt_to_bus(mtop+ystep), ZORAN_MBOT); | ||
516 | zraor((ztv->vidInterlace*ystep)<<0,~ZORAN_OCR_MASKSTRIDE,ZORAN_OCR); | ||
517 | } | ||
518 | |||
519 | struct tvnorm | ||
520 | { | ||
521 | u16 Wt, Wa, Ht, Ha, HStart, VStart; | ||
522 | }; | ||
523 | |||
524 | static struct tvnorm tvnorms[] = { | ||
525 | /* PAL-BDGHI */ | ||
526 | /* { 864, 720, 625, 576, 131, 21 },*/ | ||
527 | /*00*/ { 864, 768, 625, 576, 81, 17 }, | ||
528 | /* NTSC */ | ||
529 | /*01*/ { 858, 720, 525, 480, 121, 10 }, | ||
530 | /* SECAM */ | ||
531 | /*02*/ { 864, 720, 625, 576, 131, 21 }, | ||
532 | /* BW50 */ | ||
533 | /*03*/ { 864, 720, 625, 576, 131, 21 }, | ||
534 | /* BW60 */ | ||
535 | /*04*/ { 858, 720, 525, 480, 121, 10 } | ||
536 | }; | ||
537 | #define TVNORMS (sizeof(tvnorms)/sizeof(tvnorm)) | ||
538 | |||
539 | /* | ||
540 | * Program the chip for a setup as described in the vidinfo struct. | ||
541 | * | ||
542 | * Side-effects: calculates vidXshift, vidInterlace, | ||
543 | * vidHeight, vidWidth which are used in a later stage | ||
544 | * to calculate the overlay mask | ||
545 | * | ||
546 | * This is an internal function, as such it does not check the | ||
547 | * validity of the struct members... Spectaculair crashes will | ||
548 | * follow /very/ quick when you're wrong and the chip right :) | ||
549 | */ | ||
550 | static | ||
551 | void zoran_set_geo(struct zoran* ztv, struct vidinfo* i) | ||
552 | { | ||
553 | ulong top, bot; | ||
554 | int stride; | ||
555 | int winWidth, winHeight; | ||
556 | int maxWidth, maxHeight, maxXOffset, maxYOffset; | ||
557 | long vfec; | ||
558 | |||
559 | DEBUG(printk(CARD_DEBUG "set_geo(rect=(%d,%d,%d,%d), norm=%d, format=%d, bpp=%d, bpl=%d, busadr=%lx, overlay=%p)\n",CARD,i->x,i->y,i->w,i->h,ztv->norm,i->format,i->bpp,i->bpl,i->busadr,i->overlay)); | ||
560 | |||
561 | /* | ||
562 | * make sure the DMA transfers are inhibited during our | ||
563 | * reprogramming of the chip | ||
564 | */ | ||
565 | zrand(~ZORAN_VDC_VIDEN,ZORAN_VDC); | ||
566 | |||
567 | maxWidth = tvnorms[ztv->norm].Wa; | ||
568 | maxHeight = tvnorms[ztv->norm].Ha/2; | ||
569 | maxXOffset = tvnorms[ztv->norm].HStart; | ||
570 | maxYOffset = tvnorms[ztv->norm].VStart; | ||
571 | |||
572 | /* setup vfec register (keep ExtFl,TopField and VCLKPol settings) */ | ||
573 | vfec = (zrread(ZORAN_VFEC) & (ZORAN_VFEC_EXTFL|ZORAN_VFEC_TOPFIELD|ZORAN_VFEC_VCLKPOL)) | | ||
574 | (palette2fmt[i->format].mode & (ZORAN_VFEC_RGB|ZORAN_VFEC_ERRDIF|ZORAN_VFEC_LE|ZORAN_VFEC_PACK24)); | ||
575 | |||
576 | /* | ||
577 | * Set top, bottom ptrs. Since these must be DWORD aligned, | ||
578 | * possible adjust the x and the width of the window. | ||
579 | * so the endposition stay the same. The vidXshift will make | ||
580 | * sure we are not writing pixels before the requested x. | ||
581 | */ | ||
582 | ztv->vidXshift = 0; | ||
583 | winWidth = i->w; | ||
584 | if (winWidth < 0) | ||
585 | winWidth = -winWidth; | ||
586 | top = i->busadr + i->x*i->bpp + i->y*i->bpl; | ||
587 | if (top & 3) { | ||
588 | ztv->vidXshift = (top & 3) / i->bpp; | ||
589 | winWidth += ztv->vidXshift; | ||
590 | DEBUG(printk(KERN_DEBUG " window-x shifted %d pixels left\n",ztv->vidXshift)); | ||
591 | top &= ~3; | ||
592 | } | ||
593 | |||
594 | /* | ||
595 | * bottom points to next frame but in interleaved mode we want | ||
596 | * to 'mix' the 2 frames to one capture, so 'bot' points to one | ||
597 | * (physical) line below the top line. | ||
598 | */ | ||
599 | bot = top + i->bpl; | ||
600 | zrwrite(top,ZORAN_VTOP); | ||
601 | zrwrite(bot,ZORAN_VBOT); | ||
602 | |||
603 | /* | ||
604 | * Make sure the winWidth is DWORD aligned too, | ||
605 | * thereby automaticly making sure the stride to the | ||
606 | * next line is DWORD aligned too (as required by spec). | ||
607 | */ | ||
608 | if ((winWidth*i->bpp) & 3) { | ||
609 | DEBUG(printk(KERN_DEBUG " window-width enlarged by %d pixels\n",(winWidth*i->bpp) & 3)); | ||
610 | winWidth += (winWidth*i->bpp) & 3; | ||
611 | } | ||
612 | |||
613 | /* determine the DispMode and stride */ | ||
614 | if (i->h >= 0 && i->h <= maxHeight) { | ||
615 | /* single frame grab suffices for this height. */ | ||
616 | vfec |= ZORAN_VFEC_DISPMOD; | ||
617 | ztv->vidInterlace = 0; | ||
618 | stride = i->bpl - (winWidth*i->bpp); | ||
619 | winHeight = i->h; | ||
620 | } | ||
621 | else { | ||
622 | /* interleaving needed for this height */ | ||
623 | ztv->vidInterlace = 1; | ||
624 | stride = i->bpl*2 - (winWidth*i->bpp); | ||
625 | winHeight = i->h/2; | ||
626 | } | ||
627 | if (winHeight < 0) /* can happen for VBI! */ | ||
628 | winHeight = -winHeight; | ||
629 | |||
630 | /* safety net, sometimes bpl is too short??? */ | ||
631 | if (stride<0) { | ||
632 | DEBUG(printk(CARD_DEBUG "WARNING stride = %d\n",CARD,stride)); | ||
633 | stride = 0; | ||
634 | } | ||
635 | |||
636 | zraor((winHeight<<12)|(winWidth<<0),~(ZORAN_VDC_VIDWINHT|ZORAN_VDC_VIDWINWID), ZORAN_VDC); | ||
637 | zraor(stride<<16,~ZORAN_VSTR_DISPSTRIDE,ZORAN_VSTR); | ||
638 | |||
639 | /* remember vidWidth, vidHeight for overlay calculations */ | ||
640 | ztv->vidWidth = winWidth; | ||
641 | ztv->vidHeight = winHeight; | ||
642 | DEBUG(printk(KERN_DEBUG " top=%08lx, bottom=%08lx\n",top,bot)); | ||
643 | DEBUG(printk(KERN_DEBUG " winWidth=%d, winHeight=%d\n",winWidth,winHeight)); | ||
644 | DEBUG(printk(KERN_DEBUG " maxWidth=%d, maxHeight=%d\n",maxWidth,maxHeight)); | ||
645 | DEBUG(printk(KERN_DEBUG " stride=%d\n",stride)); | ||
646 | |||
647 | /* | ||
648 | * determine horizontal scales and crops | ||
649 | */ | ||
650 | if (i->w < 0) { | ||
651 | int Hstart = 1; | ||
652 | int Hend = Hstart + winWidth; | ||
653 | DEBUG(printk(KERN_DEBUG " Y: scale=0, start=%d, end=%d\n", Hstart, Hend)); | ||
654 | zraor((Hstart<<10)|(Hend<<0),~(ZORAN_VFEH_HSTART|ZORAN_VFEH_HEND),ZORAN_VFEH); | ||
655 | } | ||
656 | else { | ||
657 | int Wa = maxWidth; | ||
658 | int X = (winWidth*64+Wa-1)/Wa; | ||
659 | int We = winWidth*64/X; | ||
660 | int HorDcm = 64-X; | ||
661 | int hcrop1 = 2*(Wa-We)/4; | ||
662 | /* | ||
663 | * BUGFIX: Juha Nurmela <junki@qn-lpr2-165.quicknet.inet.fi> | ||
664 | * found the solution to the color phase shift. | ||
665 | * See ChangeLog for the full explanation) | ||
666 | */ | ||
667 | int Hstart = (maxXOffset + hcrop1) | 1; | ||
668 | int Hend = Hstart + We - 1; | ||
669 | |||
670 | DEBUG(printk(KERN_DEBUG " X: scale=%d, start=%d, end=%d\n", HorDcm, Hstart, Hend)); | ||
671 | |||
672 | zraor((Hstart<<10)|(Hend<<0),~(ZORAN_VFEH_HSTART|ZORAN_VFEH_HEND),ZORAN_VFEH); | ||
673 | vfec |= HorDcm<<14; | ||
674 | |||
675 | if (HorDcm<16) | ||
676 | vfec |= ZORAN_VFEC_HFILTER_1; /* no filter */ | ||
677 | else if (HorDcm<32) | ||
678 | vfec |= ZORAN_VFEC_HFILTER_3; /* 3 tap filter */ | ||
679 | else if (HorDcm<48) | ||
680 | vfec |= ZORAN_VFEC_HFILTER_4; /* 4 tap filter */ | ||
681 | else vfec |= ZORAN_VFEC_HFILTER_5; /* 5 tap filter */ | ||
682 | } | ||
683 | |||
684 | /* | ||
685 | * Determine vertical scales and crops | ||
686 | * | ||
687 | * when height is negative, we want to read starting at line 0 | ||
688 | * One day someone might need access to these lines... | ||
689 | */ | ||
690 | if (i->h < 0) { | ||
691 | int Vstart = 0; | ||
692 | int Vend = Vstart + winHeight; | ||
693 | DEBUG(printk(KERN_DEBUG " Y: scale=0, start=%d, end=%d\n", Vstart, Vend)); | ||
694 | zraor((Vstart<<10)|(Vend<<0),~(ZORAN_VFEV_VSTART|ZORAN_VFEV_VEND),ZORAN_VFEV); | ||
695 | } | ||
696 | else { | ||
697 | int Ha = maxHeight; | ||
698 | int Y = (winHeight*64+Ha-1)/Ha; | ||
699 | int He = winHeight*64/Y; | ||
700 | int VerDcm = 64-Y; | ||
701 | int vcrop1 = 2*(Ha-He)/4; | ||
702 | int Vstart = maxYOffset + vcrop1; | ||
703 | int Vend = Vstart + He - 1; | ||
704 | |||
705 | DEBUG(printk(KERN_DEBUG " Y: scale=%d, start=%d, end=%d\n", VerDcm, Vstart, Vend)); | ||
706 | zraor((Vstart<<10)|(Vend<<0),~(ZORAN_VFEV_VSTART|ZORAN_VFEV_VEND),ZORAN_VFEV); | ||
707 | vfec |= VerDcm<<8; | ||
708 | } | ||
709 | |||
710 | DEBUG(printk(KERN_DEBUG " F: format=%d(=%s)\n",i->format,palette2fmt[i->format].name)); | ||
711 | |||
712 | /* setup the requested format */ | ||
713 | zrwrite(vfec, ZORAN_VFEC); | ||
714 | } | ||
715 | |||
716 | static | ||
717 | void zoran_common_open(struct zoran* ztv, int flags) | ||
718 | { | ||
719 | UNUSED(flags); | ||
720 | |||
721 | /* already opened? */ | ||
722 | if (ztv->users++ != 0) | ||
723 | return; | ||
724 | |||
725 | /* unmute audio */ | ||
726 | /* /what/ audio? */ | ||
727 | |||
728 | ztv->state = 0; | ||
729 | |||
730 | /* setup the encoder to the initial values */ | ||
731 | ztv->picture.colour=254<<7; | ||
732 | ztv->picture.brightness=128<<8; | ||
733 | ztv->picture.hue=128<<8; | ||
734 | ztv->picture.contrast=216<<7; | ||
735 | i2c_control_device(&ztv->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_PICTURE, &ztv->picture); | ||
736 | |||
737 | /* default to the composite input since my camera is there */ | ||
738 | zoran_muxsel(ztv, 0, VIDEO_MODE_PAL); | ||
739 | } | ||
740 | |||
741 | static | ||
742 | void zoran_common_close(struct zoran* ztv) | ||
743 | { | ||
744 | if (--ztv->users != 0) | ||
745 | return; | ||
746 | |||
747 | /* mute audio */ | ||
748 | /* /what/ audio? */ | ||
749 | |||
750 | /* stop the chip */ | ||
751 | zoran_cap(ztv, 0); | ||
752 | } | ||
753 | |||
754 | /* | ||
755 | * Open a zoran card. Right now the flags are just a hack | ||
756 | */ | ||
757 | static int zoran_open(struct video_device *dev, int flags) | ||
758 | { | ||
759 | struct zoran *ztv = (struct zoran*)dev; | ||
760 | struct vidinfo* item; | ||
761 | char* pos; | ||
762 | |||
763 | DEBUG(printk(CARD_DEBUG "open(dev,%d)\n",CARD,flags)); | ||
764 | |||
765 | /********************************************* | ||
766 | * We really should be doing lazy allocing... | ||
767 | *********************************************/ | ||
768 | /* allocate a frame buffer */ | ||
769 | if (!ztv->fbuffer) | ||
770 | ztv->fbuffer = bmalloc(ZORAN_MAX_FBUFSIZE); | ||
771 | if (!ztv->fbuffer) { | ||
772 | /* could not get a buffer, bail out */ | ||
773 | return -ENOBUFS; | ||
774 | } | ||
775 | /* at this time we _always_ have a framebuffer */ | ||
776 | memset(ztv->fbuffer,0,ZORAN_MAX_FBUFSIZE); | ||
777 | |||
778 | if (!ztv->overinfo.overlay) | ||
779 | ztv->overinfo.overlay = kmalloc(1024*1024/8, GFP_KERNEL); | ||
780 | if (!ztv->overinfo.overlay) { | ||
781 | /* could not get an overlay buffer, bail out */ | ||
782 | bfree(ztv->fbuffer, ZORAN_MAX_FBUFSIZE); | ||
783 | return -ENOBUFS; | ||
784 | } | ||
785 | /* at this time we _always_ have a overlay */ | ||
786 | |||
787 | /* clear buffer status, and give them a DMAable address */ | ||
788 | pos = ztv->fbuffer; | ||
789 | for (item=ztv->grabinfo; item!=ztv->grabinfo+ZORAN_MAX_FBUFFERS; item++) | ||
790 | { | ||
791 | item->status = FBUFFER_FREE; | ||
792 | item->memadr = pos; | ||
793 | item->busadr = virt_to_bus(pos); | ||
794 | pos += ZORAN_MAX_FBUFFER; | ||
795 | } | ||
796 | |||
797 | /* do the common part of all open's */ | ||
798 | zoran_common_open(ztv, flags); | ||
799 | |||
800 | return 0; | ||
801 | } | ||
802 | |||
803 | static | ||
804 | void zoran_close(struct video_device* dev) | ||
805 | { | ||
806 | struct zoran *ztv = (struct zoran*)dev; | ||
807 | |||
808 | DEBUG(printk(CARD_DEBUG "close(dev)\n",CARD)); | ||
809 | |||
810 | /* driver specific closure */ | ||
811 | clear_bit(STATE_OVERLAY, &ztv->state); | ||
812 | |||
813 | zoran_common_close(ztv); | ||
814 | |||
815 | /* | ||
816 | * This is sucky but right now I can't find a good way to | ||
817 | * be sure its safe to free the buffer. We wait 5-6 fields | ||
818 | * which is more than sufficient to be sure. | ||
819 | */ | ||
820 | msleep(100); /* Wait 1/10th of a second */ | ||
821 | |||
822 | /* free the allocated framebuffer */ | ||
823 | bfree(ztv->fbuffer, ZORAN_MAX_FBUFSIZE); | ||
824 | ztv->fbuffer = 0; | ||
825 | kfree(ztv->overinfo.overlay); | ||
826 | ztv->overinfo.overlay = 0; | ||
827 | |||
828 | } | ||
829 | |||
830 | /* | ||
831 | * This read function could be used reentrant in a SMP situation. | ||
832 | * | ||
833 | * This is made possible by the spinlock which is kept till we | ||
834 | * found and marked a buffer for our own use. The lock must | ||
835 | * be released as soon as possible to prevent lock contention. | ||
836 | */ | ||
837 | static | ||
838 | long zoran_read(struct video_device* dev, char* buf, unsigned long count, int nonblock) | ||
839 | { | ||
840 | struct zoran *ztv = (struct zoran*)dev; | ||
841 | unsigned long max; | ||
842 | struct vidinfo* unused = 0; | ||
843 | struct vidinfo* done = 0; | ||
844 | |||
845 | DEBUG(printk(CARD_DEBUG "zoran_read(%p,%ld,%d)\n",CARD,buf,count,nonblock)); | ||
846 | |||
847 | /* find ourself a free or completed buffer */ | ||
848 | for (;;) { | ||
849 | struct vidinfo* item; | ||
850 | |||
851 | write_lock_irq(&ztv->lock); | ||
852 | for (item=ztv->grabinfo; item!=ztv->grabinfo+ZORAN_MAX_FBUFFERS; item++) | ||
853 | { | ||
854 | if (!unused && item->status == FBUFFER_FREE) | ||
855 | unused = item; | ||
856 | if (!done && item->status == FBUFFER_DONE) | ||
857 | done = item; | ||
858 | } | ||
859 | if (done || unused) | ||
860 | break; | ||
861 | |||
862 | /* no more free buffers, wait for them. */ | ||
863 | write_unlock_irq(&ztv->lock); | ||
864 | if (nonblock) | ||
865 | return -EWOULDBLOCK; | ||
866 | interruptible_sleep_on(&ztv->grabq); | ||
867 | if (signal_pending(current)) | ||
868 | return -EINTR; | ||
869 | } | ||
870 | |||
871 | /* Do we have 'ready' data? */ | ||
872 | if (!done) { | ||
873 | /* no? than this will take a while... */ | ||
874 | if (nonblock) { | ||
875 | write_unlock_irq(&ztv->lock); | ||
876 | return -EWOULDBLOCK; | ||
877 | } | ||
878 | |||
879 | /* mark the unused buffer as wanted */ | ||
880 | unused->status = FBUFFER_BUSY; | ||
881 | unused->w = 320; | ||
882 | unused->h = 240; | ||
883 | unused->format = VIDEO_PALETTE_RGB24; | ||
884 | unused->bpp = palette2fmt[unused->format].bpp; | ||
885 | unused->bpl = unused->w * unused->bpp; | ||
886 | unused->next = 0; | ||
887 | { /* add to tail of queue */ | ||
888 | struct vidinfo* oldframe = ztv->workqueue; | ||
889 | if (!oldframe) ztv->workqueue = unused; | ||
890 | else { | ||
891 | while (oldframe->next) oldframe = oldframe->next; | ||
892 | oldframe->next = unused; | ||
893 | } | ||
894 | } | ||
895 | write_unlock_irq(&ztv->lock); | ||
896 | |||
897 | /* tell the state machine we want it filled /NOW/ */ | ||
898 | zoran_cap(ztv, 1); | ||
899 | |||
900 | /* wait till this buffer gets grabbed */ | ||
901 | wait_event_interruptible(ztv->grabq, | ||
902 | (unused->status != FBUFFER_BUSY)); | ||
903 | /* see if a signal did it */ | ||
904 | if (signal_pending(current)) | ||
905 | return -EINTR; | ||
906 | done = unused; | ||
907 | } | ||
908 | else | ||
909 | write_unlock_irq(&ztv->lock); | ||
910 | |||
911 | /* Yes! we got data! */ | ||
912 | max = done->bpl * done->h; | ||
913 | if (count > max) | ||
914 | count = max; | ||
915 | if (copy_to_user((void*)buf, done->memadr, count)) | ||
916 | count = -EFAULT; | ||
917 | |||
918 | /* keep the engine running */ | ||
919 | done->status = FBUFFER_FREE; | ||
920 | // zoran_cap(ztv,1); | ||
921 | |||
922 | /* tell listeners this buffer became free */ | ||
923 | wake_up_interruptible(&ztv->grabq); | ||
924 | |||
925 | /* goodbye */ | ||
926 | DEBUG(printk(CARD_DEBUG "zoran_read() returns %lu\n",CARD,count)); | ||
927 | return count; | ||
928 | } | ||
929 | |||
930 | static | ||
931 | long zoran_write(struct video_device* dev, const char* buf, unsigned long count, int nonblock) | ||
932 | { | ||
933 | struct zoran *ztv = (struct zoran *)dev; | ||
934 | UNUSED(ztv); UNUSED(dev); UNUSED(buf); UNUSED(count); UNUSED(nonblock); | ||
935 | DEBUG(printk(CARD_DEBUG "zoran_write\n",CARD)); | ||
936 | return -EINVAL; | ||
937 | } | ||
938 | |||
939 | static | ||
940 | unsigned int zoran_poll(struct video_device *dev, struct file *file, poll_table *wait) | ||
941 | { | ||
942 | struct zoran *ztv = (struct zoran *)dev; | ||
943 | struct vidinfo* item; | ||
944 | unsigned int mask = 0; | ||
945 | |||
946 | poll_wait(file, &ztv->grabq, wait); | ||
947 | |||
948 | for (item=ztv->grabinfo; item!=ztv->grabinfo+ZORAN_MAX_FBUFFERS; item++) | ||
949 | if (item->status == FBUFFER_DONE) | ||
950 | { | ||
951 | mask |= (POLLIN | POLLRDNORM); | ||
952 | break; | ||
953 | } | ||
954 | |||
955 | DEBUG(printk(CARD_DEBUG "zoran_poll()=%x\n",CARD,mask)); | ||
956 | |||
957 | return mask; | ||
958 | } | ||
959 | |||
960 | /* append a new clipregion to the vector of video_clips */ | ||
961 | static | ||
962 | void new_clip(struct video_window* vw, struct video_clip* vcp, int x, int y, int w, int h) | ||
963 | { | ||
964 | vcp[vw->clipcount].x = x; | ||
965 | vcp[vw->clipcount].y = y; | ||
966 | vcp[vw->clipcount].width = w; | ||
967 | vcp[vw->clipcount].height = h; | ||
968 | vw->clipcount++; | ||
969 | } | ||
970 | |||
971 | static | ||
972 | int zoran_ioctl(struct video_device* dev, unsigned int cmd, void *arg) | ||
973 | { | ||
974 | struct zoran* ztv = (struct zoran*)dev; | ||
975 | |||
976 | switch (cmd) { | ||
977 | case VIDIOCGCAP: | ||
978 | { | ||
979 | struct video_capability c; | ||
980 | DEBUG(printk(CARD_DEBUG "VIDIOCGCAP\n",CARD)); | ||
981 | |||
982 | strcpy(c.name,ztv->video_dev.name); | ||
983 | c.type = VID_TYPE_CAPTURE| | ||
984 | VID_TYPE_OVERLAY| | ||
985 | VID_TYPE_CLIPPING| | ||
986 | VID_TYPE_FRAMERAM| | ||
987 | VID_TYPE_SCALES; | ||
988 | if (ztv->have_tuner) | ||
989 | c.type |= VID_TYPE_TUNER; | ||
990 | if (pci_problems & (PCIPCI_FAIL|PCIAGP_FAIL)) | ||
991 | c.type &= ~VID_TYPE_OVERLAY; | ||
992 | if (ztv->have_decoder) { | ||
993 | c.channels = ztv->card->video_inputs; | ||
994 | c.audios = ztv->card->audio_inputs; | ||
995 | } else | ||
996 | /* no decoder -> no channels */ | ||
997 | c.channels = c.audios = 0; | ||
998 | c.maxwidth = 768; | ||
999 | c.maxheight = 576; | ||
1000 | c.minwidth = 32; | ||
1001 | c.minheight = 32; | ||
1002 | if (copy_to_user(arg,&c,sizeof(c))) | ||
1003 | return -EFAULT; | ||
1004 | break; | ||
1005 | } | ||
1006 | |||
1007 | case VIDIOCGCHAN: | ||
1008 | { | ||
1009 | struct video_channel v; | ||
1010 | int mux; | ||
1011 | if (copy_from_user(&v, arg,sizeof(v))) | ||
1012 | return -EFAULT; | ||
1013 | DEBUG(printk(CARD_DEBUG "VIDIOCGCHAN(%d)\n",CARD,v.channel)); | ||
1014 | v.flags=VIDEO_VC_AUDIO | ||
1015 | #ifdef VIDEO_VC_NORM | ||
1016 | |VIDEO_VC_NORM | ||
1017 | #endif | ||
1018 | ; | ||
1019 | v.tuners=0; | ||
1020 | v.type=VIDEO_TYPE_CAMERA; | ||
1021 | #ifdef I_EXPECT_POSSIBLE_NORMS_IN_THE_API | ||
1022 | v.norm=VIDEO_MODE_PAL| | ||
1023 | VIDEO_MODE_NTSC| | ||
1024 | VIDEO_MODE_SECAM; | ||
1025 | #else | ||
1026 | v.norm=VIDEO_MODE_PAL; | ||
1027 | #endif | ||
1028 | /* too many inputs? no decoder -> no channels */ | ||
1029 | if (!ztv->have_decoder || v.channel < 0 || v.channel >= ztv->card->video_inputs) | ||
1030 | return -EINVAL; | ||
1031 | |||
1032 | /* now determine the name of the channel */ | ||
1033 | mux = ztv->card->video_mux[v.channel]; | ||
1034 | if (mux & IS_TUNER) { | ||
1035 | /* lets assume only one tuner, yes? */ | ||
1036 | strcpy(v.name,"Television"); | ||
1037 | v.type = VIDEO_TYPE_TV; | ||
1038 | if (ztv->have_tuner) { | ||
1039 | v.flags |= VIDEO_VC_TUNER; | ||
1040 | v.tuners = 1; | ||
1041 | } | ||
1042 | } | ||
1043 | else if (mux & IS_SVHS) | ||
1044 | sprintf(v.name,"S-Video-%d",v.channel); | ||
1045 | else | ||
1046 | sprintf(v.name,"CVBS-%d",v.channel); | ||
1047 | |||
1048 | if (copy_to_user(arg,&v,sizeof(v))) | ||
1049 | return -EFAULT; | ||
1050 | break; | ||
1051 | } | ||
1052 | case VIDIOCSCHAN: | ||
1053 | { /* set video channel */ | ||
1054 | struct video_channel v; | ||
1055 | if (copy_from_user(&v, arg,sizeof(v))) | ||
1056 | return -EFAULT; | ||
1057 | DEBUG(printk(CARD_DEBUG "VIDIOCSCHAN(%d,%d)\n",CARD,v.channel,v.norm)); | ||
1058 | |||
1059 | /* too many inputs? no decoder -> no channels */ | ||
1060 | if (!ztv->have_decoder || v.channel >= ztv->card->video_inputs || v.channel < 0) | ||
1061 | return -EINVAL; | ||
1062 | |||
1063 | if (v.norm != VIDEO_MODE_PAL && | ||
1064 | v.norm != VIDEO_MODE_NTSC && | ||
1065 | v.norm != VIDEO_MODE_SECAM && | ||
1066 | v.norm != VIDEO_MODE_AUTO) | ||
1067 | return -EOPNOTSUPP; | ||
1068 | |||
1069 | /* make it happen, nr1! */ | ||
1070 | return zoran_muxsel(ztv,v.channel,v.norm); | ||
1071 | } | ||
1072 | |||
1073 | case VIDIOCGTUNER: | ||
1074 | { | ||
1075 | struct video_tuner v; | ||
1076 | if (copy_from_user(&v, arg,sizeof(v))) | ||
1077 | return -EFAULT; | ||
1078 | DEBUG(printk(CARD_DEBUG "VIDIOCGTUNER(%d)\n",CARD,v.tuner)); | ||
1079 | |||
1080 | /* Only no or one tuner for now */ | ||
1081 | if (!ztv->have_tuner || v.tuner) | ||
1082 | return -EINVAL; | ||
1083 | |||
1084 | strcpy(v.name,"Television"); | ||
1085 | v.rangelow = 0; | ||
1086 | v.rangehigh = ~0; | ||
1087 | v.flags = VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM; | ||
1088 | v.mode = ztv->norm; | ||
1089 | v.signal = 0xFFFF; /* unknown */ | ||
1090 | |||
1091 | if (copy_to_user(arg,&v,sizeof(v))) | ||
1092 | return -EFAULT; | ||
1093 | break; | ||
1094 | } | ||
1095 | case VIDIOCSTUNER: | ||
1096 | { | ||
1097 | struct video_tuner v; | ||
1098 | if (copy_from_user(&v, arg, sizeof(v))) | ||
1099 | return -EFAULT; | ||
1100 | DEBUG(printk(CARD_DEBUG "VIDIOCSTUNER(%d,%d)\n",CARD,v.tuner,v.mode)); | ||
1101 | |||
1102 | /* Only no or one tuner for now */ | ||
1103 | if (!ztv->have_tuner || v.tuner) | ||
1104 | return -EINVAL; | ||
1105 | |||
1106 | /* and it only has certain valid modes */ | ||
1107 | if( v.mode != VIDEO_MODE_PAL && | ||
1108 | v.mode != VIDEO_MODE_NTSC && | ||
1109 | v.mode != VIDEO_MODE_SECAM) | ||
1110 | return -EOPNOTSUPP; | ||
1111 | |||
1112 | /* engage! */ | ||
1113 | return zoran_muxsel(ztv,v.tuner,v.mode); | ||
1114 | } | ||
1115 | |||
1116 | case VIDIOCGPICT: | ||
1117 | { | ||
1118 | struct video_picture p = ztv->picture; | ||
1119 | DEBUG(printk(CARD_DEBUG "VIDIOCGPICT\n",CARD)); | ||
1120 | p.depth = ztv->depth; | ||
1121 | switch (p.depth) { | ||
1122 | case 8: p.palette=VIDEO_PALETTE_YUV422; | ||
1123 | break; | ||
1124 | case 15: p.palette=VIDEO_PALETTE_RGB555; | ||
1125 | break; | ||
1126 | case 16: p.palette=VIDEO_PALETTE_RGB565; | ||
1127 | break; | ||
1128 | case 24: p.palette=VIDEO_PALETTE_RGB24; | ||
1129 | break; | ||
1130 | case 32: p.palette=VIDEO_PALETTE_RGB32; | ||
1131 | break; | ||
1132 | } | ||
1133 | if (copy_to_user(arg, &p, sizeof(p))) | ||
1134 | return -EFAULT; | ||
1135 | break; | ||
1136 | } | ||
1137 | case VIDIOCSPICT: | ||
1138 | { | ||
1139 | struct video_picture p; | ||
1140 | if (copy_from_user(&p, arg,sizeof(p))) | ||
1141 | return -EFAULT; | ||
1142 | DEBUG(printk(CARD_DEBUG "VIDIOCSPICT(%d,%d,%d,%d,%d,%d,%d)\n",CARD,p.brightness,p.hue,p.colour,p.contrast,p.whiteness,p.depth,p.palette)); | ||
1143 | |||
1144 | /* depth must match with framebuffer */ | ||
1145 | if (p.depth != ztv->depth) | ||
1146 | return -EINVAL; | ||
1147 | |||
1148 | /* check if palette matches this bpp */ | ||
1149 | if (p.palette>NRPALETTES || | ||
1150 | palette2fmt[p.palette].bpp != ztv->overinfo.bpp) | ||
1151 | return -EINVAL; | ||
1152 | |||
1153 | write_lock_irq(&ztv->lock); | ||
1154 | ztv->overinfo.format = p.palette; | ||
1155 | ztv->picture = p; | ||
1156 | write_unlock_irq(&ztv->lock); | ||
1157 | |||
1158 | /* tell the decoder */ | ||
1159 | i2c_control_device(&ztv->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_PICTURE, &p); | ||
1160 | break; | ||
1161 | } | ||
1162 | |||
1163 | case VIDIOCGWIN: | ||
1164 | { | ||
1165 | struct video_window vw; | ||
1166 | DEBUG(printk(CARD_DEBUG "VIDIOCGWIN\n",CARD)); | ||
1167 | read_lock(&ztv->lock); | ||
1168 | vw.x = ztv->overinfo.x; | ||
1169 | vw.y = ztv->overinfo.y; | ||
1170 | vw.width = ztv->overinfo.w; | ||
1171 | vw.height = ztv->overinfo.h; | ||
1172 | vw.chromakey= 0; | ||
1173 | vw.flags = 0; | ||
1174 | if (ztv->vidInterlace) | ||
1175 | vw.flags|=VIDEO_WINDOW_INTERLACE; | ||
1176 | read_unlock(&ztv->lock); | ||
1177 | if (copy_to_user(arg,&vw,sizeof(vw))) | ||
1178 | return -EFAULT; | ||
1179 | break; | ||
1180 | } | ||
1181 | case VIDIOCSWIN: | ||
1182 | { | ||
1183 | struct video_window vw; | ||
1184 | struct video_clip *vcp; | ||
1185 | int on; | ||
1186 | if (copy_from_user(&vw,arg,sizeof(vw))) | ||
1187 | return -EFAULT; | ||
1188 | DEBUG(printk(CARD_DEBUG "VIDIOCSWIN(%d,%d,%d,%d,%x,%d)\n",CARD,vw.x,vw.y,vw.width,vw.height,vw.flags,vw.clipcount)); | ||
1189 | |||
1190 | if (vw.flags) | ||
1191 | return -EINVAL; | ||
1192 | |||
1193 | if (vw.clipcount <0 || vw.clipcount>256) | ||
1194 | return -EDOM; /* Too many! */ | ||
1195 | |||
1196 | /* | ||
1197 | * Do any clips. | ||
1198 | */ | ||
1199 | vcp = vmalloc(sizeof(struct video_clip)*(vw.clipcount+4)); | ||
1200 | if (vcp==NULL) | ||
1201 | return -ENOMEM; | ||
1202 | if (vw.clipcount && copy_from_user(vcp,vw.clips,sizeof(struct video_clip)*vw.clipcount)) { | ||
1203 | vfree(vcp); | ||
1204 | return -EFAULT; | ||
1205 | } | ||
1206 | |||
1207 | on = ztv->running; | ||
1208 | if (on) | ||
1209 | zoran_cap(ztv, 0); | ||
1210 | |||
1211 | /* | ||
1212 | * strange, it seems xawtv sometimes calls us with 0 | ||
1213 | * width and/or height. Ignore these values | ||
1214 | */ | ||
1215 | if (vw.x == 0) | ||
1216 | vw.x = ztv->overinfo.x; | ||
1217 | if (vw.y == 0) | ||
1218 | vw.y = ztv->overinfo.y; | ||
1219 | |||
1220 | /* by now we are committed to the new data... */ | ||
1221 | write_lock_irq(&ztv->lock); | ||
1222 | ztv->overinfo.x = vw.x; | ||
1223 | ztv->overinfo.y = vw.y; | ||
1224 | ztv->overinfo.w = vw.width; | ||
1225 | ztv->overinfo.h = vw.height; | ||
1226 | write_unlock_irq(&ztv->lock); | ||
1227 | |||
1228 | /* | ||
1229 | * Impose display clips | ||
1230 | */ | ||
1231 | if (vw.x+vw.width > ztv->swidth) | ||
1232 | new_clip(&vw, vcp, ztv->swidth-vw.x, 0, vw.width-1, vw.height-1); | ||
1233 | if (vw.y+vw.height > ztv->sheight) | ||
1234 | new_clip(&vw, vcp, 0, ztv->sheight-vw.y, vw.width-1, vw.height-1); | ||
1235 | |||
1236 | /* built the requested clipping zones */ | ||
1237 | zoran_set_geo(ztv, &ztv->overinfo); | ||
1238 | zoran_built_overlay(ztv, vw.clipcount, vcp); | ||
1239 | vfree(vcp); | ||
1240 | |||
1241 | /* if we were on, restart the video engine */ | ||
1242 | if (on) | ||
1243 | zoran_cap(ztv, 1); | ||
1244 | break; | ||
1245 | } | ||
1246 | |||
1247 | case VIDIOCCAPTURE: | ||
1248 | { | ||
1249 | int v; | ||
1250 | if (get_user(v, (int *)arg)) | ||
1251 | return -EFAULT; | ||
1252 | DEBUG(printk(CARD_DEBUG "VIDIOCCAPTURE(%d)\n",CARD,v)); | ||
1253 | |||
1254 | if (v==0) { | ||
1255 | clear_bit(STATE_OVERLAY, &ztv->state); | ||
1256 | zoran_cap(ztv, 1); | ||
1257 | } | ||
1258 | else { | ||
1259 | /* is VIDIOCSFBUF, VIDIOCSWIN done? */ | ||
1260 | if (ztv->overinfo.busadr==0 || ztv->overinfo.w==0 || ztv->overinfo.h==0) | ||
1261 | return -EINVAL; | ||
1262 | |||
1263 | set_bit(STATE_OVERLAY, &ztv->state); | ||
1264 | zoran_cap(ztv, 1); | ||
1265 | } | ||
1266 | break; | ||
1267 | } | ||
1268 | |||
1269 | case VIDIOCGFBUF: | ||
1270 | { | ||
1271 | struct video_buffer v; | ||
1272 | DEBUG(printk(CARD_DEBUG "VIDIOCGFBUF\n",CARD)); | ||
1273 | read_lock(&ztv->lock); | ||
1274 | v.base = (void *)ztv->overinfo.busadr; | ||
1275 | v.height = ztv->sheight; | ||
1276 | v.width = ztv->swidth; | ||
1277 | v.depth = ztv->depth; | ||
1278 | v.bytesperline = ztv->overinfo.bpl; | ||
1279 | read_unlock(&ztv->lock); | ||
1280 | if(copy_to_user(arg, &v,sizeof(v))) | ||
1281 | return -EFAULT; | ||
1282 | break; | ||
1283 | } | ||
1284 | case VIDIOCSFBUF: | ||
1285 | { | ||
1286 | struct video_buffer v; | ||
1287 | if(!capable(CAP_SYS_ADMIN)) | ||
1288 | return -EPERM; | ||
1289 | if (pcipci_problems & (PCIPCI_FAIL|PCIAGP_FAIL)) | ||
1290 | return -ENXIO; | ||
1291 | if (copy_from_user(&v, arg,sizeof(v))) | ||
1292 | return -EFAULT; | ||
1293 | DEBUG(printk(CARD_DEBUG "VIDIOCSFBUF(%p,%d,%d,%d,%d)\n",CARD,v.base, v.width,v.height,v.depth,v.bytesperline)); | ||
1294 | |||
1295 | if (v.depth!=15 && v.depth!=16 && v.depth!=24 && v.depth!=32) | ||
1296 | return -EINVAL; | ||
1297 | if (v.bytesperline<1) | ||
1298 | return -EINVAL; | ||
1299 | if (ztv->running) | ||
1300 | return -EBUSY; | ||
1301 | write_lock_irq(&ztv->lock); | ||
1302 | ztv->overinfo.busadr = (ulong)v.base; | ||
1303 | ztv->sheight = v.height; | ||
1304 | ztv->swidth = v.width; | ||
1305 | ztv->depth = v.depth; /* bits per pixel */ | ||
1306 | ztv->overinfo.bpp = ((v.depth+1)&0x38)/8;/* bytes per pixel */ | ||
1307 | ztv->overinfo.bpl = v.bytesperline; /* bytes per line */ | ||
1308 | write_unlock_irq(&ztv->lock); | ||
1309 | break; | ||
1310 | } | ||
1311 | |||
1312 | case VIDIOCKEY: | ||
1313 | { | ||
1314 | /* Will be handled higher up .. */ | ||
1315 | break; | ||
1316 | } | ||
1317 | |||
1318 | case VIDIOCSYNC: | ||
1319 | { | ||
1320 | int i; | ||
1321 | if (get_user(i, (int *) arg)) | ||
1322 | return -EFAULT; | ||
1323 | DEBUG(printk(CARD_DEBUG "VIDEOCSYNC(%d)\n",CARD,i)); | ||
1324 | if (i<0 || i>ZORAN_MAX_FBUFFERS) | ||
1325 | return -EINVAL; | ||
1326 | switch (ztv->grabinfo[i].status) { | ||
1327 | case FBUFFER_FREE: | ||
1328 | return -EINVAL; | ||
1329 | case FBUFFER_BUSY: | ||
1330 | /* wait till this buffer gets grabbed */ | ||
1331 | wait_event_interruptible(ztv->grabq, | ||
1332 | (ztv->grabinfo[i].status != FBUFFER_BUSY)); | ||
1333 | /* see if a signal did it */ | ||
1334 | if (signal_pending(current)) | ||
1335 | return -EINTR; | ||
1336 | /* don't fall through; a DONE buffer is not UNUSED */ | ||
1337 | break; | ||
1338 | case FBUFFER_DONE: | ||
1339 | ztv->grabinfo[i].status = FBUFFER_FREE; | ||
1340 | /* tell ppl we have a spare buffer */ | ||
1341 | wake_up_interruptible(&ztv->grabq); | ||
1342 | break; | ||
1343 | } | ||
1344 | DEBUG(printk(CARD_DEBUG "VIDEOCSYNC(%d) returns\n",CARD,i)); | ||
1345 | break; | ||
1346 | } | ||
1347 | |||
1348 | case VIDIOCMCAPTURE: | ||
1349 | { | ||
1350 | struct video_mmap vm; | ||
1351 | struct vidinfo* frame; | ||
1352 | if (copy_from_user(&vm,arg,sizeof(vm))) | ||
1353 | return -EFAULT; | ||
1354 | DEBUG(printk(CARD_DEBUG "VIDIOCMCAPTURE(%d,(%d,%d),%d)\n",CARD,vm.frame,vm.width,vm.height,vm.format)); | ||
1355 | if (vm.frame<0 || vm.frame>ZORAN_MAX_FBUFFERS || | ||
1356 | vm.width<32 || vm.width>768 || | ||
1357 | vm.height<32 || vm.height>576 || | ||
1358 | vm.format>NRPALETTES || | ||
1359 | palette2fmt[vm.format].mode == 0) | ||
1360 | return -EINVAL; | ||
1361 | |||
1362 | /* we are allowed to take over UNUSED and DONE buffers */ | ||
1363 | frame = &ztv->grabinfo[vm.frame]; | ||
1364 | if (frame->status == FBUFFER_BUSY) | ||
1365 | return -EBUSY; | ||
1366 | |||
1367 | /* setup the other parameters if they are given */ | ||
1368 | write_lock_irq(&ztv->lock); | ||
1369 | frame->w = vm.width; | ||
1370 | frame->h = vm.height; | ||
1371 | frame->format = vm.format; | ||
1372 | frame->bpp = palette2fmt[frame->format].bpp; | ||
1373 | frame->bpl = frame->w*frame->bpp; | ||
1374 | frame->status = FBUFFER_BUSY; | ||
1375 | frame->next = 0; | ||
1376 | { /* add to tail of queue */ | ||
1377 | struct vidinfo* oldframe = ztv->workqueue; | ||
1378 | if (!oldframe) ztv->workqueue = frame; | ||
1379 | else { | ||
1380 | while (oldframe->next) oldframe = oldframe->next; | ||
1381 | oldframe->next = frame; | ||
1382 | } | ||
1383 | } | ||
1384 | write_unlock_irq(&ztv->lock); | ||
1385 | zoran_cap(ztv, 1); | ||
1386 | break; | ||
1387 | } | ||
1388 | |||
1389 | case VIDIOCGMBUF: | ||
1390 | { | ||
1391 | struct video_mbuf mb; | ||
1392 | int i; | ||
1393 | DEBUG(printk(CARD_DEBUG "VIDIOCGMBUF\n",CARD)); | ||
1394 | mb.size = ZORAN_MAX_FBUFSIZE; | ||
1395 | mb.frames = ZORAN_MAX_FBUFFERS; | ||
1396 | for (i=0; i<ZORAN_MAX_FBUFFERS; i++) | ||
1397 | mb.offsets[i] = i*ZORAN_MAX_FBUFFER; | ||
1398 | if(copy_to_user(arg, &mb,sizeof(mb))) | ||
1399 | return -EFAULT; | ||
1400 | break; | ||
1401 | } | ||
1402 | |||
1403 | case VIDIOCGUNIT: | ||
1404 | { | ||
1405 | struct video_unit vu; | ||
1406 | DEBUG(printk(CARD_DEBUG "VIDIOCGUNIT\n",CARD)); | ||
1407 | vu.video = ztv->video_dev.minor; | ||
1408 | vu.vbi = ztv->vbi_dev.minor; | ||
1409 | vu.radio = VIDEO_NO_UNIT; | ||
1410 | vu.audio = VIDEO_NO_UNIT; | ||
1411 | vu.teletext = VIDEO_NO_UNIT; | ||
1412 | if(copy_to_user(arg, &vu,sizeof(vu))) | ||
1413 | return -EFAULT; | ||
1414 | break; | ||
1415 | } | ||
1416 | |||
1417 | case VIDIOCGFREQ: | ||
1418 | { | ||
1419 | unsigned long v = ztv->tuner_freq; | ||
1420 | if (copy_to_user(arg,&v,sizeof(v))) | ||
1421 | return -EFAULT; | ||
1422 | DEBUG(printk(CARD_DEBUG "VIDIOCGFREQ\n",CARD)); | ||
1423 | break; | ||
1424 | } | ||
1425 | case VIDIOCSFREQ: | ||
1426 | { | ||
1427 | unsigned long v; | ||
1428 | if (copy_from_user(&v, arg, sizeof(v))) | ||
1429 | return -EFAULT; | ||
1430 | DEBUG(printk(CARD_DEBUG "VIDIOCSFREQ\n",CARD)); | ||
1431 | |||
1432 | if (ztv->have_tuner) { | ||
1433 | int fixme = v; | ||
1434 | if (i2c_control_device(&(ztv->i2c), I2C_DRIVERID_TUNER, TUNER_SET_TVFREQ, &fixme) < 0) | ||
1435 | return -EAGAIN; | ||
1436 | } | ||
1437 | ztv->tuner_freq = v; | ||
1438 | break; | ||
1439 | } | ||
1440 | |||
1441 | /* Why isn't this in the API? | ||
1442 | * And why doesn't it take a buffer number? | ||
1443 | case BTTV_FIELDNR: | ||
1444 | { | ||
1445 | unsigned long v = ztv->lastfieldnr; | ||
1446 | if (copy_to_user(arg,&v,sizeof(v))) | ||
1447 | return -EFAULT; | ||
1448 | DEBUG(printk(CARD_DEBUG "BTTV_FIELDNR\n",CARD)); | ||
1449 | break; | ||
1450 | } | ||
1451 | */ | ||
1452 | |||
1453 | default: | ||
1454 | return -ENOIOCTLCMD; | ||
1455 | } | ||
1456 | return 0; | ||
1457 | } | ||
1458 | |||
1459 | static | ||
1460 | int zoran_mmap(struct vm_area_struct *vma, struct video_device* dev, const char* adr, unsigned long size) | ||
1461 | { | ||
1462 | struct zoran* ztv = (struct zoran*)dev; | ||
1463 | unsigned long start = (unsigned long)adr; | ||
1464 | unsigned long pos; | ||
1465 | |||
1466 | DEBUG(printk(CARD_DEBUG "zoran_mmap(0x%p,%ld)\n",CARD,adr,size)); | ||
1467 | |||
1468 | /* sanity checks */ | ||
1469 | if (size > ZORAN_MAX_FBUFSIZE || !ztv->fbuffer) | ||
1470 | return -EINVAL; | ||
1471 | |||
1472 | /* start mapping the whole shabang to user memory */ | ||
1473 | pos = (unsigned long)ztv->fbuffer; | ||
1474 | while (size>0) { | ||
1475 | unsigned long pfn = virt_to_phys((void*)pos) >> PAGE_SHIFT; | ||
1476 | if (remap_pfn_range(vma, start, pfn, PAGE_SIZE, PAGE_SHARED)) | ||
1477 | return -EAGAIN; | ||
1478 | start += PAGE_SIZE; | ||
1479 | pos += PAGE_SIZE; | ||
1480 | size -= PAGE_SIZE; | ||
1481 | } | ||
1482 | return 0; | ||
1483 | } | ||
1484 | |||
1485 | static struct video_device zr36120_template= | ||
1486 | { | ||
1487 | .owner = THIS_MODULE, | ||
1488 | .name = "UNSET", | ||
1489 | .type = VID_TYPE_TUNER|VID_TYPE_CAPTURE|VID_TYPE_OVERLAY, | ||
1490 | .hardware = VID_HARDWARE_ZR36120, | ||
1491 | .open = zoran_open, | ||
1492 | .close = zoran_close, | ||
1493 | .read = zoran_read, | ||
1494 | .write = zoran_write, | ||
1495 | .poll = zoran_poll, | ||
1496 | .ioctl = zoran_ioctl, | ||
1497 | .compat_ioctl = v4l_compat_ioctl32, | ||
1498 | .mmap = zoran_mmap, | ||
1499 | .minor = -1, | ||
1500 | }; | ||
1501 | |||
1502 | static | ||
1503 | int vbi_open(struct video_device *dev, int flags) | ||
1504 | { | ||
1505 | struct zoran *ztv = dev->priv; | ||
1506 | struct vidinfo* item; | ||
1507 | |||
1508 | DEBUG(printk(CARD_DEBUG "vbi_open(dev,%d)\n",CARD,flags)); | ||
1509 | |||
1510 | /* | ||
1511 | * During VBI device open, we continiously grab VBI-like | ||
1512 | * data in the vbi buffer when we have nothing to do. | ||
1513 | * Only when there is an explicit request for VBI data | ||
1514 | * (read call) we /force/ a read. | ||
1515 | */ | ||
1516 | |||
1517 | /* allocate buffers */ | ||
1518 | for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++) | ||
1519 | { | ||
1520 | item->status = FBUFFER_FREE; | ||
1521 | |||
1522 | /* alloc */ | ||
1523 | if (!item->memadr) { | ||
1524 | item->memadr = bmalloc(ZORAN_VBI_BUFSIZE); | ||
1525 | if (!item->memadr) { | ||
1526 | /* could not get a buffer, bail out */ | ||
1527 | while (item != ztv->readinfo) { | ||
1528 | item--; | ||
1529 | bfree(item->memadr, ZORAN_VBI_BUFSIZE); | ||
1530 | item->memadr = 0; | ||
1531 | item->busadr = 0; | ||
1532 | } | ||
1533 | return -ENOBUFS; | ||
1534 | } | ||
1535 | } | ||
1536 | |||
1537 | /* determine the DMAable address */ | ||
1538 | item->busadr = virt_to_bus(item->memadr); | ||
1539 | } | ||
1540 | |||
1541 | /* do the common part of all open's */ | ||
1542 | zoran_common_open(ztv, flags); | ||
1543 | |||
1544 | set_bit(STATE_VBI, &ztv->state); | ||
1545 | /* start read-ahead */ | ||
1546 | zoran_cap(ztv, 1); | ||
1547 | |||
1548 | return 0; | ||
1549 | } | ||
1550 | |||
1551 | static | ||
1552 | void vbi_close(struct video_device *dev) | ||
1553 | { | ||
1554 | struct zoran *ztv = dev->priv; | ||
1555 | struct vidinfo* item; | ||
1556 | |||
1557 | DEBUG(printk(CARD_DEBUG "vbi_close(dev)\n",CARD)); | ||
1558 | |||
1559 | /* driver specific closure */ | ||
1560 | clear_bit(STATE_VBI, &ztv->state); | ||
1561 | |||
1562 | zoran_common_close(ztv); | ||
1563 | |||
1564 | /* | ||
1565 | * This is sucky but right now I can't find a good way to | ||
1566 | * be sure its safe to free the buffer. We wait 5-6 fields | ||
1567 | * which is more than sufficient to be sure. | ||
1568 | */ | ||
1569 | msleep(100); /* Wait 1/10th of a second */ | ||
1570 | |||
1571 | for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++) | ||
1572 | { | ||
1573 | if (item->memadr) | ||
1574 | bfree(item->memadr, ZORAN_VBI_BUFSIZE); | ||
1575 | item->memadr = 0; | ||
1576 | } | ||
1577 | |||
1578 | } | ||
1579 | |||
1580 | /* | ||
1581 | * This read function could be used reentrant in a SMP situation. | ||
1582 | * | ||
1583 | * This is made possible by the spinlock which is kept till we | ||
1584 | * found and marked a buffer for our own use. The lock must | ||
1585 | * be released as soon as possible to prevent lock contention. | ||
1586 | */ | ||
1587 | static | ||
1588 | long vbi_read(struct video_device* dev, char* buf, unsigned long count, int nonblock) | ||
1589 | { | ||
1590 | struct zoran *ztv = dev->priv; | ||
1591 | unsigned long max; | ||
1592 | struct vidinfo* unused = 0; | ||
1593 | struct vidinfo* done = 0; | ||
1594 | |||
1595 | DEBUG(printk(CARD_DEBUG "vbi_read(0x%p,%ld,%d)\n",CARD,buf,count,nonblock)); | ||
1596 | |||
1597 | /* find ourself a free or completed buffer */ | ||
1598 | for (;;) { | ||
1599 | struct vidinfo* item; | ||
1600 | |||
1601 | write_lock_irq(&ztv->lock); | ||
1602 | for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++) { | ||
1603 | if (!unused && item->status == FBUFFER_FREE) | ||
1604 | unused = item; | ||
1605 | if (!done && item->status == FBUFFER_DONE) | ||
1606 | done = item; | ||
1607 | } | ||
1608 | if (done || unused) | ||
1609 | break; | ||
1610 | |||
1611 | /* no more free buffers, wait for them. */ | ||
1612 | write_unlock_irq(&ztv->lock); | ||
1613 | if (nonblock) | ||
1614 | return -EWOULDBLOCK; | ||
1615 | interruptible_sleep_on(&ztv->vbiq); | ||
1616 | if (signal_pending(current)) | ||
1617 | return -EINTR; | ||
1618 | } | ||
1619 | |||
1620 | /* Do we have 'ready' data? */ | ||
1621 | if (!done) { | ||
1622 | /* no? than this will take a while... */ | ||
1623 | if (nonblock) { | ||
1624 | write_unlock_irq(&ztv->lock); | ||
1625 | return -EWOULDBLOCK; | ||
1626 | } | ||
1627 | |||
1628 | /* mark the unused buffer as wanted */ | ||
1629 | unused->status = FBUFFER_BUSY; | ||
1630 | unused->next = 0; | ||
1631 | { /* add to tail of queue */ | ||
1632 | struct vidinfo* oldframe = ztv->workqueue; | ||
1633 | if (!oldframe) ztv->workqueue = unused; | ||
1634 | else { | ||
1635 | while (oldframe->next) oldframe = oldframe->next; | ||
1636 | oldframe->next = unused; | ||
1637 | } | ||
1638 | } | ||
1639 | write_unlock_irq(&ztv->lock); | ||
1640 | |||
1641 | /* tell the state machine we want it filled /NOW/ */ | ||
1642 | zoran_cap(ztv, 1); | ||
1643 | |||
1644 | /* wait till this buffer gets grabbed */ | ||
1645 | wait_event_interruptible(ztv->vbiq, | ||
1646 | (unused->status != FBUFFER_BUSY)); | ||
1647 | /* see if a signal did it */ | ||
1648 | if (signal_pending(current)) | ||
1649 | return -EINTR; | ||
1650 | done = unused; | ||
1651 | } | ||
1652 | else | ||
1653 | write_unlock_irq(&ztv->lock); | ||
1654 | |||
1655 | /* Yes! we got data! */ | ||
1656 | max = done->bpl * -done->h; | ||
1657 | if (count > max) | ||
1658 | count = max; | ||
1659 | |||
1660 | /* check if the user gave us enough room to write the data */ | ||
1661 | if (!access_ok(VERIFY_WRITE, buf, count)) { | ||
1662 | count = -EFAULT; | ||
1663 | goto out; | ||
1664 | } | ||
1665 | |||
1666 | /* | ||
1667 | * Now transform/strip the data from YUV to Y-only | ||
1668 | * NB. Assume the Y is in the LSB of the YUV data. | ||
1669 | */ | ||
1670 | { | ||
1671 | unsigned char* optr = buf; | ||
1672 | unsigned char* eptr = buf+count; | ||
1673 | |||
1674 | /* are we beeing accessed from an old driver? */ | ||
1675 | if (count == 2*19*2048) { | ||
1676 | /* | ||
1677 | * Extreme HACK, old VBI programs expect 2048 points | ||
1678 | * of data, and we only got 864 orso. Double each | ||
1679 | * datapoint and clear the rest of the line. | ||
1680 | * This way we have appear to have a | ||
1681 | * sample_frequency of 29.5 Mc. | ||
1682 | */ | ||
1683 | int x,y; | ||
1684 | unsigned char* iptr = done->memadr+1; | ||
1685 | for (y=done->h; optr<eptr && y<0; y++) | ||
1686 | { | ||
1687 | /* copy to doubled data to userland */ | ||
1688 | for (x=0; optr+1<eptr && x<-done->w; x++) | ||
1689 | { | ||
1690 | unsigned char a = iptr[x*2]; | ||
1691 | __put_user(a, optr++); | ||
1692 | __put_user(a, optr++); | ||
1693 | } | ||
1694 | /* and clear the rest of the line */ | ||
1695 | for (x*=2; optr<eptr && x<done->bpl; x++) | ||
1696 | __put_user(0, optr++); | ||
1697 | /* next line */ | ||
1698 | iptr += done->bpl; | ||
1699 | } | ||
1700 | } | ||
1701 | else { | ||
1702 | /* | ||
1703 | * Other (probably newer) programs asked | ||
1704 | * us what geometry we are using, and are | ||
1705 | * reading the correct size. | ||
1706 | */ | ||
1707 | int x,y; | ||
1708 | unsigned char* iptr = done->memadr+1; | ||
1709 | for (y=done->h; optr<eptr && y<0; y++) | ||
1710 | { | ||
1711 | /* copy to doubled data to userland */ | ||
1712 | for (x=0; optr<eptr && x<-done->w; x++) | ||
1713 | __put_user(iptr[x*2], optr++); | ||
1714 | /* and clear the rest of the line */ | ||
1715 | for (;optr<eptr && x<done->bpl; x++) | ||
1716 | __put_user(0, optr++); | ||
1717 | /* next line */ | ||
1718 | iptr += done->bpl; | ||
1719 | } | ||
1720 | } | ||
1721 | |||
1722 | /* API compliance: | ||
1723 | * place the framenumber (half fieldnr) in the last long | ||
1724 | */ | ||
1725 | __put_user(done->fieldnr/2, ((ulong*)eptr)[-1]); | ||
1726 | } | ||
1727 | |||
1728 | /* keep the engine running */ | ||
1729 | done->status = FBUFFER_FREE; | ||
1730 | zoran_cap(ztv, 1); | ||
1731 | |||
1732 | /* tell listeners this buffer just became free */ | ||
1733 | wake_up_interruptible(&ztv->vbiq); | ||
1734 | |||
1735 | /* goodbye */ | ||
1736 | out: | ||
1737 | DEBUG(printk(CARD_DEBUG "vbi_read() returns %lu\n",CARD,count)); | ||
1738 | return count; | ||
1739 | } | ||
1740 | |||
1741 | static | ||
1742 | unsigned int vbi_poll(struct video_device *dev, struct file *file, poll_table *wait) | ||
1743 | { | ||
1744 | struct zoran *ztv = dev->priv; | ||
1745 | struct vidinfo* item; | ||
1746 | unsigned int mask = 0; | ||
1747 | |||
1748 | poll_wait(file, &ztv->vbiq, wait); | ||
1749 | |||
1750 | for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++) | ||
1751 | if (item->status == FBUFFER_DONE) | ||
1752 | { | ||
1753 | mask |= (POLLIN | POLLRDNORM); | ||
1754 | break; | ||
1755 | } | ||
1756 | |||
1757 | DEBUG(printk(CARD_DEBUG "vbi_poll()=%x\n",CARD,mask)); | ||
1758 | |||
1759 | return mask; | ||
1760 | } | ||
1761 | |||
1762 | static | ||
1763 | int vbi_ioctl(struct video_device *dev, unsigned int cmd, void *arg) | ||
1764 | { | ||
1765 | struct zoran* ztv = dev->priv; | ||
1766 | |||
1767 | switch (cmd) { | ||
1768 | case VIDIOCGVBIFMT: | ||
1769 | { | ||
1770 | struct vbi_format f; | ||
1771 | DEBUG(printk(CARD_DEBUG "VIDIOCGVBIINFO\n",CARD)); | ||
1772 | f.sampling_rate = 14750000UL; | ||
1773 | f.samples_per_line = -ztv->readinfo[0].w; | ||
1774 | f.sample_format = VIDEO_PALETTE_RAW; | ||
1775 | f.start[0] = f.start[1] = ztv->readinfo[0].y; | ||
1776 | f.start[1] += 312; | ||
1777 | f.count[0] = f.count[1] = -ztv->readinfo[0].h; | ||
1778 | f.flags = VBI_INTERLACED; | ||
1779 | if (copy_to_user(arg,&f,sizeof(f))) | ||
1780 | return -EFAULT; | ||
1781 | break; | ||
1782 | } | ||
1783 | case VIDIOCSVBIFMT: | ||
1784 | { | ||
1785 | struct vbi_format f; | ||
1786 | int i; | ||
1787 | if (copy_from_user(&f, arg,sizeof(f))) | ||
1788 | return -EFAULT; | ||
1789 | DEBUG(printk(CARD_DEBUG "VIDIOCSVBIINFO(%d,%d,%d,%d,%d,%d,%d,%x)\n",CARD,f.sampling_rate,f.samples_per_line,f.sample_format,f.start[0],f.start[1],f.count[0],f.count[1],f.flags)); | ||
1790 | |||
1791 | /* lots of parameters are fixed... (PAL) */ | ||
1792 | if (f.sampling_rate != 14750000UL || | ||
1793 | f.samples_per_line > 864 || | ||
1794 | f.sample_format != VIDEO_PALETTE_RAW || | ||
1795 | f.start[0] < 0 || | ||
1796 | f.start[0] != f.start[1]-312 || | ||
1797 | f.count[0] != f.count[1] || | ||
1798 | f.start[0]+f.count[0] >= 288 || | ||
1799 | f.flags != VBI_INTERLACED) | ||
1800 | return -EINVAL; | ||
1801 | |||
1802 | write_lock_irq(&ztv->lock); | ||
1803 | ztv->readinfo[0].y = f.start[0]; | ||
1804 | ztv->readinfo[0].w = -f.samples_per_line; | ||
1805 | ztv->readinfo[0].h = -f.count[0]; | ||
1806 | ztv->readinfo[0].bpl = f.samples_per_line*ztv->readinfo[0].bpp; | ||
1807 | for (i=1; i<ZORAN_VBI_BUFFERS; i++) | ||
1808 | ztv->readinfo[i] = ztv->readinfo[i]; | ||
1809 | write_unlock_irq(&ztv->lock); | ||
1810 | break; | ||
1811 | } | ||
1812 | default: | ||
1813 | return -ENOIOCTLCMD; | ||
1814 | } | ||
1815 | return 0; | ||
1816 | } | ||
1817 | |||
1818 | static struct video_device vbi_template= | ||
1819 | { | ||
1820 | .owner = THIS_MODULE, | ||
1821 | .name = "UNSET", | ||
1822 | .type = VID_TYPE_CAPTURE|VID_TYPE_TELETEXT, | ||
1823 | .hardware = VID_HARDWARE_ZR36120, | ||
1824 | .open = vbi_open, | ||
1825 | .close = vbi_close, | ||
1826 | .read = vbi_read, | ||
1827 | .write = zoran_write, | ||
1828 | .poll = vbi_poll, | ||
1829 | .ioctl = vbi_ioctl, | ||
1830 | .minor = -1, | ||
1831 | }; | ||
1832 | |||
1833 | /* | ||
1834 | * Scan for a Zoran chip, request the irq and map the io memory | ||
1835 | */ | ||
1836 | static | ||
1837 | int __init find_zoran(void) | ||
1838 | { | ||
1839 | int result; | ||
1840 | struct zoran *ztv; | ||
1841 | struct pci_dev *dev = NULL; | ||
1842 | unsigned char revision; | ||
1843 | int zoran_num = 0; | ||
1844 | |||
1845 | while ((dev = pci_get_device(PCI_VENDOR_ID_ZORAN,PCI_DEVICE_ID_ZORAN_36120, dev))) | ||
1846 | { | ||
1847 | /* Ok, a ZR36120/ZR36125 found! */ | ||
1848 | ztv = &zorans[zoran_num]; | ||
1849 | ztv->dev = dev; | ||
1850 | |||
1851 | if (pci_enable_device(dev)) | ||
1852 | continue; | ||
1853 | |||
1854 | pci_read_config_byte(dev, PCI_CLASS_REVISION, &revision); | ||
1855 | printk(KERN_INFO "zoran: Zoran %x (rev %d) ", | ||
1856 | dev->device, revision); | ||
1857 | printk("bus: %d, devfn: %d, irq: %d, ", | ||
1858 | dev->bus->number, dev->devfn, dev->irq); | ||
1859 | printk("memory: 0x%08lx.\n", ztv->zoran_adr); | ||
1860 | |||
1861 | ztv->zoran_mem = ioremap(ztv->zoran_adr, 0x1000); | ||
1862 | DEBUG(printk(KERN_DEBUG "zoran: mapped-memory at 0x%p\n",ztv->zoran_mem)); | ||
1863 | |||
1864 | result = request_irq(dev->irq, zoran_irq, | ||
1865 | IRQF_SHARED|IRQF_DISABLED,"zoran", ztv); | ||
1866 | if (result==-EINVAL) | ||
1867 | { | ||
1868 | iounmap(ztv->zoran_mem); | ||
1869 | printk(KERN_ERR "zoran: Bad irq number or handler\n"); | ||
1870 | continue; | ||
1871 | } | ||
1872 | if (result==-EBUSY) | ||
1873 | printk(KERN_ERR "zoran: IRQ %d busy, change your PnP config in BIOS\n",dev->irq); | ||
1874 | if (result < 0) { | ||
1875 | iounmap(ztv->zoran_mem); | ||
1876 | continue; | ||
1877 | } | ||
1878 | /* Enable bus-mastering */ | ||
1879 | pci_set_master(dev); | ||
1880 | /* Keep a reference */ | ||
1881 | pci_dev_get(dev); | ||
1882 | zoran_num++; | ||
1883 | } | ||
1884 | if(zoran_num) | ||
1885 | printk(KERN_INFO "zoran: %d Zoran card(s) found.\n",zoran_num); | ||
1886 | return zoran_num; | ||
1887 | } | ||
1888 | |||
1889 | static | ||
1890 | int __init init_zoran(int card) | ||
1891 | { | ||
1892 | struct zoran *ztv = &zorans[card]; | ||
1893 | int i; | ||
1894 | |||
1895 | /* if the given cardtype valid? */ | ||
1896 | if (cardtype[card]>=NRTVCARDS) { | ||
1897 | printk(KERN_INFO "invalid cardtype(%d) detected\n",cardtype[card]); | ||
1898 | return -1; | ||
1899 | } | ||
1900 | |||
1901 | /* reset the zoran */ | ||
1902 | zrand(~ZORAN_PCI_SOFTRESET,ZORAN_PCI); | ||
1903 | udelay(10); | ||
1904 | zror(ZORAN_PCI_SOFTRESET,ZORAN_PCI); | ||
1905 | udelay(10); | ||
1906 | |||
1907 | /* zoran chip specific details */ | ||
1908 | ztv->card = tvcards+cardtype[card]; /* point to the selected card */ | ||
1909 | ztv->norm = 0; /* PAL */ | ||
1910 | ztv->tuner_freq = 0; | ||
1911 | |||
1912 | /* videocard details */ | ||
1913 | ztv->swidth = 800; | ||
1914 | ztv->sheight = 600; | ||
1915 | ztv->depth = 16; | ||
1916 | |||
1917 | /* State details */ | ||
1918 | ztv->fbuffer = 0; | ||
1919 | ztv->overinfo.kindof = FBUFFER_OVERLAY; | ||
1920 | ztv->overinfo.status = FBUFFER_FREE; | ||
1921 | ztv->overinfo.x = 0; | ||
1922 | ztv->overinfo.y = 0; | ||
1923 | ztv->overinfo.w = 768; /* 640 */ | ||
1924 | ztv->overinfo.h = 576; /* 480 */ | ||
1925 | ztv->overinfo.format = VIDEO_PALETTE_RGB565; | ||
1926 | ztv->overinfo.bpp = palette2fmt[ztv->overinfo.format].bpp; | ||
1927 | ztv->overinfo.bpl = ztv->overinfo.bpp*ztv->swidth; | ||
1928 | ztv->overinfo.busadr = 0; | ||
1929 | ztv->overinfo.memadr = 0; | ||
1930 | ztv->overinfo.overlay = 0; | ||
1931 | for (i=0; i<ZORAN_MAX_FBUFFERS; i++) { | ||
1932 | ztv->grabinfo[i] = ztv->overinfo; | ||
1933 | ztv->grabinfo[i].kindof = FBUFFER_GRAB; | ||
1934 | } | ||
1935 | init_waitqueue_head(&ztv->grabq); | ||
1936 | |||
1937 | /* VBI details */ | ||
1938 | ztv->readinfo[0] = ztv->overinfo; | ||
1939 | ztv->readinfo[0].kindof = FBUFFER_VBI; | ||
1940 | ztv->readinfo[0].w = -864; | ||
1941 | ztv->readinfo[0].h = -38; | ||
1942 | ztv->readinfo[0].format = VIDEO_PALETTE_YUV422; | ||
1943 | ztv->readinfo[0].bpp = palette2fmt[ztv->readinfo[0].format].bpp; | ||
1944 | ztv->readinfo[0].bpl = 1024*ztv->readinfo[0].bpp; | ||
1945 | for (i=1; i<ZORAN_VBI_BUFFERS; i++) | ||
1946 | ztv->readinfo[i] = ztv->readinfo[0]; | ||
1947 | init_waitqueue_head(&ztv->vbiq); | ||
1948 | |||
1949 | /* maintenance data */ | ||
1950 | ztv->have_decoder = 0; | ||
1951 | ztv->have_tuner = 0; | ||
1952 | ztv->tuner_type = 0; | ||
1953 | ztv->running = 0; | ||
1954 | ztv->users = 0; | ||
1955 | rwlock_init(&ztv->lock); | ||
1956 | ztv->workqueue = 0; | ||
1957 | ztv->fieldnr = 0; | ||
1958 | ztv->lastfieldnr = 0; | ||
1959 | |||
1960 | if (triton1) | ||
1961 | zrand(~ZORAN_VDC_TRICOM, ZORAN_VDC); | ||
1962 | |||
1963 | /* external FL determines TOP frame */ | ||
1964 | zror(ZORAN_VFEC_EXTFL, ZORAN_VFEC); | ||
1965 | |||
1966 | /* set HSpol */ | ||
1967 | if (ztv->card->hsync_pos) | ||
1968 | zrwrite(ZORAN_VFEH_HSPOL, ZORAN_VFEH); | ||
1969 | /* set VSpol */ | ||
1970 | if (ztv->card->vsync_pos) | ||
1971 | zrwrite(ZORAN_VFEV_VSPOL, ZORAN_VFEV); | ||
1972 | |||
1973 | /* Set the proper General Purpuse register bits */ | ||
1974 | /* implicit: no softreset, 0 waitstates */ | ||
1975 | zrwrite(ZORAN_PCI_SOFTRESET|(ztv->card->gpdir<<0),ZORAN_PCI); | ||
1976 | /* implicit: 3 duration and recovery PCI clocks on guest 0-3 */ | ||
1977 | zrwrite(ztv->card->gpval<<24,ZORAN_GUEST); | ||
1978 | |||
1979 | /* clear interrupt status */ | ||
1980 | zrwrite(~0, ZORAN_ISR); | ||
1981 | |||
1982 | /* | ||
1983 | * i2c template | ||
1984 | */ | ||
1985 | ztv->i2c = zoran_i2c_bus_template; | ||
1986 | sprintf(ztv->i2c.name,"zoran-%d",card); | ||
1987 | ztv->i2c.data = ztv; | ||
1988 | |||
1989 | /* | ||
1990 | * Now add the template and register the device unit | ||
1991 | */ | ||
1992 | ztv->video_dev = zr36120_template; | ||
1993 | strcpy(ztv->video_dev.name, ztv->i2c.name); | ||
1994 | ztv->video_dev.priv = ztv; | ||
1995 | if (video_register_device(&ztv->video_dev, VFL_TYPE_GRABBER, video_nr) < 0) | ||
1996 | return -1; | ||
1997 | |||
1998 | ztv->vbi_dev = vbi_template; | ||
1999 | strcpy(ztv->vbi_dev.name, ztv->i2c.name); | ||
2000 | ztv->vbi_dev.priv = ztv; | ||
2001 | if (video_register_device(&ztv->vbi_dev, VFL_TYPE_VBI, vbi_nr) < 0) { | ||
2002 | video_unregister_device(&ztv->video_dev); | ||
2003 | return -1; | ||
2004 | } | ||
2005 | i2c_register_bus(&ztv->i2c); | ||
2006 | |||
2007 | /* set interrupt mask - the PIN enable will be set later */ | ||
2008 | zrwrite(ZORAN_ICR_GIRQ0|ZORAN_ICR_GIRQ1|ZORAN_ICR_CODE, ZORAN_ICR); | ||
2009 | |||
2010 | printk(KERN_INFO "%s: installed %s\n",ztv->i2c.name,ztv->card->name); | ||
2011 | return 0; | ||
2012 | } | ||
2013 | |||
2014 | static | ||
2015 | void release_zoran(int max) | ||
2016 | { | ||
2017 | struct zoran *ztv; | ||
2018 | int i; | ||
2019 | |||
2020 | for (i=0;i<max; i++) | ||
2021 | { | ||
2022 | ztv = &zorans[i]; | ||
2023 | |||
2024 | /* turn off all capturing, DMA and IRQs */ | ||
2025 | /* reset the zoran */ | ||
2026 | zrand(~ZORAN_PCI_SOFTRESET,ZORAN_PCI); | ||
2027 | udelay(10); | ||
2028 | zror(ZORAN_PCI_SOFTRESET,ZORAN_PCI); | ||
2029 | udelay(10); | ||
2030 | |||
2031 | /* first disable interrupts before unmapping the memory! */ | ||
2032 | zrwrite(0, ZORAN_ICR); | ||
2033 | zrwrite(0xffffffffUL,ZORAN_ISR); | ||
2034 | |||
2035 | /* free it */ | ||
2036 | free_irq(ztv->dev->irq,ztv); | ||
2037 | |||
2038 | /* unregister i2c_bus */ | ||
2039 | i2c_unregister_bus((&ztv->i2c)); | ||
2040 | |||
2041 | /* unmap and free memory */ | ||
2042 | if (ztv->zoran_mem) | ||
2043 | iounmap(ztv->zoran_mem); | ||
2044 | |||
2045 | /* Drop PCI device */ | ||
2046 | pci_dev_put(ztv->dev); | ||
2047 | |||
2048 | video_unregister_device(&ztv->video_dev); | ||
2049 | video_unregister_device(&ztv->vbi_dev); | ||
2050 | } | ||
2051 | } | ||
2052 | |||
2053 | void __exit zr36120_exit(void) | ||
2054 | { | ||
2055 | release_zoran(zoran_cards); | ||
2056 | } | ||
2057 | |||
2058 | int __init zr36120_init(void) | ||
2059 | { | ||
2060 | int card; | ||
2061 | |||
2062 | handle_chipset(); | ||
2063 | zoran_cards = find_zoran(); | ||
2064 | if (zoran_cards <= 0) | ||
2065 | return -EIO; | ||
2066 | |||
2067 | /* initialize Zorans */ | ||
2068 | for (card=0; card<zoran_cards; card++) { | ||
2069 | if (init_zoran(card) < 0) { | ||
2070 | /* only release the zorans we have registered */ | ||
2071 | release_zoran(card); | ||
2072 | return -EIO; | ||
2073 | } | ||
2074 | } | ||
2075 | return 0; | ||
2076 | } | ||
2077 | |||
2078 | module_init(zr36120_init); | ||
2079 | module_exit(zr36120_exit); | ||
diff --git a/drivers/media/video/zr36120.h b/drivers/media/video/zr36120.h deleted file mode 100644 index a71e485b0f98..000000000000 --- a/drivers/media/video/zr36120.h +++ /dev/null | |||
@@ -1,279 +0,0 @@ | |||
1 | /* | ||
2 | zr36120.h - Zoran 36120/36125 based framegrabbers | ||
3 | |||
4 | Copyright (C) 1998-1999 Pauline Middelink (middelin@polyware.nl) | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef _ZR36120_H | ||
22 | #define _ZR36120_H | ||
23 | |||
24 | #ifdef __KERNEL__ | ||
25 | |||
26 | #include <linux/types.h> | ||
27 | #include <linux/wait.h> | ||
28 | |||
29 | #include <linux/i2c-old.h> | ||
30 | #include <linux/videodev.h> | ||
31 | |||
32 | #include <asm/io.h> | ||
33 | |||
34 | /* | ||
35 | * Debug macro's, place an x behind the ) for actual debug-compilation | ||
36 | * E.g. #define DEBUG(x...) x | ||
37 | */ | ||
38 | #define DEBUG(x...) /* Debug driver */ | ||
39 | #define IDEBUG(x...) /* Debug interrupt handler */ | ||
40 | #define PDEBUG 0 /* Debug PCI writes */ | ||
41 | |||
42 | /* defined in zr36120_i2c */ | ||
43 | extern struct i2c_bus zoran_i2c_bus_template; | ||
44 | |||
45 | #define ZORAN_MAX_FBUFFERS 2 | ||
46 | #define ZORAN_MAX_FBUFFER (768*576*2) | ||
47 | #define ZORAN_MAX_FBUFSIZE (ZORAN_MAX_FBUFFERS*ZORAN_MAX_FBUFFER) | ||
48 | |||
49 | #define ZORAN_VBI_BUFFERS 2 | ||
50 | #define ZORAN_VBI_BUFSIZE (22*1024*2) | ||
51 | |||
52 | struct tvcard { | ||
53 | char* name; /* name of the cardtype */ | ||
54 | int video_inputs; /* number of channels defined in video_mux */ | ||
55 | int audio_inputs; /* number of channels defined in audio_mux */ | ||
56 | __u32 swapi2c:1, /* need to swap i2c wires SDA/SCL? */ | ||
57 | usegirq1:1, /* VSYNC at GIRQ1 instead of GIRQ0? */ | ||
58 | vsync_pos:1, /* positive VSYNC signal? */ | ||
59 | hsync_pos:1, /* positive HSYNC signal? */ | ||
60 | gpdir:8, /* General Purpose Direction register */ | ||
61 | gpval:8; /* General Purpose Value register */ | ||
62 | int video_mux[6]; /* mapping channel number to physical input */ | ||
63 | #define IS_TUNER 0x80 | ||
64 | #define IS_SVHS 0x40 | ||
65 | #define CHANNEL_MASK 0x3F | ||
66 | int audio_mux[6]; /* mapping channel number to physical input */ | ||
67 | }; | ||
68 | #define TUNER(x) ((x)|IS_TUNER) | ||
69 | #define SVHS(x) ((x)|IS_SVHS) | ||
70 | |||
71 | struct vidinfo { | ||
72 | struct vidinfo* next; /* next active buffer */ | ||
73 | uint kindof; | ||
74 | #define FBUFFER_OVERLAY 0 | ||
75 | #define FBUFFER_GRAB 1 | ||
76 | #define FBUFFER_VBI 2 | ||
77 | uint status; | ||
78 | #define FBUFFER_FREE 0 | ||
79 | #define FBUFFER_BUSY 1 | ||
80 | #define FBUFFER_DONE 2 | ||
81 | ulong fieldnr; /* # of field, not framer! */ | ||
82 | uint x,y; | ||
83 | int w,h; /* w,h can be negative! */ | ||
84 | uint format; /* index in palette2fmt[] */ | ||
85 | uint bpp; /* lookup from palette2fmt[] */ | ||
86 | uint bpl; /* calc: width * bpp */ | ||
87 | ulong busadr; /* bus addr for DMA engine */ | ||
88 | char* memadr; /* kernel addr for making copies */ | ||
89 | ulong* overlay; /* kernel addr of overlay mask */ | ||
90 | }; | ||
91 | |||
92 | struct zoran | ||
93 | { | ||
94 | struct video_device video_dev; | ||
95 | #define CARD_DEBUG KERN_DEBUG "%s(%lu): " | ||
96 | #define CARD_INFO KERN_INFO "%s(%lu): " | ||
97 | #define CARD_ERR KERN_ERR "%s(%lu): " | ||
98 | #define CARD ztv->video_dev.name,ztv->fieldnr | ||
99 | |||
100 | /* zoran chip specific details */ | ||
101 | struct i2c_bus i2c; /* i2c registration data */ | ||
102 | struct pci_dev* dev; /* ptr to PCI device */ | ||
103 | ulong zoran_adr; /* bus address of IO memory */ | ||
104 | char* zoran_mem; /* kernel address of IO memory */ | ||
105 | struct tvcard* card; /* the cardtype */ | ||
106 | uint norm; /* 0=PAL, 1=NTSC, 2=SECAM */ | ||
107 | uint tuner_freq; /* Current freq in kHz */ | ||
108 | struct video_picture picture; /* Current picture params */ | ||
109 | |||
110 | /* videocard details */ | ||
111 | uint swidth; /* screen width */ | ||
112 | uint sheight; /* screen height */ | ||
113 | uint depth; /* depth in bits */ | ||
114 | |||
115 | /* State details */ | ||
116 | char* fbuffer; /* framebuffers for mmap */ | ||
117 | struct vidinfo overinfo; /* overlay data */ | ||
118 | struct vidinfo grabinfo[ZORAN_MAX_FBUFFERS]; /* grabbing data*/ | ||
119 | wait_queue_head_t grabq; /* grabbers queue */ | ||
120 | |||
121 | /* VBI details */ | ||
122 | struct video_device vbi_dev; | ||
123 | struct vidinfo readinfo[2]; /* VBI data - flip buffers */ | ||
124 | wait_queue_head_t vbiq; /* vbi queue */ | ||
125 | |||
126 | /* maintenance data */ | ||
127 | int have_decoder; /* did we detect a mux? */ | ||
128 | int have_tuner; /* did we detect a tuner? */ | ||
129 | int users; /* howmany video/vbi open? */ | ||
130 | int tuner_type; /* tuner type, when found */ | ||
131 | int running; /* are we rolling? */ | ||
132 | rwlock_t lock; | ||
133 | long state; /* what is requested of us? */ | ||
134 | #define STATE_OVERLAY 0 | ||
135 | #define STATE_VBI 1 | ||
136 | struct vidinfo* workqueue; /* buffers to grab, head is active */ | ||
137 | ulong fieldnr; /* #field, ticked every VSYNC */ | ||
138 | ulong lastfieldnr; /* #field, ticked every GRAB */ | ||
139 | |||
140 | int vidInterlace; /* calculated */ | ||
141 | int vidXshift; /* calculated */ | ||
142 | uint vidWidth; /* calculated */ | ||
143 | uint vidHeight; /* calculated */ | ||
144 | }; | ||
145 | |||
146 | #define zrwrite(dat,adr) writel((dat),(char *) (ztv->zoran_mem+(adr))) | ||
147 | #define zrread(adr) readl(ztv->zoran_mem+(adr)) | ||
148 | |||
149 | #if PDEBUG == 0 | ||
150 | #define zrand(dat,adr) zrwrite((dat) & zrread(adr), adr) | ||
151 | #define zror(dat,adr) zrwrite((dat) | zrread(adr), adr) | ||
152 | #define zraor(dat,mask,adr) zrwrite( ((dat)&~(mask)) | ((mask)&zrread(adr)), adr) | ||
153 | #else | ||
154 | #define zrand(dat, adr) \ | ||
155 | do { \ | ||
156 | ulong data = (dat) & zrread((adr)); \ | ||
157 | zrwrite(data, (adr)); \ | ||
158 | if (0 != (~(dat) & zrread((adr)))) \ | ||
159 | printk(KERN_DEBUG "zoran: zrand at %d(%d) detected set bits(%x)\n", __LINE__, (adr), (dat)); \ | ||
160 | } while(0) | ||
161 | |||
162 | #define zror(dat, adr) \ | ||
163 | do { \ | ||
164 | ulong data = (dat) | zrread((adr)); \ | ||
165 | zrwrite(data, (adr)); \ | ||
166 | if ((dat) != ((dat) & zrread(adr))) \ | ||
167 | printk(KERN_DEBUG "zoran: zror at %d(%d) detected unset bits(%x)\n", __LINE__, (adr), (dat)); \ | ||
168 | } while(0) | ||
169 | |||
170 | #define zraor(dat, mask, adr) \ | ||
171 | do { \ | ||
172 | ulong data; \ | ||
173 | if ((dat) & (mask)) \ | ||
174 | printk(KERN_DEBUG "zoran: zraor at %d(%d) detected bits(%x:%x)\n", __LINE__, (adr), (dat), (mask)); \ | ||
175 | data = ((dat)&~(mask)) | ((mask) & zrread((adr))); \ | ||
176 | zrwrite(data,(adr)); \ | ||
177 | if ( (dat) != (~(mask) & zrread((adr))) ) \ | ||
178 | printk(KERN_DEBUG "zoran: zraor at %d(%d) could not set all bits(%x:%x)\n", __LINE__, (adr), (dat), (mask)); \ | ||
179 | } while(0) | ||
180 | #endif | ||
181 | |||
182 | #endif | ||
183 | |||
184 | /* zoran PCI address space */ | ||
185 | #define ZORAN_VFEH 0x000 /* Video Front End Horizontal Conf. */ | ||
186 | #define ZORAN_VFEH_HSPOL (1<<30) | ||
187 | #define ZORAN_VFEH_HSTART (0x3FF<<10) | ||
188 | #define ZORAN_VFEH_HEND (0x3FF<<0) | ||
189 | |||
190 | #define ZORAN_VFEV 0x004 /* Video Front End Vertical Conf. */ | ||
191 | #define ZORAN_VFEV_VSPOL (1<<30) | ||
192 | #define ZORAN_VFEV_VSTART (0x3FF<<10) | ||
193 | #define ZORAN_VFEV_VEND (0x3FF<<0) | ||
194 | |||
195 | #define ZORAN_VFEC 0x008 /* Video Front End Scaler and Pixel */ | ||
196 | #define ZORAN_VFEC_EXTFL (1<<26) | ||
197 | #define ZORAN_VFEC_TOPFIELD (1<<25) | ||
198 | #define ZORAN_VFEC_VCLKPOL (1<<24) | ||
199 | #define ZORAN_VFEC_HFILTER (7<<21) | ||
200 | #define ZORAN_VFEC_HFILTER_1 (0<<21) /* no lumi, 3-tap chromo */ | ||
201 | #define ZORAN_VFEC_HFILTER_2 (1<<21) /* 3-tap lumi, 3-tap chromo */ | ||
202 | #define ZORAN_VFEC_HFILTER_3 (2<<21) /* 4-tap lumi, 4-tap chromo */ | ||
203 | #define ZORAN_VFEC_HFILTER_4 (3<<21) /* 5-tap lumi, 4-tap chromo */ | ||
204 | #define ZORAN_VFEC_HFILTER_5 (4<<21) /* 4-tap lumi, 4-tap chromo */ | ||
205 | #define ZORAN_VFEC_DUPFLD (1<<20) | ||
206 | #define ZORAN_VFEC_HORDCM (63<<14) | ||
207 | #define ZORAN_VFEC_VERDCM (63<<8) | ||
208 | #define ZORAN_VFEC_DISPMOD (1<<6) | ||
209 | #define ZORAN_VFEC_RGB (3<<3) | ||
210 | #define ZORAN_VFEC_RGB_YUV422 (0<<3) | ||
211 | #define ZORAN_VFEC_RGB_RGB888 (1<<3) | ||
212 | #define ZORAN_VFEC_RGB_RGB565 (2<<3) | ||
213 | #define ZORAN_VFEC_RGB_RGB555 (3<<3) | ||
214 | #define ZORAN_VFEC_ERRDIF (1<<2) | ||
215 | #define ZORAN_VFEC_PACK24 (1<<1) | ||
216 | #define ZORAN_VFEC_LE (1<<0) | ||
217 | |||
218 | #define ZORAN_VTOP 0x00C /* Video Display "Top" */ | ||
219 | |||
220 | #define ZORAN_VBOT 0x010 /* Video Display "Bottom" */ | ||
221 | |||
222 | #define ZORAN_VSTR 0x014 /* Video Display Stride */ | ||
223 | #define ZORAN_VSTR_DISPSTRIDE (0xFFFF<<16) | ||
224 | #define ZORAN_VSTR_VIDOVF (1<<8) | ||
225 | #define ZORAN_VSTR_SNAPSHOT (1<<1) | ||
226 | #define ZORAN_VSTR_GRAB (1<<0) | ||
227 | |||
228 | #define ZORAN_VDC 0x018 /* Video Display Conf. */ | ||
229 | #define ZORAN_VDC_VIDEN (1<<31) | ||
230 | #define ZORAN_VDC_MINPIX (0x1F<<25) | ||
231 | #define ZORAN_VDC_TRICOM (1<<24) | ||
232 | #define ZORAN_VDC_VIDWINHT (0x3FF<<12) | ||
233 | #define ZORAN_VDC_VIDWINWID (0x3FF<<0) | ||
234 | |||
235 | #define ZORAN_MTOP 0x01C /* Masking Map "Top" */ | ||
236 | |||
237 | #define ZORAN_MBOT 0x020 /* Masking Map "Bottom" */ | ||
238 | |||
239 | #define ZORAN_OCR 0x024 /* Overlay Control */ | ||
240 | #define ZORAN_OCR_OVLEN (1<<15) | ||
241 | #define ZORAN_OCR_MASKSTRIDE (0xFF<<0) | ||
242 | |||
243 | #define ZORAN_PCI 0x028 /* System, PCI and GPP Control */ | ||
244 | #define ZORAN_PCI_SOFTRESET (1<<24) | ||
245 | #define ZORAN_PCI_WAITSTATE (3<<16) | ||
246 | #define ZORAN_PCI_GENPURDIR (0xFF<<0) | ||
247 | |||
248 | #define ZORAN_GUEST 0x02C /* GuestBus Control */ | ||
249 | |||
250 | #define ZORAN_CSOURCE 0x030 /* Code Source Address */ | ||
251 | |||
252 | #define ZORAN_CTRANS 0x034 /* Code Transfer Control */ | ||
253 | |||
254 | #define ZORAN_CMEM 0x038 /* Code Memory Pointer */ | ||
255 | |||
256 | #define ZORAN_ISR 0x03C /* Interrupt Status Register */ | ||
257 | #define ZORAN_ISR_CODE (1<<28) | ||
258 | #define ZORAN_ISR_GIRQ0 (1<<29) | ||
259 | #define ZORAN_ISR_GIRQ1 (1<<30) | ||
260 | |||
261 | #define ZORAN_ICR 0x040 /* Interrupt Control Register */ | ||
262 | #define ZORAN_ICR_EN (1<<24) | ||
263 | #define ZORAN_ICR_CODE (1<<28) | ||
264 | #define ZORAN_ICR_GIRQ0 (1<<29) | ||
265 | #define ZORAN_ICR_GIRQ1 (1<<30) | ||
266 | |||
267 | #define ZORAN_I2C 0x044 /* I2C-Bus */ | ||
268 | #define ZORAN_I2C_SCL (1<<1) | ||
269 | #define ZORAN_I2C_SDA (1<<0) | ||
270 | |||
271 | #define ZORAN_POST 0x48 /* PostOffice */ | ||
272 | #define ZORAN_POST_PEN (1<<25) | ||
273 | #define ZORAN_POST_TIME (1<<24) | ||
274 | #define ZORAN_POST_DIR (1<<23) | ||
275 | #define ZORAN_POST_GUESTID (3<<20) | ||
276 | #define ZORAN_POST_GUEST (7<<16) | ||
277 | #define ZORAN_POST_DATA (0xFF<<0) | ||
278 | |||
279 | #endif | ||
diff --git a/drivers/media/video/zr36120_i2c.c b/drivers/media/video/zr36120_i2c.c deleted file mode 100644 index 21fde43a6aed..000000000000 --- a/drivers/media/video/zr36120_i2c.c +++ /dev/null | |||
@@ -1,132 +0,0 @@ | |||
1 | /* | ||
2 | zr36120_i2c.c - Zoran 36120/36125 based framegrabbers | ||
3 | |||
4 | Copyright (C) 1998-1999 Pauline Middelink <middelin@polyware.nl> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/types.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <asm/io.h> | ||
24 | |||
25 | #include <linux/video_decoder.h> | ||
26 | #include <asm/uaccess.h> | ||
27 | |||
28 | #include "tuner.h" | ||
29 | #include "zr36120.h" | ||
30 | |||
31 | /* ----------------------------------------------------------------------- */ | ||
32 | /* I2C functions */ | ||
33 | /* ----------------------------------------------------------------------- */ | ||
34 | |||
35 | /* software I2C functions */ | ||
36 | |||
37 | #define I2C_DELAY 10 | ||
38 | |||
39 | static void i2c_setlines(struct i2c_bus *bus,int ctrl,int data) | ||
40 | { | ||
41 | struct zoran *ztv = (struct zoran*)bus->data; | ||
42 | unsigned int b = 0; | ||
43 | if (data) b |= ztv->card->swapi2c ? ZORAN_I2C_SCL : ZORAN_I2C_SDA; | ||
44 | if (ctrl) b |= ztv->card->swapi2c ? ZORAN_I2C_SDA : ZORAN_I2C_SCL; | ||
45 | zrwrite(b, ZORAN_I2C); | ||
46 | udelay(I2C_DELAY); | ||
47 | } | ||
48 | |||
49 | static int i2c_getdataline(struct i2c_bus *bus) | ||
50 | { | ||
51 | struct zoran *ztv = (struct zoran*)bus->data; | ||
52 | if (ztv->card->swapi2c) | ||
53 | return zrread(ZORAN_I2C) & ZORAN_I2C_SCL; | ||
54 | return zrread(ZORAN_I2C) & ZORAN_I2C_SDA; | ||
55 | } | ||
56 | |||
57 | static | ||
58 | void attach_inform(struct i2c_bus *bus, int id) | ||
59 | { | ||
60 | struct zoran *ztv = (struct zoran*)bus->data; | ||
61 | struct video_decoder_capability dc; | ||
62 | int rv; | ||
63 | |||
64 | switch (id) { | ||
65 | case I2C_DRIVERID_VIDEODECODER: | ||
66 | DEBUG(printk(CARD_INFO "decoder attached\n",CARD)); | ||
67 | |||
68 | /* fetch the capabilities of the decoder */ | ||
69 | rv = i2c_control_device(&ztv->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_GET_CAPABILITIES, &dc); | ||
70 | if (rv) { | ||
71 | DEBUG(printk(CARD_DEBUG "decoder is not V4L aware!\n",CARD)); | ||
72 | break; | ||
73 | } | ||
74 | DEBUG(printk(CARD_DEBUG "capabilities %d %d %d\n",CARD,dc.flags,dc.inputs,dc.outputs)); | ||
75 | |||
76 | /* Test if the decoder can de VBI transfers */ | ||
77 | if (dc.flags & 16 /*VIDEO_DECODER_VBI*/) | ||
78 | ztv->have_decoder = 2; | ||
79 | else | ||
80 | ztv->have_decoder = 1; | ||
81 | break; | ||
82 | case I2C_DRIVERID_TUNER: | ||
83 | ztv->have_tuner = 1; | ||
84 | DEBUG(printk(CARD_INFO "tuner attached\n",CARD)); | ||
85 | if (ztv->tuner_type >= 0) | ||
86 | { | ||
87 | if (i2c_control_device(&ztv->i2c,I2C_DRIVERID_TUNER,TUNER_SET_TYPE,&ztv->tuner_type)<0) | ||
88 | DEBUG(printk(CARD_INFO "attach_inform; tuner won't be set to type %d\n",CARD,ztv->tuner_type)); | ||
89 | } | ||
90 | break; | ||
91 | default: | ||
92 | DEBUG(printk(CARD_INFO "attach_inform; unknown device id=%d\n",CARD,id)); | ||
93 | break; | ||
94 | } | ||
95 | } | ||
96 | |||
97 | static | ||
98 | void detach_inform(struct i2c_bus *bus, int id) | ||
99 | { | ||
100 | struct zoran *ztv = (struct zoran*)bus->data; | ||
101 | |||
102 | switch (id) { | ||
103 | case I2C_DRIVERID_VIDEODECODER: | ||
104 | ztv->have_decoder = 0; | ||
105 | DEBUG(printk(CARD_INFO "decoder detached\n",CARD)); | ||
106 | break; | ||
107 | case I2C_DRIVERID_TUNER: | ||
108 | ztv->have_tuner = 0; | ||
109 | DEBUG(printk(CARD_INFO "tuner detached\n",CARD)); | ||
110 | break; | ||
111 | default: | ||
112 | DEBUG(printk(CARD_INFO "detach_inform; unknown device id=%d\n",CARD,id)); | ||
113 | break; | ||
114 | } | ||
115 | } | ||
116 | |||
117 | struct i2c_bus zoran_i2c_bus_template = | ||
118 | { | ||
119 | "ZR36120", | ||
120 | I2C_BUSID_ZORAN, | ||
121 | NULL, | ||
122 | |||
123 | SPIN_LOCK_UNLOCKED, | ||
124 | |||
125 | attach_inform, | ||
126 | detach_inform, | ||
127 | |||
128 | i2c_setlines, | ||
129 | i2c_getdataline, | ||
130 | NULL, | ||
131 | NULL | ||
132 | }; | ||
diff --git a/drivers/media/video/zr36120_mem.c b/drivers/media/video/zr36120_mem.c deleted file mode 100644 index 416eaa93b8a4..000000000000 --- a/drivers/media/video/zr36120_mem.c +++ /dev/null | |||
@@ -1,78 +0,0 @@ | |||
1 | /* | ||
2 | zr36120_mem.c - Zoran 36120/36125 based framegrabbers | ||
3 | |||
4 | Copyright (C) 1998-1999 Pauline Middelink <middelin@polyware.nl> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/mm.h> | ||
22 | #include <linux/pci.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <asm/io.h> | ||
26 | #ifdef CONFIG_BIGPHYS_AREA | ||
27 | #include <linux/bigphysarea.h> | ||
28 | #endif | ||
29 | |||
30 | #include "zr36120.h" | ||
31 | #include "zr36120_mem.h" | ||
32 | |||
33 | /*******************************/ | ||
34 | /* Memory management functions */ | ||
35 | /*******************************/ | ||
36 | |||
37 | void* bmalloc(unsigned long size) | ||
38 | { | ||
39 | void* mem; | ||
40 | #ifdef CONFIG_BIGPHYS_AREA | ||
41 | mem = bigphysarea_alloc_pages(size/PAGE_SIZE, 1, GFP_KERNEL); | ||
42 | #else | ||
43 | /* | ||
44 | * The following function got a lot of memory at boottime, | ||
45 | * so we know its always there... | ||
46 | */ | ||
47 | mem = (void*)__get_free_pages(GFP_USER|GFP_DMA,get_order(size)); | ||
48 | #endif | ||
49 | if (mem) { | ||
50 | unsigned long adr = (unsigned long)mem; | ||
51 | while (size > 0) { | ||
52 | SetPageReserved(virt_to_page(phys_to_virt(adr))); | ||
53 | adr += PAGE_SIZE; | ||
54 | size -= PAGE_SIZE; | ||
55 | } | ||
56 | } | ||
57 | return mem; | ||
58 | } | ||
59 | |||
60 | void bfree(void* mem, unsigned long size) | ||
61 | { | ||
62 | if (mem) { | ||
63 | unsigned long adr = (unsigned long)mem; | ||
64 | unsigned long siz = size; | ||
65 | while (siz > 0) { | ||
66 | ClearPageReserved(virt_to_page(phys_to_virt(adr))); | ||
67 | adr += PAGE_SIZE; | ||
68 | siz -= PAGE_SIZE; | ||
69 | } | ||
70 | #ifdef CONFIG_BIGPHYS_AREA | ||
71 | bigphysarea_free_pages(mem); | ||
72 | #else | ||
73 | free_pages((unsigned long)mem,get_order(size)); | ||
74 | #endif | ||
75 | } | ||
76 | } | ||
77 | |||
78 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/video/zr36120_mem.h b/drivers/media/video/zr36120_mem.h deleted file mode 100644 index aad117acc91d..000000000000 --- a/drivers/media/video/zr36120_mem.h +++ /dev/null | |||
@@ -1,3 +0,0 @@ | |||
1 | /* either kmalloc() or bigphysarea() alloced memory - continuous */ | ||
2 | void* bmalloc(unsigned long size); | ||
3 | void bfree(void* mem, unsigned long size); | ||
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h index 0a8f750cbede..0f4cf34b6fa2 100644 --- a/include/linux/i2c-id.h +++ b/include/linux/i2c-id.h | |||
@@ -159,6 +159,7 @@ | |||
159 | #define I2C_DRIVERID_ASB100 1043 | 159 | #define I2C_DRIVERID_ASB100 1043 |
160 | #define I2C_DRIVERID_FSCHER 1046 | 160 | #define I2C_DRIVERID_FSCHER 1046 |
161 | #define I2C_DRIVERID_W83L785TS 1047 | 161 | #define I2C_DRIVERID_W83L785TS 1047 |
162 | #define I2C_DRIVERID_OV7670 1048 /* Omnivision 7670 camera */ | ||
162 | 163 | ||
163 | /* | 164 | /* |
164 | * ---- Adapter types ---------------------------------------------------- | 165 | * ---- Adapter types ---------------------------------------------------- |
@@ -250,6 +251,7 @@ | |||
250 | #define I2C_HW_SMBUS_OV518 0x04000f /* OV518(+) USB 1.1 webcam ICs */ | 251 | #define I2C_HW_SMBUS_OV518 0x04000f /* OV518(+) USB 1.1 webcam ICs */ |
251 | #define I2C_HW_SMBUS_OV519 0x040010 /* OV519 USB 1.1 webcam IC */ | 252 | #define I2C_HW_SMBUS_OV519 0x040010 /* OV519 USB 1.1 webcam IC */ |
252 | #define I2C_HW_SMBUS_OVFX2 0x040011 /* Cypress/OmniVision FX2 webcam */ | 253 | #define I2C_HW_SMBUS_OVFX2 0x040011 /* Cypress/OmniVision FX2 webcam */ |
254 | #define I2C_HW_SMBUS_CAFE 0x040012 /* Marvell 88ALP01 "CAFE" cam */ | ||
253 | 255 | ||
254 | /* --- ISA pseudo-adapter */ | 256 | /* --- ISA pseudo-adapter */ |
255 | #define I2C_HW_ISA 0x050000 | 257 | #define I2C_HW_ISA 0x050000 |
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index df5c4654360d..5cb380a559fd 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h | |||
@@ -244,6 +244,7 @@ struct v4l2_pix_format | |||
244 | #define V4L2_PIX_FMT_YYUV v4l2_fourcc('Y','Y','U','V') /* 16 YUV 4:2:2 */ | 244 | #define V4L2_PIX_FMT_YYUV v4l2_fourcc('Y','Y','U','V') /* 16 YUV 4:2:2 */ |
245 | #define V4L2_PIX_FMT_HI240 v4l2_fourcc('H','I','2','4') /* 8 8-bit color */ | 245 | #define V4L2_PIX_FMT_HI240 v4l2_fourcc('H','I','2','4') /* 8 8-bit color */ |
246 | #define V4L2_PIX_FMT_HM12 v4l2_fourcc('H','M','1','2') /* 8 YUV 4:2:0 16x16 macroblocks */ | 246 | #define V4L2_PIX_FMT_HM12 v4l2_fourcc('H','M','1','2') /* 8 YUV 4:2:0 16x16 macroblocks */ |
247 | #define V4L2_PIX_FMT_RGB444 v4l2_fourcc('R','4','4','4') /* 16 xxxxrrrr ggggbbbb */ | ||
247 | 248 | ||
248 | /* see http://www.siliconimaging.com/RGB%20Bayer.htm */ | 249 | /* see http://www.siliconimaging.com/RGB%20Bayer.htm */ |
249 | #define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B','A','8','1') /* 8 BGBG.. GRGR.. */ | 250 | #define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B','A','8','1') /* 8 BGBG.. GRGR.. */ |
diff --git a/include/media/ir-common.h b/include/media/ir-common.h index 8f58406533c6..2b25f5c95006 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h | |||
@@ -92,6 +92,7 @@ extern IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE]; | |||
92 | extern IR_KEYTAB_TYPE ir_codes_npgtech[IR_KEYTAB_SIZE]; | 92 | extern IR_KEYTAB_TYPE ir_codes_npgtech[IR_KEYTAB_SIZE]; |
93 | extern IR_KEYTAB_TYPE ir_codes_norwood[IR_KEYTAB_SIZE]; | 93 | extern IR_KEYTAB_TYPE ir_codes_norwood[IR_KEYTAB_SIZE]; |
94 | extern IR_KEYTAB_TYPE ir_codes_proteus_2309[IR_KEYTAB_SIZE]; | 94 | extern IR_KEYTAB_TYPE ir_codes_proteus_2309[IR_KEYTAB_SIZE]; |
95 | extern IR_KEYTAB_TYPE ir_codes_budget_ci_old[IR_KEYTAB_SIZE]; | ||
95 | 96 | ||
96 | #endif | 97 | #endif |
97 | 98 | ||
diff --git a/include/media/saa7146.h b/include/media/saa7146.h index fee579f10b32..796bcf151a3a 100644 --- a/include/media/saa7146.h +++ b/include/media/saa7146.h | |||
@@ -42,10 +42,6 @@ extern unsigned int saa7146_debug; | |||
42 | #define DEB_INT(x) if (0!=(DEBUG_VARIABLE&0x20)) { DEBUG_PROLOG; printk x; } /* interrupt debug messages */ | 42 | #define DEB_INT(x) if (0!=(DEBUG_VARIABLE&0x20)) { DEBUG_PROLOG; printk x; } /* interrupt debug messages */ |
43 | #define DEB_CAP(x) if (0!=(DEBUG_VARIABLE&0x40)) { DEBUG_PROLOG; printk x; } /* capture debug messages */ | 43 | #define DEB_CAP(x) if (0!=(DEBUG_VARIABLE&0x40)) { DEBUG_PROLOG; printk x; } /* capture debug messages */ |
44 | 44 | ||
45 | #define SAA7146_IER_DISABLE(x,y) \ | ||
46 | saa7146_write(x, IER, saa7146_read(x, IER) & ~(y)); | ||
47 | #define SAA7146_IER_ENABLE(x,y) \ | ||
48 | saa7146_write(x, IER, saa7146_read(x, IER) | (y)); | ||
49 | #define SAA7146_ISR_CLEAR(x,y) \ | 45 | #define SAA7146_ISR_CLEAR(x,y) \ |
50 | saa7146_write(x, ISR, (y)); | 46 | saa7146_write(x, ISR, (y)); |
51 | 47 | ||
@@ -441,4 +437,20 @@ int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop); | |||
441 | #define SAA7146_I2C_BUS_BIT_RATE_80 (0x200) | 437 | #define SAA7146_I2C_BUS_BIT_RATE_80 (0x200) |
442 | #define SAA7146_I2C_BUS_BIT_RATE_60 (0x300) | 438 | #define SAA7146_I2C_BUS_BIT_RATE_60 (0x300) |
443 | 439 | ||
440 | static inline void SAA7146_IER_DISABLE(struct saa7146_dev *x, unsigned y) | ||
441 | { | ||
442 | unsigned long flags; | ||
443 | spin_lock_irqsave(&x->int_slock, flags); | ||
444 | saa7146_write(x, IER, saa7146_read(x, IER) & ~y); | ||
445 | spin_unlock_irqrestore(&x->int_slock, flags); | ||
446 | } | ||
447 | |||
448 | static inline void SAA7146_IER_ENABLE(struct saa7146_dev *x, unsigned y) | ||
449 | { | ||
450 | unsigned long flags; | ||
451 | spin_lock_irqsave(&x->int_slock, flags); | ||
452 | saa7146_write(x, IER, saa7146_read(x, IER) | y); | ||
453 | spin_unlock_irqrestore(&x->int_slock, flags); | ||
454 | } | ||
455 | |||
444 | #endif | 456 | #endif |
diff --git a/include/media/tuner-types.h b/include/media/tuner-types.h index 37dad07a8439..e5ad3fcfe984 100644 --- a/include/media/tuner-types.h +++ b/include/media/tuner-types.h | |||
@@ -50,6 +50,10 @@ struct tuner_params { | |||
50 | sensitivity. If this setting is 1, then set PORT2 to 1 to | 50 | sensitivity. If this setting is 1, then set PORT2 to 1 to |
51 | get proper FM reception. */ | 51 | get proper FM reception. */ |
52 | unsigned int port2_fm_high_sensitivity:1; | 52 | unsigned int port2_fm_high_sensitivity:1; |
53 | /* Some Philips tuners use tda9887 cGainNormal to select the FM radio | ||
54 | sensitivity. If this setting is 1, e register will use cGainNormal | ||
55 | instead of cGainLow. */ | ||
56 | unsigned int fm_gain_normal:1; | ||
53 | /* Most tuners with a tda9887 use QSS mode. Some (cheaper) tuners | 57 | /* Most tuners with a tda9887 use QSS mode. Some (cheaper) tuners |
54 | use Intercarrier mode. If this setting is 1, then the tuner | 58 | use Intercarrier mode. If this setting is 1, then the tuner |
55 | needs to be set to intercarrier mode. */ | 59 | needs to be set to intercarrier mode. */ |
diff --git a/include/media/tuner.h b/include/media/tuner.h index 3116e750132f..99acf847365c 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h | |||
@@ -145,6 +145,7 @@ extern int tuner_debug; | |||
145 | #define TDA9887_DEEMPHASIS_75 (3<<16) | 145 | #define TDA9887_DEEMPHASIS_75 (3<<16) |
146 | #define TDA9887_AUTOMUTE (1<<18) | 146 | #define TDA9887_AUTOMUTE (1<<18) |
147 | #define TDA9887_GATING_18 (1<<19) | 147 | #define TDA9887_GATING_18 (1<<19) |
148 | #define TDA9887_GAIN_NORMAL (1<<20) | ||
148 | 149 | ||
149 | #ifdef __KERNEL__ | 150 | #ifdef __KERNEL__ |
150 | 151 | ||
diff --git a/include/media/tveeprom.h b/include/media/tveeprom.h index e9fc1a785497..5660ea24996b 100644 --- a/include/media/tveeprom.h +++ b/include/media/tveeprom.h | |||
@@ -3,7 +3,7 @@ | |||
3 | 3 | ||
4 | struct tveeprom { | 4 | struct tveeprom { |
5 | u32 has_radio; | 5 | u32 has_radio; |
6 | u32 has_ir; /* 0: no IR, 1: IR present, 2: unknown */ | 6 | u32 has_ir; /* bit 0: IR receiver present, bit 1: IR transmitter (blaster) present. -1 == unknown */ |
7 | u32 has_MAC_address; /* 0: no MAC, 1: MAC present, 2: unknown */ | 7 | u32 has_MAC_address; /* 0: no MAC, 1: MAC present, 2: unknown */ |
8 | 8 | ||
9 | u32 tuner_type; | 9 | u32 tuner_type; |
diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index aecc946980a3..91b19921f958 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h | |||
@@ -144,6 +144,9 @@ enum v4l2_chip_ident { | |||
144 | V4L2_IDENT_CX25841 = 241, | 144 | V4L2_IDENT_CX25841 = 241, |
145 | V4L2_IDENT_CX25842 = 242, | 145 | V4L2_IDENT_CX25842 = 242, |
146 | V4L2_IDENT_CX25843 = 243, | 146 | V4L2_IDENT_CX25843 = 243, |
147 | |||
148 | /* OmniVision sensors - range 250-299 */ | ||
149 | V4L2_IDENT_OV7670 = 250, | ||
147 | }; | 150 | }; |
148 | 151 | ||
149 | /* audio ioctls */ | 152 | /* audio ioctls */ |
@@ -251,4 +254,8 @@ struct v4l2_crystal_freq { | |||
251 | If the frequency is not supported, then -EINVAL is returned. */ | 254 | If the frequency is not supported, then -EINVAL is returned. */ |
252 | #define VIDIOC_INT_S_CRYSTAL_FREQ _IOW ('d', 113, struct v4l2_crystal_freq) | 255 | #define VIDIOC_INT_S_CRYSTAL_FREQ _IOW ('d', 113, struct v4l2_crystal_freq) |
253 | 256 | ||
257 | /* Initialize the sensor registors to some sort of reasonable | ||
258 | default values. */ | ||
259 | #define VIDIOC_INT_INIT _IOW ('d', 114, u32) | ||
260 | |||
254 | #endif /* V4L2_COMMON_H_ */ | 261 | #endif /* V4L2_COMMON_H_ */ |
diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index 6a11d772700f..fb96472a1bd3 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h | |||
@@ -43,6 +43,7 @@ | |||
43 | 43 | ||
44 | /* Video standard functions */ | 44 | /* Video standard functions */ |
45 | extern unsigned int v4l2_video_std_fps(struct v4l2_standard *vs); | 45 | extern unsigned int v4l2_video_std_fps(struct v4l2_standard *vs); |
46 | extern char *v4l2_norm_to_name(v4l2_std_id id); | ||
46 | extern int v4l2_video_std_construct(struct v4l2_standard *vs, | 47 | extern int v4l2_video_std_construct(struct v4l2_standard *vs, |
47 | int id, char *name); | 48 | int id, char *name); |
48 | 49 | ||
@@ -81,12 +82,6 @@ extern long v4l_compat_ioctl32(struct file *file, unsigned int cmd, | |||
81 | * This version moves redundant code from video device code to | 82 | * This version moves redundant code from video device code to |
82 | * the common handler | 83 | * the common handler |
83 | */ | 84 | */ |
84 | struct v4l2_tvnorm { | ||
85 | char *name; | ||
86 | v4l2_std_id id; | ||
87 | |||
88 | void *priv_data; | ||
89 | }; | ||
90 | 85 | ||
91 | struct video_device | 86 | struct video_device |
92 | { | 87 | { |
@@ -104,9 +99,8 @@ struct video_device | |||
104 | int debug; /* Activates debug level*/ | 99 | int debug; /* Activates debug level*/ |
105 | 100 | ||
106 | /* Video standard vars */ | 101 | /* Video standard vars */ |
107 | int tvnormsize; /* Size of tvnorm array */ | 102 | v4l2_std_id tvnorms; /* Supported tv norms */ |
108 | v4l2_std_id current_norm; /* Current tvnorm */ | 103 | v4l2_std_id current_norm; /* Current tvnorm */ |
109 | struct v4l2_tvnorm *tvnorms; | ||
110 | 104 | ||
111 | /* callbacks */ | 105 | /* callbacks */ |
112 | void (*release)(struct video_device *vfd); | 106 | void (*release)(struct video_device *vfd); |
@@ -211,7 +205,7 @@ struct video_device | |||
211 | /* Standard handling | 205 | /* Standard handling |
212 | G_STD and ENUMSTD are handled by videodev.c | 206 | G_STD and ENUMSTD are handled by videodev.c |
213 | */ | 207 | */ |
214 | int (*vidioc_s_std) (struct file *file, void *fh, v4l2_std_id a); | 208 | int (*vidioc_s_std) (struct file *file, void *fh, v4l2_std_id *norm); |
215 | int (*vidioc_querystd) (struct file *file, void *fh, v4l2_std_id *a); | 209 | int (*vidioc_querystd) (struct file *file, void *fh, v4l2_std_id *a); |
216 | 210 | ||
217 | /* Input handling */ | 211 | /* Input handling */ |