Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
425 | giacomo | 1 | /* |
2 | cm7326.c - v4l2 driver for pc104+ framegrabber module |
||
3 | http://www.rtdusa.com/PC104/UM/video/cm7326.htm |
||
4 | |||
5 | Copyright (C) 2002 Miguel Freitas |
||
6 | Copyright (C) 2003 Michael Hunold <michael@mihu.de> |
||
7 | |||
8 | Visit http://www.mihu.de/linux/saa7146 |
||
9 | for further details about this card. |
||
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 | #define DEBUG_VARIABLE debug |
||
27 | #include "drivers/saa7146_vv.h" |
||
28 | |||
29 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) |
||
30 | #define KBUILD_MODNAME cm7326 |
||
31 | #endif |
||
32 | |||
33 | /* module parameters */ |
||
34 | static int debug = 0; |
||
35 | MODULE_PARM(debug,"i"); |
||
36 | MODULE_PARM_DESC(debug, "debug verbosity"); |
||
37 | |||
38 | /* global variables */ |
||
39 | static int cm7326_num = 0; |
||
40 | |||
41 | /* we simply use the two video-interfaces (aka port a and port b) */ |
||
42 | #define CM7326_INPUTS 6 |
||
43 | static struct v4l2_input cm7326_inputs[CM7326_INPUTS] = |
||
44 | { |
||
45 | { 0, "VID1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, |
||
46 | { 1, "VID2", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, |
||
47 | { 2, "VID3", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, |
||
48 | { 3, "VID4", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, |
||
49 | { 4, "VID5", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, |
||
50 | { 5, "VID6", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, |
||
51 | }; |
||
52 | |||
53 | #define CM7326_AUDIOS 0 |
||
54 | |||
55 | /* you can demand that your extension get's called for any v4l2-ioctl. here, |
||
56 | we want to be called exclusively when the ioctls VIDIOC_S_INPUT and |
||
57 | VIDIOC_ENUMINPUT get called by an user application */ |
||
58 | static struct saa7146_extension_ioctls ioctls[] = |
||
59 | { |
||
60 | { VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE }, |
||
61 | { VIDIOC_G_INPUT, SAA7146_EXCLUSIVE }, |
||
62 | { VIDIOC_S_INPUT, SAA7146_EXCLUSIVE }, |
||
63 | { VIDIOC_S_STD, SAA7146_AFTER }, |
||
64 | { 0, 0 } |
||
65 | }; |
||
66 | |||
67 | struct cm7326 |
||
68 | { |
||
69 | struct video_device video_dev; |
||
70 | struct video_device vbi_dev; |
||
71 | |||
72 | struct i2c_adapter i2c_adapter; |
||
73 | |||
74 | int cur_input; /* current input */ |
||
75 | }; |
||
76 | |||
77 | static unsigned char saa7110_initseq[] = { |
||
78 | 0x4C, 0x3C, 0x0D, 0xEF, 0xBD, 0xF0, 0x00, 0x00, |
||
79 | 0xF8, 0xF8, 0x60, 0x60, 0x00, 0x06, 0x18, 0x90, |
||
80 | 0x00, 0x2C, 0x40, 0x46, 0x42, 0x1A, 0xFF, 0xDA, |
||
81 | 0xF0, 0x8B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||
82 | 0xD9, 0x17, 0x40, 0x41, 0x80, 0x41, 0x80, 0x4F, |
||
83 | 0xFE, 0x01, 0xCF, 0x0F, 0x03, 0x01, 0x81, 0x03, |
||
84 | 0x40, 0x75, 0x01, 0x8C, 0x03 |
||
85 | }; |
||
86 | |||
87 | static int saa7110_init(struct cm7326 *cm7326) |
||
88 | { |
||
89 | union i2c_smbus_data data; |
||
90 | int ret = 0; |
||
91 | int i = 0; |
||
92 | |||
93 | for (i = 0; i < sizeof(saa7110_initseq); i++) { |
||
94 | data.byte = saa7110_initseq[i]; |
||
95 | if (0 != i2c_smbus_xfer(&cm7326->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, i, I2C_SMBUS_BYTE_DATA, &data)) { |
||
96 | DEB_D(("failed for address 0x%02x\n", i)); |
||
97 | return -EFAULT; |
||
98 | } |
||
99 | } |
||
100 | |||
101 | data.byte = 0x16; |
||
102 | ret += i2c_smbus_xfer(&cm7326->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, 0x21, I2C_SMBUS_BYTE_DATA, &data); |
||
103 | |||
104 | /* fixme: unclear why there are two writes to register 0x0d here ... */ |
||
105 | data.byte = 0x04; |
||
106 | ret += i2c_smbus_xfer(&cm7326->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, 0x0D, I2C_SMBUS_BYTE_DATA, &data); |
||
107 | data.byte = 0x06; |
||
108 | ret += i2c_smbus_xfer(&cm7326->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, 0x0D, I2C_SMBUS_BYTE_DATA, &data); |
||
109 | |||
110 | if (0 != ret) { |
||
111 | DEB_S(("writing to saa7110 failed.\n")); |
||
112 | return -EFAULT; |
||
113 | } |
||
114 | |||
115 | return 0; |
||
116 | } |
||
117 | |||
118 | static const unsigned char input_modes[9][8] = { |
||
119 | /* mode 0 */ { 0x00, 0xD9, 0x17, 0x40, 0x03, 0x44, 0x75, 0x16 }, |
||
120 | /* mode 1 */ { 0x00, 0xD8, 0x17, 0x40, 0x03, 0x44, 0x75, 0x16 }, |
||
121 | /* mode 2 */ { 0x00, 0xBA, 0x07, 0x91, 0x03, 0x60, 0xB5, 0x05 }, |
||
122 | /* mode 3 */ { 0x00, 0xB8, 0x07, 0x91, 0x03, 0x60, 0xB5, 0x05 }, |
||
123 | /* mode 4 */ { 0x00, 0x7C, 0x07, 0xD2, 0x83, 0x60, 0xB5, 0x03 }, |
||
124 | /* mode 5 */ { 0x00, 0x78, 0x07, 0xD2, 0x83, 0x60, 0xB5, 0x03 }, |
||
125 | /* mode 6 */ { 0x80, 0x59, 0x17, 0x42, 0xA3, 0x44, 0x75, 0x12 }, |
||
126 | /* mode 7 */ { 0x80, 0x9A, 0x17, 0xB1, 0x13, 0x60, 0xB5, 0x14 }, |
||
127 | /* mode 8 */ { 0x80, 0x3C, 0x27, 0xC1, 0x23, 0x44, 0x75, 0x21 } |
||
128 | }; |
||
129 | |||
130 | static int saa7110_selmux(struct cm7326 *cm7326, int chan) |
||
131 | { |
||
132 | const unsigned char* ptr = input_modes[chan]; |
||
133 | union i2c_smbus_data data; |
||
134 | int ret = 0; |
||
135 | |||
136 | data.byte = ptr[0]; /* Luminance control */ |
||
137 | ret += i2c_smbus_xfer(&cm7326->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, 0x06, I2C_SMBUS_BYTE_DATA, &data); |
||
138 | |||
139 | data.byte = ptr[1]; /* Analog Control #1 */ |
||
140 | ret += i2c_smbus_xfer(&cm7326->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, 0x20, I2C_SMBUS_BYTE_DATA, &data); |
||
141 | |||
142 | data.byte = ptr[2]; /* Analog Control #2 */ |
||
143 | ret += i2c_smbus_xfer(&cm7326->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, 0x21, I2C_SMBUS_BYTE_DATA, &data); |
||
144 | |||
145 | data.byte = ptr[3]; /* Mixer Control #1 */ |
||
146 | ret += i2c_smbus_xfer(&cm7326->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, 0x22, I2C_SMBUS_BYTE_DATA, &data); |
||
147 | |||
148 | data.byte = ptr[4]; /* Mixer Control #2 */ |
||
149 | ret += i2c_smbus_xfer(&cm7326->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, 0x2c, I2C_SMBUS_BYTE_DATA, &data); |
||
150 | |||
151 | data.byte = ptr[5]; /* ADCs gain control */ |
||
152 | ret += i2c_smbus_xfer(&cm7326->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, 0x30, I2C_SMBUS_BYTE_DATA, &data); |
||
153 | |||
154 | data.byte = ptr[6]; /* Mixer Control #3 */ |
||
155 | ret += i2c_smbus_xfer(&cm7326->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, 0x31, I2C_SMBUS_BYTE_DATA, &data); |
||
156 | |||
157 | /* fixme: unclear why there are two writes analog control #2 above and here */ |
||
158 | data.byte = ptr[7]; /* Analog Control #2 */ |
||
159 | ret += i2c_smbus_xfer(&cm7326->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, 0x21, I2C_SMBUS_BYTE_DATA, &data); |
||
160 | |||
161 | if (0 != ret) { |
||
162 | DEB_S(("writing to saa7110 failed.\n")); |
||
163 | return -EFAULT; |
||
164 | } |
||
165 | |||
166 | return 0; |
||
167 | } |
||
168 | |||
169 | static int cm7326_probe(struct saa7146_dev *dev) |
||
170 | { |
||
171 | struct cm7326 *cm7326 = NULL; |
||
172 | union i2c_smbus_data data; |
||
173 | int err = 0; |
||
174 | |||
175 | DEB_D(("cm7326_probe called.\n")); |
||
176 | |||
177 | cm7326 = (struct cm7326*)kmalloc(sizeof(struct cm7326), GFP_KERNEL); |
||
178 | if( NULL == cm7326 ) { |
||
179 | printk("cm7326: cm7326_probe: not enough kernel memory.\n"); |
||
180 | return -ENOMEM; |
||
181 | } |
||
182 | memset(cm7326, 0x0, sizeof(struct cm7326)); |
||
183 | |||
184 | saa7146_i2c_adapter_prepare(dev, &cm7326->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480); |
||
185 | if(i2c_add_adapter(&cm7326->i2c_adapter) < 0) { |
||
186 | DEB_S(("cannot register i2c-device. skipping.\n")); |
||
187 | kfree(cm7326); |
||
188 | return -EFAULT; |
||
189 | } |
||
190 | |||
191 | /* have a look if a saa7110 is present */ |
||
192 | if (0 != (err = i2c_smbus_xfer(&cm7326->i2c_adapter, 0x4e, 0, I2C_SMBUS_READ, 0x00, I2C_SMBUS_BYTE_DATA, &data))) { |
||
193 | DEB_D(("cm7326_probe failed for this device.\n")); |
||
194 | i2c_del_adapter(&cm7326->i2c_adapter); |
||
195 | kfree(cm7326); |
||
196 | return -ENODEV; |
||
197 | } |
||
198 | |||
199 | DEB_D(("cm7326_probe succeeded for this device.\n")); |
||
200 | |||
201 | /* we store the pointer in our private data field */ |
||
202 | (struct cm7326*)dev->ext_priv = cm7326; |
||
203 | |||
204 | return 0; |
||
205 | } |
||
206 | |||
207 | /* bring hardware to a sane state. this has to be done, just in case someone |
||
208 | wants to capture from this device before it has been properly initialized. |
||
209 | the capture engine would badly fail, because no valid signal arrives on the |
||
210 | saa7146, thus leading to timeouts and stuff. */ |
||
211 | static int cm7326_init_done(struct saa7146_dev *dev) |
||
212 | { |
||
213 | struct cm7326* cm7326 = (struct cm7326*)dev->ext_priv; |
||
214 | int ret = 0; |
||
215 | |||
216 | DEB_D(("cm7326_init_done called.\n")); |
||
217 | |||
218 | /* initialize the helper ics to useful values */ |
||
219 | if (0 != (ret = saa7110_init(cm7326))) { |
||
220 | DEB_S(("initialization of saa7110 failed\n")); |
||
221 | return -EFAULT; |
||
222 | } |
||
223 | |||
224 | /* the rest for saa7146: you should definitely set some basic values |
||
225 | for the input-port handling of the saa7146. */ |
||
226 | |||
227 | /* some stuff is done via variables */ |
||
228 | saa7146_set_hps_source_and_sync(dev, SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A); |
||
229 | |||
230 | /* some stuff is done via direct write to the registers */ |
||
231 | |||
232 | /* this is ugly, but because of the fact that this is completely |
||
233 | hardware dependend, it should be done directly... */ |
||
234 | saa7146_write(dev, DD1_STREAM_B, 0x00000000); |
||
235 | saa7146_write(dev, DD1_INIT, 0x02000200); |
||
236 | saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26)); |
||
237 | |||
238 | return 0; |
||
239 | } |
||
240 | |||
241 | static struct saa7146_ext_vv vv_data; |
||
242 | |||
243 | /* this function only gets called when the probing was successful */ |
||
244 | static int cm7326_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info) |
||
245 | { |
||
246 | struct cm7326* cm7326 = (struct cm7326*)dev->ext_priv; |
||
247 | |||
248 | DEB_D(("cm7326_attach called.\n")); |
||
249 | |||
250 | /* checking for i2c-devices can be omitted here, because we |
||
251 | already did this in "cm7326_vl42_probe" */ |
||
252 | |||
253 | saa7146_vv_init(dev,&vv_data); |
||
254 | if( 0 != saa7146_register_device(&cm7326->video_dev, dev, "cm7326", VFL_TYPE_GRABBER)) { |
||
255 | ERR(("cannot register capture v4l2 device. skipping.\n")); |
||
256 | return -1; |
||
257 | } |
||
258 | |||
259 | printk("cm7326: found 'cm7326'-%d.\n",cm7326_num); |
||
260 | cm7326_num++; |
||
261 | |||
262 | /* the rest */ |
||
263 | cm7326->cur_input = 0; |
||
264 | return cm7326_init_done(dev); |
||
265 | } |
||
266 | |||
267 | static int cm7326_detach(struct saa7146_dev *dev) |
||
268 | { |
||
269 | struct cm7326* cm7326 = (struct cm7326*)dev->ext_priv; |
||
270 | |||
271 | DEB_EE(("dev:%p\n",dev)); |
||
272 | |||
273 | saa7146_unregister_device(&cm7326->video_dev,dev); |
||
274 | saa7146_vv_release(dev); |
||
275 | |||
276 | cm7326_num--; |
||
277 | |||
278 | i2c_del_adapter(&cm7326->i2c_adapter); |
||
279 | kfree(cm7326); |
||
280 | return 0; |
||
281 | } |
||
282 | |||
283 | static int cm7326_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) |
||
284 | { |
||
285 | struct saa7146_dev *dev = fh->dev; |
||
286 | struct cm7326* card = (struct cm7326*)dev->ext_priv; |
||
287 | |||
288 | switch(cmd) |
||
289 | { |
||
290 | case VIDIOC_G_INPUT: |
||
291 | { |
||
292 | int* input = (int *)arg; |
||
293 | *input = card->cur_input; |
||
294 | |||
295 | DEB_D(("VIDIOC_G_INPUT %d.\n",*input)); |
||
296 | return 0; |
||
297 | } |
||
298 | case VIDIOC_S_INPUT: |
||
299 | { |
||
300 | int input = *(int *)arg; |
||
301 | int source = 0, sync = 0; |
||
302 | int i; |
||
303 | static int saa7110_inputs[6] = {5,4,3,2,1,0}; |
||
304 | |||
305 | if (input < 0 || input >= CM7326_INPUTS) { |
||
306 | DEB_D(("v4l2_ioctl: VIDIOC_S_INPUT: invalid input %d.\n",input)); |
||
307 | return -EINVAL; |
||
308 | } |
||
309 | |||
310 | DEB_D(("v4l2_ioctl: VIDIOC_S_INPUT %d.\n",input)); |
||
311 | |||
312 | source = SAA7146_HPS_SOURCE_PORT_A; |
||
313 | sync = SAA7146_HPS_SYNC_PORT_A; |
||
314 | card->cur_input = input; |
||
315 | |||
316 | /* switch video in saa7110 */ |
||
317 | saa7146_set_hps_source_and_sync(dev, source, sync); |
||
318 | i = saa7110_inputs[input]; |
||
319 | return saa7110_selmux(card, i); |
||
320 | } |
||
321 | case VIDIOC_ENUMINPUT: |
||
322 | { |
||
323 | struct v4l2_input *i = arg; |
||
324 | |||
325 | /* sanity check to satisfy xawtv */ |
||
326 | if( i->index < 0 || i->index >= CM7326_INPUTS) { |
||
327 | DEB_D(("v4l2_ioctl: VIDIOC_ENUMINPUT: invalid input %d.\n",i->index)); |
||
328 | return -EINVAL; |
||
329 | } |
||
330 | |||
331 | memcpy(i, &cm7326_inputs[i->index], sizeof(struct v4l2_input)); |
||
332 | |||
333 | DEB_D(("v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n",i->index)); |
||
334 | return 0; |
||
335 | } |
||
336 | default: |
||
337 | DEB_D(("v4l2_ioctl does not handle this ioctl.\n")); |
||
338 | return -ENOIOCTLCMD; |
||
339 | } |
||
340 | return 0; |
||
341 | } |
||
342 | |||
343 | static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *std) |
||
344 | { |
||
345 | struct cm7326* cm7326 = (struct cm7326*)dev->ext_priv; |
||
346 | union i2c_smbus_data data; |
||
347 | int ret = 0; |
||
348 | |||
349 | data.byte = 0x00; |
||
350 | ret += i2c_smbus_xfer(&cm7326->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, 0x06, I2C_SMBUS_BYTE_DATA, &data); |
||
351 | |||
352 | switch (std->id) { |
||
353 | case V4L2_STD_NTSC: |
||
354 | { |
||
355 | data.byte = 0x06; |
||
356 | ret += i2c_smbus_xfer(&cm7326->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, 0x0D, I2C_SMBUS_BYTE_DATA, &data); |
||
357 | data.byte = 0x2C; |
||
358 | ret += i2c_smbus_xfer(&cm7326->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, 0x11, I2C_SMBUS_BYTE_DATA, &data); |
||
359 | data.byte = 0x81; |
||
360 | ret += i2c_smbus_xfer(&cm7326->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, 0x30, I2C_SMBUS_BYTE_DATA, &data); |
||
361 | data.byte = 0xDF; |
||
362 | ret += i2c_smbus_xfer(&cm7326->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, 0x2A, I2C_SMBUS_BYTE_DATA, &data); |
||
363 | break; |
||
364 | } |
||
365 | case V4L2_STD_PAL: |
||
366 | { |
||
367 | data.byte = 0x06; |
||
368 | ret += i2c_smbus_xfer(&cm7326->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, 0x0D, I2C_SMBUS_BYTE_DATA, &data); |
||
369 | data.byte = 0x59; |
||
370 | ret += i2c_smbus_xfer(&cm7326->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, 0x11, I2C_SMBUS_BYTE_DATA, &data); |
||
371 | data.byte = 0x9A; |
||
372 | ret += i2c_smbus_xfer(&cm7326->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, 0x2E, I2C_SMBUS_BYTE_DATA, &data); |
||
373 | break; |
||
374 | } |
||
375 | case V4L2_STD_SECAM: |
||
376 | { |
||
377 | data.byte = 0x07; |
||
378 | ret += i2c_smbus_xfer(&cm7326->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, 0x0D, I2C_SMBUS_BYTE_DATA, &data); |
||
379 | data.byte = 0x59; |
||
380 | ret += i2c_smbus_xfer(&cm7326->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, 0x11, I2C_SMBUS_BYTE_DATA, &data); |
||
381 | data.byte = 0x9A; |
||
382 | ret += i2c_smbus_xfer(&cm7326->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, 0x2E, I2C_SMBUS_BYTE_DATA, &data); |
||
383 | break; |
||
384 | } |
||
385 | default: |
||
386 | { |
||
387 | DEB_S(("invalid standard.\n")); |
||
388 | return -EFAULT; |
||
389 | } |
||
390 | } |
||
391 | |||
392 | if (0 != ret) { |
||
393 | DEB_S(("writing to saa7110 failed.\n")); |
||
394 | return -EFAULT; |
||
395 | } |
||
396 | |||
397 | return 0; |
||
398 | } |
||
399 | |||
400 | static struct saa7146_standard standard[] = { |
||
401 | { |
||
402 | .name = "PAL", .id = V4L2_STD_PAL, |
||
403 | .v_offset = 0x17, .v_field = 288, .v_calc = 576, |
||
404 | .h_offset = 0x14, .h_pixels = 680, .h_calc = 680+1, |
||
405 | .v_max_out = 576, .h_max_out = 768, |
||
406 | }, { |
||
407 | .name = "NTSC", .id = V4L2_STD_NTSC, |
||
408 | .v_offset = 0x14, .v_field = 240, .v_calc = 480, |
||
409 | .h_offset = 0x00, .h_pixels = 640, .h_calc = 640+1, |
||
410 | .v_max_out = 480, .h_max_out = 640, |
||
411 | }, { |
||
412 | .name = "SECAM", .id = V4L2_STD_SECAM, |
||
413 | .v_offset = 0x14, .v_field = 288, .v_calc = 576, |
||
414 | .h_offset = 0x14, .h_pixels = 720, .h_calc = 720+1, |
||
415 | .v_max_out = 576, .h_max_out = 768, |
||
416 | } |
||
417 | }; |
||
418 | |||
419 | static struct saa7146_extension extension; |
||
420 | |||
421 | static struct saa7146_pci_extension_data cm7326 = { |
||
422 | .ext_priv = "cm7326", |
||
423 | .ext = &extension, |
||
424 | }; |
||
425 | |||
426 | static struct pci_device_id pci_tbl[] = { |
||
427 | { |
||
428 | .vendor = PCI_VENDOR_ID_PHILIPS, |
||
429 | .device = PCI_DEVICE_ID_PHILIPS_SAA7146, |
||
430 | .subvendor = 0x1435, |
||
431 | .subdevice = 0x3303, |
||
432 | .driver_data = (unsigned long)&cm7326, |
||
433 | }, { |
||
434 | .vendor = 0, |
||
435 | } |
||
436 | }; |
||
437 | |||
438 | static struct saa7146_ext_vv vv_data = { |
||
439 | .inputs = CM7326_INPUTS, |
||
440 | .capabilities = 0, |
||
441 | .stds = &standard[0], |
||
442 | .num_stds = sizeof(standard)/sizeof(struct saa7146_standard), |
||
443 | .std_callback = &std_callback, |
||
444 | .ioctls = &ioctls[0], |
||
445 | .ioctl = cm7326_ioctl, |
||
446 | }; |
||
447 | |||
448 | static struct saa7146_extension extension = { |
||
449 | .name = "cm7326", |
||
450 | .flags = SAA7146_USE_I2C_IRQ, |
||
451 | |||
452 | .pci_tbl = &pci_tbl[0], |
||
453 | .module = THIS_MODULE, |
||
454 | |||
455 | .probe = cm7326_probe, |
||
456 | .attach = cm7326_attach, |
||
457 | .detach = cm7326_detach, |
||
458 | |||
459 | .irq_mask = 0, |
||
460 | .irq_func = NULL, |
||
461 | }; |
||
462 | |||
463 | |||
464 | int __init cm7326_init_module(void) |
||
465 | { |
||
466 | int ret = 0; |
||
467 | |||
468 | ret = saa7146_register_extension(&extension); |
||
469 | if (0 != ret) { |
||
470 | DEB_S(("failed to register extension.\n")); |
||
471 | } |
||
472 | |||
473 | return ret; |
||
474 | } |
||
475 | |||
476 | void __exit cm7326_cleanup_module(void) |
||
477 | { |
||
478 | saa7146_unregister_extension(&extension); |
||
479 | } |
||
480 | |||
481 | module_init(cm7326_init_module); |
||
482 | module_exit(cm7326_cleanup_module); |
||
483 | |||
484 | MODULE_AUTHOR("Miguel Freitas, Michael Hunold"); |
||
485 | MODULE_DESCRIPTION("CM7326 frame grabber v4l2-driver"); |
||
486 | MODULE_LICENSE("GPL"); |
||
487 |