diff options
author | Mauro Carvalho Chehab <mchehab@brturbo.com.br> | 2005-11-09 00:37:24 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-09 10:56:17 -0500 |
commit | 596d92d5128d308b5a79f21c3e72c87f5fc7e58b (patch) | |
tree | 3957529296b0765e7979f205a9dd0bce7de1eb7a | |
parent | 2b5200a7b19a53969db68c97d379339592ca6a4f (diff) |
[PATCH] v4l: 767: included support for em2800
- Included support for em2800.
Signed-off-by: Mauro Carvalho Chehab <mchehab@brturbo.com.br>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | Documentation/video4linux/CARDLIST.em28xx | 13 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-cards.c | 125 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-core.c | 13 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-i2c.c | 182 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-video.c | 73 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx.h | 29 |
6 files changed, 375 insertions, 60 deletions
diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx index a33ddea0b6f5..d86aae09450b 100644 --- a/Documentation/video4linux/CARDLIST.em28xx +++ b/Documentation/video4linux/CARDLIST.em28xx | |||
@@ -1,4 +1,9 @@ | |||
1 | 0 -> Terratec Cinergy 250 USB [0ccd:0036] | 1 | 0 -> Unknown EM2800 video grabber (em2800) [eb1a:2800] |
2 | 1 -> Pinnacle PCTV USB 2 [2304:0208] | 2 | 1 -> Unknown EM2820/2840 video grabber (em2820/em2840) [eb1a:2820] |
3 | 2 -> Hauppauge WinTV USB 2 [2040:4200] | 3 | 2 -> Terratec Cinergy 250 USB (em2820/em2840) [0ccd:0036] |
4 | 3 -> MSI VOX USB 2.0 [eb1a:2820] | 4 | 3 -> Pinnacle PCTV USB 2 (em2820/em2840) [2304:0208] |
5 | 4 -> Hauppauge WinTV USB 2 (em2820/em2840) [2040:4200] | ||
6 | 5 -> MSI VOX USB 2.0 (em2820/em2840) | ||
7 | 6 -> Terratec Cinergy 200 USB (em2800) | ||
8 | 7 -> Leadtek Winfast USB II (em2800) | ||
9 | 8 -> Kworld USB2800 (em2800) | ||
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 7333bbad8871..91c70ebd0ea4 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | em2820-cards.c - driver for Empia EM2820/2840 USB video capture devices | 2 | em2820-cards.c - driver for Empia EM2800/EM2820/2840 USB video capture devices |
3 | 3 | ||
4 | Copyright (C) 2005 Markus Rechberger <mrechberger@gmail.com> | 4 | Copyright (C) 2005 Markus Rechberger <mrechberger@gmail.com> |
5 | Ludovico Cavedon <cavedon@sssup.it> | 5 | Ludovico Cavedon <cavedon@sssup.it> |
@@ -35,14 +35,43 @@ | |||
35 | 35 | ||
36 | #include "em2820.h" | 36 | #include "em2820.h" |
37 | 37 | ||
38 | enum em2820_board_entry { | ||
39 | EM2820_BOARD_TERRATEC_CINERGY_250, | ||
40 | EM2820_BOARD_PINNACLE_USB_2, | ||
41 | EM2820_BOARD_HAUPPAUGE_WINTV_USB_2, | ||
42 | EM2820_BOARD_MSI_VOX_USB_2 | ||
43 | }; | ||
44 | |||
45 | struct em2820_board em2820_boards[] = { | 38 | struct em2820_board em2820_boards[] = { |
39 | [EM2800_BOARD_UNKNOWN] = { | ||
40 | .name = "Unknown EM2800 video grabber", | ||
41 | .is_em2800 = 1, | ||
42 | .vchannels = 2, | ||
43 | .norm = VIDEO_MODE_PAL, | ||
44 | .tda9887_conf = TDA9887_PRESENT, | ||
45 | .has_tuner = 1, | ||
46 | .decoder = EM2820_SAA7113, | ||
47 | .input = {{ | ||
48 | .type = EM2820_VMUX_COMPOSITE1, | ||
49 | .vmux = 0, | ||
50 | .amux = 1, | ||
51 | },{ | ||
52 | .type = EM2820_VMUX_SVIDEO, | ||
53 | .vmux = 9, | ||
54 | .amux = 1, | ||
55 | }}, | ||
56 | }, | ||
57 | [EM2820_BOARD_UNKNOWN] = { | ||
58 | .name = "Unknown EM2820/2840 video grabber", | ||
59 | .is_em2800 = 0, | ||
60 | .vchannels = 2, | ||
61 | .norm = VIDEO_MODE_PAL, | ||
62 | .tda9887_conf = TDA9887_PRESENT, | ||
63 | .has_tuner = 1, | ||
64 | .decoder = EM2820_SAA7113, | ||
65 | .input = {{ | ||
66 | .type = EM2820_VMUX_COMPOSITE1, | ||
67 | .vmux = 0, | ||
68 | .amux = 1, | ||
69 | },{ | ||
70 | .type = EM2820_VMUX_SVIDEO, | ||
71 | .vmux = 9, | ||
72 | .amux = 1, | ||
73 | }}, | ||
74 | }, | ||
46 | [EM2820_BOARD_TERRATEC_CINERGY_250] = { | 75 | [EM2820_BOARD_TERRATEC_CINERGY_250] = { |
47 | .name = "Terratec Cinergy 250 USB", | 76 | .name = "Terratec Cinergy 250 USB", |
48 | .vchannels = 3, | 77 | .vchannels = 3, |
@@ -129,17 +158,88 @@ struct em2820_board em2820_boards[] = { | |||
129 | .amux = 1, | 158 | .amux = 1, |
130 | }}, | 159 | }}, |
131 | }, | 160 | }, |
132 | { } /* Terminating entry */ | 161 | [EM2800_BOARD_TERRATEC_CINERGY_200] = { |
162 | .name = "Terratec Cinergy 200 USB", | ||
163 | .chip_id = 0x4, | ||
164 | .is_em2800 = 1, | ||
165 | .vchannels = 3, | ||
166 | .norm = VIDEO_MODE_PAL, | ||
167 | .tuner_type = TUNER_LG_PAL_NEW_TAPC, | ||
168 | .tda9887_conf = TDA9887_PRESENT, | ||
169 | .has_tuner = 1, | ||
170 | .decoder = EM2820_SAA7113, | ||
171 | .input = {{ | ||
172 | .type = EM2820_VMUX_TELEVISION, | ||
173 | .vmux = 2, | ||
174 | .amux = 0, | ||
175 | },{ | ||
176 | .type = EM2820_VMUX_COMPOSITE1, | ||
177 | .vmux = 0, | ||
178 | .amux = 1, | ||
179 | },{ | ||
180 | .type = EM2820_VMUX_SVIDEO, | ||
181 | .vmux = 9, | ||
182 | .amux = 1, | ||
183 | }}, | ||
184 | }, | ||
185 | [EM2800_BOARD_LEADTEK_WINFAST_USBII] = { | ||
186 | .name = "Leadtek Winfast USB II", | ||
187 | .chip_id = 0x2, | ||
188 | .is_em2800 = 1, | ||
189 | .vchannels = 3, | ||
190 | .norm = VIDEO_MODE_PAL, | ||
191 | .tuner_type = TUNER_LG_PAL_NEW_TAPC, | ||
192 | .tda9887_conf = TDA9887_PRESENT, | ||
193 | .has_tuner = 1, | ||
194 | .decoder = EM2820_SAA7113, | ||
195 | .input = {{ | ||
196 | .type = EM2820_VMUX_TELEVISION, | ||
197 | .vmux = 2, | ||
198 | .amux = 0, | ||
199 | },{ | ||
200 | .type = EM2820_VMUX_COMPOSITE1, | ||
201 | .vmux = 0, | ||
202 | .amux = 1, | ||
203 | },{ | ||
204 | .type = EM2820_VMUX_SVIDEO, | ||
205 | .vmux = 9, | ||
206 | .amux = 1, | ||
207 | }}, | ||
208 | }, | ||
209 | [EM2800_BOARD_KWORLD_USB2800] = { | ||
210 | .name = "Kworld USB2800", | ||
211 | .chip_id = 0x7, | ||
212 | .is_em2800 = 1, | ||
213 | .vchannels = 3, | ||
214 | .norm = VIDEO_MODE_PAL, | ||
215 | .tuner_type = TUNER_PHILIPS_ATSC, | ||
216 | .tda9887_conf = TDA9887_PRESENT, | ||
217 | .has_tuner = 1, | ||
218 | .decoder = EM2820_SAA7113, | ||
219 | .input = {{ | ||
220 | .type = EM2820_VMUX_TELEVISION, | ||
221 | .vmux = 2, | ||
222 | .amux = 0, | ||
223 | },{ | ||
224 | .type = EM2820_VMUX_COMPOSITE1, | ||
225 | .vmux = 0, | ||
226 | .amux = 1, | ||
227 | },{ | ||
228 | .type = EM2820_VMUX_SVIDEO, | ||
229 | .vmux = 9, | ||
230 | .amux = 1, | ||
231 | }}, | ||
232 | }, | ||
133 | }; | 233 | }; |
234 | const unsigned int em2820_bcount = ARRAY_SIZE(em2820_boards); | ||
134 | 235 | ||
135 | /* table of devices that work with this driver */ | 236 | /* table of devices that work with this driver */ |
136 | struct usb_device_id em2820_id_table [] = { | 237 | struct usb_device_id em2820_id_table [] = { |
137 | /* Terratec Cinerhy 200 USB: em2800 nor supported, at the moment */ | 238 | { USB_DEVICE(0xeb1a, 0x2800), .driver_info = EM2800_BOARD_UNKNOWN }, |
138 | /* { USB_DEVICE(0xeb1a, 0x2800), .driver_info = EM2800_BOARD_TERRATEC_CINERGY_200 }, */ | 239 | { USB_DEVICE(0xeb1a, 0x2820), .driver_info = EM2820_BOARD_UNKNOWN }, |
139 | { USB_DEVICE(0x0ccd, 0x0036), .driver_info = EM2820_BOARD_TERRATEC_CINERGY_250 }, | 240 | { USB_DEVICE(0x0ccd, 0x0036), .driver_info = EM2820_BOARD_TERRATEC_CINERGY_250 }, |
140 | { USB_DEVICE(0x2304, 0x0208), .driver_info = EM2820_BOARD_PINNACLE_USB_2 }, | 241 | { USB_DEVICE(0x2304, 0x0208), .driver_info = EM2820_BOARD_PINNACLE_USB_2 }, |
141 | { USB_DEVICE(0x2040, 0x4200), .driver_info = EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 }, | 242 | { USB_DEVICE(0x2040, 0x4200), .driver_info = EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 }, |
142 | { USB_DEVICE(0xeb1a, 0x2820), .driver_info = EM2820_BOARD_MSI_VOX_USB_2 }, | ||
143 | { }, | 243 | { }, |
144 | }; | 244 | }; |
145 | 245 | ||
@@ -163,6 +263,7 @@ void em2820_card_setup(struct em2820 *dev) | |||
163 | } | 263 | } |
164 | 264 | ||
165 | EXPORT_SYMBOL(em2820_boards); | 265 | EXPORT_SYMBOL(em2820_boards); |
266 | EXPORT_SYMBOL(em2820_bcount); | ||
166 | EXPORT_SYMBOL(em2820_id_table); | 267 | EXPORT_SYMBOL(em2820_id_table); |
167 | 268 | ||
168 | MODULE_DEVICE_TABLE (usb, em2820_id_table); | 269 | MODULE_DEVICE_TABLE (usb, em2820_id_table); |
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index e187422f6d6d..594e6d681ba4 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | em2820-core.c - driver for Empia EM2820/2840 USB video capture devices | 2 | em2820-core.c - driver for Empia EM2800/EM2820/2840 USB video capture devices |
3 | 3 | ||
4 | Copyright (C) 2005 Markus Rechberger <mrechberger@gmail.com> | 4 | Copyright (C) 2005 Markus Rechberger <mrechberger@gmail.com> |
5 | Ludovico Cavedon <cavedon@sssup.it> | 5 | Ludovico Cavedon <cavedon@sssup.it> |
@@ -562,6 +562,11 @@ static inline void em2820_isoc_video_copy(struct em2820 *dev, | |||
562 | void *fieldstart, *startwrite, *startread; | 562 | void *fieldstart, *startwrite, *startread; |
563 | int linesdone, currlinedone, offset, lencopy,remain; | 563 | int linesdone, currlinedone, offset, lencopy,remain; |
564 | 564 | ||
565 | if(dev->frame_size != (*f)->buf.length){ | ||
566 | em2820_err("frame_size %i and buf.length %i are different!!!\n",dev->frame_size,(*f)->buf.length); | ||
567 | return; | ||
568 | } | ||
569 | |||
565 | if ((*f)->fieldbytesused + len > dev->field_size) | 570 | if ((*f)->fieldbytesused + len > dev->field_size) |
566 | len =dev->field_size - (*f)->fieldbytesused; | 571 | len =dev->field_size - (*f)->fieldbytesused; |
567 | remain = len; | 572 | remain = len; |
@@ -780,6 +785,11 @@ int em2820_set_alternate(struct em2820 *dev) | |||
780 | dev->alt = alt; | 785 | dev->alt = alt; |
781 | if (dev->alt == 0) { | 786 | if (dev->alt == 0) { |
782 | int i; | 787 | int i; |
788 | if(dev->is_em2800){ /* always use the max packet size for em2800 based devices */ | ||
789 | for(i=0;i< EM2820_MAX_ALT; i++) | ||
790 | if(dev->alt_max_pkt_size[i]>dev->alt_max_pkt_size[dev->alt]) | ||
791 | dev->alt=i; | ||
792 | }else{ | ||
783 | unsigned int min_pkt_size = dev->field_size / 137; /* FIXME: empiric magic number */ | 793 | unsigned int min_pkt_size = dev->field_size / 137; /* FIXME: empiric magic number */ |
784 | em2820_coredbg("minimum isoc packet size: %u", min_pkt_size); | 794 | em2820_coredbg("minimum isoc packet size: %u", min_pkt_size); |
785 | dev->alt = 7; | 795 | dev->alt = 7; |
@@ -788,6 +798,7 @@ int em2820_set_alternate(struct em2820 *dev) | |||
788 | dev->alt = i; | 798 | dev->alt = i; |
789 | break; | 799 | break; |
790 | } | 800 | } |
801 | } | ||
791 | } | 802 | } |
792 | 803 | ||
793 | if (dev->alt != prev_alt) { | 804 | if (dev->alt != prev_alt) { |
diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index 3065ddb4b368..b7360d579a8a 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | em2820-i2c.c - driver for Empia EM2820/2840 USB video capture devices | 2 | em2820-i2c.c - driver for Empia EM2800/EM2820/2840 USB video capture devices |
3 | 3 | ||
4 | Copyright (C) 2005 Markus Rechberger <mrechberger@gmail.com> | 4 | Copyright (C) 2005 Markus Rechberger <mrechberger@gmail.com> |
5 | Ludovico Cavedon <cavedon@sssup.it> | 5 | Ludovico Cavedon <cavedon@sssup.it> |
@@ -29,11 +29,6 @@ | |||
29 | #include <media/tuner.h> | 29 | #include <media/tuner.h> |
30 | #include <linux/video_decoder.h> | 30 | #include <linux/video_decoder.h> |
31 | 31 | ||
32 | /* To be moved to compat.h */ | ||
33 | #if !defined(I2C_HW_B_EM2820) | ||
34 | #define I2C_HW_B_EM2820 0x99 | ||
35 | #endif | ||
36 | |||
37 | #include "em2820.h" | 32 | #include "em2820.h" |
38 | 33 | ||
39 | /* ----------------------------------------------------------- */ | 34 | /* ----------------------------------------------------------- */ |
@@ -56,11 +51,132 @@ MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); | |||
56 | printk(fmt , ##args); } while (0) | 51 | printk(fmt , ##args); } while (0) |
57 | 52 | ||
58 | /* | 53 | /* |
59 | * i2c_send_bytes() | 54 | * em2800_i2c_send_max4() |
55 | * send up to 4 bytes to the i2c device | ||
56 | */ | ||
57 | static int em2800_i2c_send_max4(struct em2820 *dev, unsigned char addr, | ||
58 | char *buf, int len) | ||
59 | { | ||
60 | int ret; | ||
61 | int write_timeout; | ||
62 | unsigned char b2[6]; | ||
63 | BUG_ON(len < 1 || len > 4); | ||
64 | b2[5] = 0x80 + len - 1; | ||
65 | b2[4] = addr; | ||
66 | b2[3] = buf[0]; | ||
67 | if (len > 1) | ||
68 | b2[2] = buf[1]; | ||
69 | if (len > 2) | ||
70 | b2[1] = buf[2]; | ||
71 | if (len > 3) | ||
72 | b2[0] = buf[3]; | ||
73 | |||
74 | ret = dev->em2820_write_regs(dev, 4 - len, &b2[4 - len], 2 + len); | ||
75 | if (ret != 2 + len) { | ||
76 | em2820_warn("writting to i2c device failed (error=%i)\n", ret); | ||
77 | return -EIO; | ||
78 | } | ||
79 | for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0; | ||
80 | write_timeout -= 5) { | ||
81 | ret = dev->em2820_read_reg(dev, 0x05); | ||
82 | if (ret == 0x80 + len - 1) | ||
83 | return len; | ||
84 | mdelay(5); | ||
85 | } | ||
86 | em2820_warn("i2c write timed out\n"); | ||
87 | return -EIO; | ||
88 | } | ||
89 | |||
90 | /* | ||
91 | * em2800_i2c_send_bytes() | ||
92 | */ | ||
93 | static int em2800_i2c_send_bytes(void *data, unsigned char addr, char *buf, | ||
94 | short len) | ||
95 | { | ||
96 | char *bufPtr = buf; | ||
97 | int ret; | ||
98 | int wrcount = 0; | ||
99 | int count; | ||
100 | int maxLen = 4; | ||
101 | struct em2820 *dev = (struct em2820 *)data; | ||
102 | while (len > 0) { | ||
103 | count = (len > maxLen) ? maxLen : len; | ||
104 | ret = em2800_i2c_send_max4(dev, addr, bufPtr, count); | ||
105 | if (ret > 0) { | ||
106 | len -= count; | ||
107 | bufPtr += count; | ||
108 | wrcount += count; | ||
109 | } else | ||
110 | return (ret < 0) ? ret : -EFAULT; | ||
111 | } | ||
112 | return wrcount; | ||
113 | } | ||
114 | |||
115 | /* | ||
116 | * em2800_i2c_check_for_device() | ||
117 | * check if there is a i2c_device at the supplied address | ||
118 | */ | ||
119 | static int em2800_i2c_check_for_device(struct em2820 *dev, unsigned char addr) | ||
120 | { | ||
121 | char msg; | ||
122 | int ret; | ||
123 | int write_timeout; | ||
124 | msg = addr; | ||
125 | ret = dev->em2820_write_regs(dev, 0x04, &msg, 1); | ||
126 | if (ret < 0) { | ||
127 | em2820_warn("setting i2c device address failed (error=%i)\n", | ||
128 | ret); | ||
129 | return ret; | ||
130 | } | ||
131 | msg = 0x84; | ||
132 | ret = dev->em2820_write_regs(dev, 0x05, &msg, 1); | ||
133 | if (ret < 0) { | ||
134 | em2820_warn("preparing i2c read failed (error=%i)\n", ret); | ||
135 | return ret; | ||
136 | } | ||
137 | for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0; | ||
138 | write_timeout -= 5) { | ||
139 | unsigned msg = dev->em2820_read_reg(dev, 0x5); | ||
140 | if (msg == 0x94) | ||
141 | return -ENODEV; | ||
142 | else if (msg == 0x84) | ||
143 | return 0; | ||
144 | mdelay(5); | ||
145 | } | ||
146 | return -ENODEV; | ||
147 | } | ||
148 | |||
149 | /* | ||
150 | * em2800_i2c_recv_bytes() | ||
151 | * read from the i2c device | ||
152 | */ | ||
153 | static int em2800_i2c_recv_bytes(struct em2820 *dev, unsigned char addr, | ||
154 | char *buf, int len) | ||
155 | { | ||
156 | int ret; | ||
157 | /* check for the device and set i2c read address */ | ||
158 | ret = em2800_i2c_check_for_device(dev, addr); | ||
159 | if (ret) { | ||
160 | em2820_warn | ||
161 | ("preparing read at i2c address 0x%x failed (error=%i)\n", | ||
162 | addr, ret); | ||
163 | return ret; | ||
164 | } | ||
165 | ret = dev->em2820_read_reg_req_len(dev, 0x0, 0x3, buf, len); | ||
166 | if (ret < 0) { | ||
167 | em2820_warn("reading from i2c device at 0x%x failed (error=%i)", | ||
168 | addr, ret); | ||
169 | return ret; | ||
170 | } | ||
171 | return ret; | ||
172 | } | ||
173 | |||
174 | /* | ||
175 | * em2820_i2c_send_bytes() | ||
60 | * untested for more than 4 bytes | 176 | * untested for more than 4 bytes |
61 | */ | 177 | */ |
62 | static int i2c_send_bytes(void *data, unsigned char addr, char *buf, short len, | 178 | static int em2820_i2c_send_bytes(void *data, unsigned char addr, char *buf, |
63 | int stop) | 179 | short len, int stop) |
64 | { | 180 | { |
65 | int wrcount = 0; | 181 | int wrcount = 0; |
66 | struct em2820 *dev = (struct em2820 *)data; | 182 | struct em2820 *dev = (struct em2820 *)data; |
@@ -71,11 +187,11 @@ static int i2c_send_bytes(void *data, unsigned char addr, char *buf, short len, | |||
71 | } | 187 | } |
72 | 188 | ||
73 | /* | 189 | /* |
74 | * i2c_recv_byte() | 190 | * em2820_i2c_recv_bytes() |
75 | * read a byte from the i2c device | 191 | * read a byte from the i2c device |
76 | */ | 192 | */ |
77 | static int i2c_recv_bytes(struct em2820 *dev, unsigned char addr, char *buf, | 193 | static int em2820_i2c_recv_bytes(struct em2820 *dev, unsigned char addr, |
78 | int len) | 194 | char *buf, int len) |
79 | { | 195 | { |
80 | int ret; | 196 | int ret; |
81 | ret = dev->em2820_read_reg_req_len(dev, 2, addr, buf, len); | 197 | ret = dev->em2820_read_reg_req_len(dev, 2, addr, buf, len); |
@@ -89,10 +205,10 @@ static int i2c_recv_bytes(struct em2820 *dev, unsigned char addr, char *buf, | |||
89 | } | 205 | } |
90 | 206 | ||
91 | /* | 207 | /* |
92 | * i2c_check_for_device() | 208 | * em2820_i2c_check_for_device() |
93 | * check if there is a i2c_device at the supplied address | 209 | * check if there is a i2c_device at the supplied address |
94 | */ | 210 | */ |
95 | static int i2c_check_for_device(struct em2820 *dev, unsigned char addr) | 211 | static int em2820_i2c_check_for_device(struct em2820 *dev, unsigned char addr) |
96 | { | 212 | { |
97 | char msg; | 213 | char msg; |
98 | int ret; | 214 | int ret; |
@@ -126,18 +242,25 @@ static int em2820_i2c_xfer(struct i2c_adapter *i2c_adap, | |||
126 | (msgs[i].flags & I2C_M_RD) ? "read" : "write", | 242 | (msgs[i].flags & I2C_M_RD) ? "read" : "write", |
127 | i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len); | 243 | i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len); |
128 | if (!msgs[i].len) { /* no len: check only for device presence */ | 244 | if (!msgs[i].len) { /* no len: check only for device presence */ |
129 | rc = i2c_check_for_device(dev, addr); | 245 | if (dev->is_em2800) |
246 | rc = em2800_i2c_check_for_device(dev, addr); | ||
247 | else | ||
248 | rc = em2820_i2c_check_for_device(dev, addr); | ||
130 | if (rc < 0) { | 249 | if (rc < 0) { |
131 | dprintk2(" no device\n"); | 250 | dprintk2(" no device\n"); |
132 | return rc; | 251 | return rc; |
133 | } | 252 | } |
134 | 253 | ||
135 | } | 254 | } else if (msgs[i].flags & I2C_M_RD) { |
136 | if (msgs[i].flags & I2C_M_RD) { | ||
137 | /* read bytes */ | 255 | /* read bytes */ |
138 | 256 | if (dev->is_em2800) | |
139 | rc = i2c_recv_bytes(dev, addr, msgs[i].buf, | 257 | rc = em2800_i2c_recv_bytes(dev, addr, |
140 | msgs[i].len); | 258 | msgs[i].buf, |
259 | msgs[i].len); | ||
260 | else | ||
261 | rc = em2820_i2c_recv_bytes(dev, addr, | ||
262 | msgs[i].buf, | ||
263 | msgs[i].len); | ||
141 | if (i2c_debug) { | 264 | if (i2c_debug) { |
142 | for (byte = 0; byte < msgs[i].len; byte++) { | 265 | for (byte = 0; byte < msgs[i].len; byte++) { |
143 | printk(" %02x", msgs[i].buf[byte]); | 266 | printk(" %02x", msgs[i].buf[byte]); |
@@ -149,8 +272,15 @@ static int em2820_i2c_xfer(struct i2c_adapter *i2c_adap, | |||
149 | for (byte = 0; byte < msgs[i].len; byte++) | 272 | for (byte = 0; byte < msgs[i].len; byte++) |
150 | printk(" %02x", msgs[i].buf[byte]); | 273 | printk(" %02x", msgs[i].buf[byte]); |
151 | } | 274 | } |
152 | rc = i2c_send_bytes(dev, addr, msgs[i].buf, msgs[i].len, | 275 | if (dev->is_em2800) |
153 | i == num - 1); | 276 | rc = em2800_i2c_send_bytes(dev, addr, |
277 | msgs[i].buf, | ||
278 | msgs[i].len); | ||
279 | else | ||
280 | rc = em2820_i2c_send_bytes(dev, addr, | ||
281 | msgs[i].buf, | ||
282 | msgs[i].len, | ||
283 | i == num - 1); | ||
154 | if (rc < 0) | 284 | if (rc < 0) |
155 | goto err; | 285 | goto err; |
156 | } | 286 | } |
@@ -171,6 +301,12 @@ static int em2820_i2c_eeprom(struct em2820 *dev, unsigned char *eedata, int len) | |||
171 | int i, err, size = len, block; | 301 | int i, err, size = len, block; |
172 | 302 | ||
173 | dev->i2c_client.addr = 0xa0 >> 1; | 303 | dev->i2c_client.addr = 0xa0 >> 1; |
304 | |||
305 | /* Check if board has eeprom */ | ||
306 | err = i2c_master_recv(&dev->i2c_client, &buf, 0); | ||
307 | if (err < 0) | ||
308 | return -1; | ||
309 | |||
174 | buf = 0; | 310 | buf = 0; |
175 | if (1 != (err = i2c_master_send(&dev->i2c_client, &buf, 1))) { | 311 | if (1 != (err = i2c_master_send(&dev->i2c_client, &buf, 1))) { |
176 | printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n", | 312 | printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n", |
@@ -389,7 +525,7 @@ static void do_i2c_scan(char *name, struct i2c_client *c) | |||
389 | rc = i2c_master_recv(c, &buf, 0); | 525 | rc = i2c_master_recv(c, &buf, 0); |
390 | if (rc < 0) | 526 | if (rc < 0) |
391 | continue; | 527 | continue; |
392 | printk(KERN_INFO "%s: found device @ 0x%x [%s]", name, | 528 | printk(KERN_INFO "%s: found i2c device @ 0x%x [%s]\n", name, |
393 | i << 1, i2c_devs[i] ? i2c_devs[i] : "???"); | 529 | i << 1, i2c_devs[i] ? i2c_devs[i] : "???"); |
394 | } | 530 | } |
395 | } | 531 | } |
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 7e4114ea15f9..d3a959b9ee64 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | em2820-video.c - driver for Empia EM2820/2840 USB video capture devices | 2 | em2820-video.c - driver for Empia EM2800/EM2820/2840 USB video capture devices |
3 | 3 | ||
4 | Copyright (C) 2005 Markus Rechberger <mrechberger@gmail.com> | 4 | Copyright (C) 2005 Markus Rechberger <mrechberger@gmail.com> |
5 | Ludovico Cavedon <cavedon@sssup.it> | 5 | Ludovico Cavedon <cavedon@sssup.it> |
@@ -50,6 +50,11 @@ MODULE_AUTHOR(DRIVER_AUTHOR); | |||
50 | MODULE_DESCRIPTION(DRIVER_DESC); | 50 | MODULE_DESCRIPTION(DRIVER_DESC); |
51 | MODULE_LICENSE("GPL"); | 51 | MODULE_LICENSE("GPL"); |
52 | 52 | ||
53 | static unsigned int card[] = {[0 ... (EM2820_MAXBOARDS - 1)] = UNSET }; | ||
54 | |||
55 | module_param_array(card, int, NULL, 0444); | ||
56 | MODULE_PARM_DESC(card,"card type"); | ||
57 | |||
53 | static int tuner = -1; | 58 | static int tuner = -1; |
54 | module_param(tuner, int, 0444); | 59 | module_param(tuner, int, 0444); |
55 | MODULE_PARM_DESC(tuner, "tuner type"); | 60 | MODULE_PARM_DESC(tuner, "tuner type"); |
@@ -1081,7 +1086,7 @@ static int em2820_do_ioctl(struct inode *inode, struct file *filp, | |||
1081 | struct v4l2_cropcap *cc = arg; | 1086 | struct v4l2_cropcap *cc = arg; |
1082 | 1087 | ||
1083 | if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 1088 | if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1084 | return EINVAL; | 1089 | return -EINVAL; |
1085 | cc->bounds.left = 0; | 1090 | cc->bounds.left = 0; |
1086 | cc->bounds.top = 0; | 1091 | cc->bounds.top = 0; |
1087 | cc->bounds.width = dev->width; | 1092 | cc->bounds.width = dev->width; |
@@ -1520,21 +1525,12 @@ static struct file_operations em2820_v4l_fops = { | |||
1520 | static int em2820_init_dev(struct em2820 **devhandle, struct usb_device *udev, | 1525 | static int em2820_init_dev(struct em2820 **devhandle, struct usb_device *udev, |
1521 | int minor, int model) | 1526 | int minor, int model) |
1522 | { | 1527 | { |
1523 | struct em2820 *dev; | 1528 | struct em2820 *dev = *devhandle; |
1524 | int retval = -ENOMEM; | 1529 | int retval = -ENOMEM; |
1525 | int errCode, i; | 1530 | int errCode, i; |
1526 | unsigned int maxh, maxw; | 1531 | unsigned int maxh, maxw; |
1527 | struct usb_interface *uif; | 1532 | struct usb_interface *uif; |
1528 | 1533 | ||
1529 | /* allocate memory for our device state and initialize it */ | ||
1530 | dev = kmalloc(sizeof(*dev), GFP_KERNEL); | ||
1531 | if (dev == NULL) { | ||
1532 | em2820_err(DRIVER_NAME ": out of memory!\n"); | ||
1533 | return -ENOMEM; | ||
1534 | } | ||
1535 | memset(dev, 0x00, sizeof(*dev)); | ||
1536 | |||
1537 | snprintf(dev->name, 29, "em2820 #%d", minor); | ||
1538 | dev->udev = udev; | 1534 | dev->udev = udev; |
1539 | dev->model = model; | 1535 | dev->model = model; |
1540 | init_MUTEX(&dev->lock); | 1536 | init_MUTEX(&dev->lock); |
@@ -1545,6 +1541,7 @@ static int em2820_init_dev(struct em2820 **devhandle, struct usb_device *udev, | |||
1545 | dev->em2820_read_reg_req_len = em2820_read_reg_req_len; | 1541 | dev->em2820_read_reg_req_len = em2820_read_reg_req_len; |
1546 | dev->em2820_write_regs_req = em2820_write_regs_req; | 1542 | dev->em2820_write_regs_req = em2820_write_regs_req; |
1547 | dev->em2820_read_reg_req = em2820_read_reg_req; | 1543 | dev->em2820_read_reg_req = em2820_read_reg_req; |
1544 | dev->is_em2800 = em2820_boards[model].is_em2800; | ||
1548 | dev->has_tuner = em2820_boards[model].has_tuner; | 1545 | dev->has_tuner = em2820_boards[model].has_tuner; |
1549 | dev->has_msp34xx = em2820_boards[model].has_msp34xx; | 1546 | dev->has_msp34xx = em2820_boards[model].has_msp34xx; |
1550 | dev->tda9887_conf = em2820_boards[model].tda9887_conf; | 1547 | dev->tda9887_conf = em2820_boards[model].tda9887_conf; |
@@ -1595,7 +1592,7 @@ static int em2820_init_dev(struct em2820 **devhandle, struct usb_device *udev, | |||
1595 | /* compute alternate max packet sizes */ | 1592 | /* compute alternate max packet sizes */ |
1596 | uif = dev->udev->actconfig->interface[0]; | 1593 | uif = dev->udev->actconfig->interface[0]; |
1597 | dev->alt_max_pkt_size[0] = 0; | 1594 | dev->alt_max_pkt_size[0] = 0; |
1598 | for (i = 1; i <= EM2820_MAX_ALT; i++) { | 1595 | for (i = 1; i <= EM2820_MAX_ALT && i < uif->num_altsetting ; i++) { |
1599 | u16 tmp = | 1596 | u16 tmp = |
1600 | le16_to_cpu(uif->altsetting[i].endpoint[1].desc. | 1597 | le16_to_cpu(uif->altsetting[i].endpoint[1].desc. |
1601 | wMaxPacketSize); | 1598 | wMaxPacketSize); |
@@ -1688,7 +1685,6 @@ static int em2820_init_dev(struct em2820 **devhandle, struct usb_device *udev, | |||
1688 | em2820_info("V4L2 device registered as /dev/video%d\n", | 1685 | em2820_info("V4L2 device registered as /dev/video%d\n", |
1689 | dev->vdev->minor); | 1686 | dev->vdev->minor); |
1690 | 1687 | ||
1691 | *devhandle = dev; | ||
1692 | return 0; | 1688 | return 0; |
1693 | } | 1689 | } |
1694 | 1690 | ||
@@ -1703,27 +1699,68 @@ static int em2820_usb_probe(struct usb_interface *interface, | |||
1703 | struct usb_device *udev; | 1699 | struct usb_device *udev; |
1704 | struct em2820 *dev = NULL; | 1700 | struct em2820 *dev = NULL; |
1705 | int retval = -ENODEV; | 1701 | int retval = -ENODEV; |
1702 | int model,i,nr; | ||
1706 | 1703 | ||
1707 | udev = usb_get_dev(interface_to_usbdev(interface)); | 1704 | udev = usb_get_dev(interface_to_usbdev(interface)); |
1708 | endpoint = &interface->cur_altsetting->endpoint[1].desc; | 1705 | endpoint = &interface->cur_altsetting->endpoint[1].desc; |
1709 | 1706 | ||
1707 | /* Don't register audio interfaces */ | ||
1708 | if (interface->altsetting[1].desc.bInterfaceClass == USB_CLASS_AUDIO) | ||
1709 | return -ENODEV; | ||
1710 | |||
1710 | /* check if the the device has the iso in endpoint at the correct place */ | 1711 | /* check if the the device has the iso in endpoint at the correct place */ |
1711 | if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != | 1712 | if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != |
1712 | USB_ENDPOINT_XFER_ISOC) { | 1713 | USB_ENDPOINT_XFER_ISOC) { |
1713 | /* em2820_err(DRIVER_NAME " probing error: endpoint is non-ISO endpoint!\n"); */ | 1714 | em2820_err(DRIVER_NAME " probing error: endpoint is non-ISO endpoint!\n"); |
1714 | return -ENODEV; | 1715 | return -ENODEV; |
1715 | } | 1716 | } |
1716 | if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) { | 1717 | if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) { |
1717 | /* em2820_err(DRIVER_NAME " probing error: endpoint is ISO OUT endpoint!\n"); */ | 1718 | em2820_err(DRIVER_NAME " probing error: endpoint is ISO OUT endpoint!\n"); |
1718 | return -ENODEV; | 1719 | return -ENODEV; |
1719 | } | 1720 | } |
1720 | 1721 | ||
1722 | model=id->driver_info; | ||
1723 | nr=interface->minor; | ||
1724 | |||
1725 | if (nr>EM2820_MAXBOARDS) { | ||
1726 | printk ("em2820: Supports only %i em28xx boards.\n",EM2820_MAXBOARDS); | ||
1727 | return -ENOMEM; | ||
1728 | } | ||
1729 | |||
1730 | /* allocate memory for our device state and initialize it */ | ||
1731 | dev = kmalloc(sizeof(*dev), GFP_KERNEL); | ||
1732 | if (dev == NULL) { | ||
1733 | em2820_err(DRIVER_NAME ": out of memory!\n"); | ||
1734 | return -ENOMEM; | ||
1735 | } | ||
1736 | memset(dev, 0, sizeof(*dev)); | ||
1737 | |||
1738 | snprintf(dev->name, 29, "em2820 #%d", nr); | ||
1739 | |||
1740 | if ((card[nr]>=0)&&(card[nr]<em2820_bcount)) | ||
1741 | model=card[nr]; | ||
1742 | |||
1743 | if ((model==EM2800_BOARD_UNKNOWN)||(model==EM2820_BOARD_UNKNOWN)) { | ||
1744 | printk( "%s: Your board has no eeprom inside it and thus can't\n" | ||
1745 | "%s: be autodetected. Please pass card=<n> insmod option to\n" | ||
1746 | "%s: workaround that. Redirect complaints to the vendor of\n" | ||
1747 | "%s: the TV card. Best regards,\n" | ||
1748 | "%s: -- tux\n", | ||
1749 | dev->name,dev->name,dev->name,dev->name,dev->name); | ||
1750 | printk("%s: Here is a list of valid choices for the card=<n> insmod option:\n", | ||
1751 | dev->name); | ||
1752 | for (i = 0; i < em2820_bcount; i++) { | ||
1753 | printk("%s: card=%d -> %s\n", | ||
1754 | dev->name, i, em2820_boards[i].name); | ||
1755 | } | ||
1756 | } | ||
1757 | |||
1721 | /* allocate device struct */ | 1758 | /* allocate device struct */ |
1722 | retval = em2820_init_dev(&dev, udev, interface->minor, id->driver_info); | 1759 | retval = em2820_init_dev(&dev, udev, nr, model); |
1723 | if (retval) | 1760 | if (retval) |
1724 | return retval; | 1761 | return retval; |
1725 | 1762 | ||
1726 | em2820_info("Found %s\n", em2820_boards[id->driver_info].name); | 1763 | em2820_info("Found %s\n", em2820_boards[model].name); |
1727 | 1764 | ||
1728 | /* save our data pointer in this interface device */ | 1765 | /* save our data pointer in this interface device */ |
1729 | usb_set_intfdata(interface, dev); | 1766 | usb_set_intfdata(interface, dev); |
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 7779121a3dea..4115938a1731 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | em2820-cards.c - driver for Empia EM2820/2840 USB video capture devices | 2 | em2820-cards.c - driver for Empia EM2800/EM2820/2840 USB video capture devices |
3 | 3 | ||
4 | Copyright (C) 2005 Markus Rechberger <mrechberger@gmail.com> | 4 | Copyright (C) 2005 Markus Rechberger <mrechberger@gmail.com> |
5 | Ludovico Cavedon <cavedon@sssup.it> | 5 | Ludovico Cavedon <cavedon@sssup.it> |
@@ -28,6 +28,23 @@ | |||
28 | #include <linux/videodev.h> | 28 | #include <linux/videodev.h> |
29 | #include <linux/i2c.h> | 29 | #include <linux/i2c.h> |
30 | 30 | ||
31 | /* Boards supported by driver */ | ||
32 | |||
33 | #define EM2800_BOARD_UNKNOWN 0 | ||
34 | #define EM2820_BOARD_UNKNOWN 1 | ||
35 | #define EM2820_BOARD_TERRATEC_CINERGY_250 2 | ||
36 | #define EM2820_BOARD_PINNACLE_USB_2 3 | ||
37 | #define EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 4 | ||
38 | #define EM2820_BOARD_MSI_VOX_USB_2 5 | ||
39 | #define EM2800_BOARD_TERRATEC_CINERGY_200 6 | ||
40 | #define EM2800_BOARD_LEADTEK_WINFAST_USBII 7 | ||
41 | #define EM2800_BOARD_KWORLD_USB2800 8 | ||
42 | |||
43 | #define UNSET -1 | ||
44 | |||
45 | /* maximum number of em28xx boards */ | ||
46 | #define EM2820_MAXBOARDS 1 /*FIXME: should be bigger */ | ||
47 | |||
31 | /* maximum number of frames that can be queued */ | 48 | /* maximum number of frames that can be queued */ |
32 | #define EM2820_NUM_FRAMES 5 | 49 | #define EM2820_NUM_FRAMES 5 |
33 | /* number of frames that get used for v4l2_read() */ | 50 | /* number of frames that get used for v4l2_read() */ |
@@ -79,6 +96,9 @@ | |||
79 | /* time to wait when stopping the isoc transfer */ | 96 | /* time to wait when stopping the isoc transfer */ |
80 | #define EM2820_URB_TIMEOUT msecs_to_jiffies(EM2820_NUM_BUFS * EM2820_NUM_PACKETS) | 97 | #define EM2820_URB_TIMEOUT msecs_to_jiffies(EM2820_NUM_BUFS * EM2820_NUM_PACKETS) |
81 | 98 | ||
99 | /* time in msecs to wait for i2c writes to finish */ | ||
100 | #define EM2800_I2C_WRITE_TIMEOUT 20 | ||
101 | |||
82 | /* the various frame states */ | 102 | /* the various frame states */ |
83 | enum em2820_frame_state { | 103 | enum em2820_frame_state { |
84 | F_UNUSED = 0, | 104 | F_UNUSED = 0, |
@@ -145,12 +165,13 @@ enum em2820_decoder { | |||
145 | 165 | ||
146 | struct em2820_board { | 166 | struct em2820_board { |
147 | char *name; | 167 | char *name; |
148 | 168 | unsigned char chip_id; | |
149 | int vchannels; | 169 | int vchannels; |
150 | int norm; | 170 | int norm; |
151 | int tuner_type; | 171 | int tuner_type; |
152 | 172 | ||
153 | /* i2c flags */ | 173 | /* i2c flags */ |
174 | unsigned int is_em2800; | ||
154 | unsigned int tda9887_conf; | 175 | unsigned int tda9887_conf; |
155 | 176 | ||
156 | unsigned int has_tuner:1; | 177 | unsigned int has_tuner:1; |
@@ -195,6 +216,7 @@ struct em2820 { | |||
195 | /* generic device properties */ | 216 | /* generic device properties */ |
196 | char name[30]; /* name (including minor) of the device */ | 217 | char name[30]; /* name (including minor) of the device */ |
197 | int model; /* index in the device_data struct */ | 218 | int model; /* index in the device_data struct */ |
219 | unsigned int is_em2800; | ||
198 | int video_inputs; /* number of video inputs */ | 220 | int video_inputs; /* number of video inputs */ |
199 | unsigned int has_tuner:1; | 221 | unsigned int has_tuner:1; |
200 | unsigned int has_msp34xx:1; | 222 | unsigned int has_msp34xx:1; |
@@ -304,11 +326,14 @@ void em2820_uninit_isoc(struct em2820 *dev); | |||
304 | int em2820_set_alternate(struct em2820 *dev); | 326 | int em2820_set_alternate(struct em2820 *dev); |
305 | 327 | ||
306 | /* Provided by em2820-cards.c */ | 328 | /* Provided by em2820-cards.c */ |
329 | extern int em2800_variant_detect(struct usb_device* udev,int model); | ||
307 | extern void em2820_card_setup(struct em2820 *dev); | 330 | extern void em2820_card_setup(struct em2820 *dev); |
308 | extern struct em2820_board em2820_boards[]; | 331 | extern struct em2820_board em2820_boards[]; |
309 | extern struct usb_device_id em2820_id_table[]; | 332 | extern struct usb_device_id em2820_id_table[]; |
333 | extern const unsigned int em2820_bcount; | ||
310 | 334 | ||
311 | /* em2820 registers */ | 335 | /* em2820 registers */ |
336 | #define CHIPID_REG 0x0a | ||
312 | #define USBSUSP_REG 0x0c /* */ | 337 | #define USBSUSP_REG 0x0c /* */ |
313 | 338 | ||
314 | #define AUDIOSRC_REG 0x0e | 339 | #define AUDIOSRC_REG 0x0e |