blob: da9481198c5305c4a916d858c046f7d1eb0fd9f7 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 dpc7146.c - v4l2 driver for the dpc7146 demonstration board
3
4 Copyright (C) 2000-2003 Michael Hunold <michael@mihu.de>
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#define DEBUG_VARIABLE debug
22
23#include <media/saa7146_vv.h>
24#include <linux/video_decoder.h> /* for saa7111a */
25
26#define I2C_SAA7111A 0x24
27
28/* All unused bytes are reserverd. */
29#define SAA711X_CHIP_VERSION 0x00
30#define SAA711X_ANALOG_INPUT_CONTROL_1 0x02
31#define SAA711X_ANALOG_INPUT_CONTROL_2 0x03
32#define SAA711X_ANALOG_INPUT_CONTROL_3 0x04
33#define SAA711X_ANALOG_INPUT_CONTROL_4 0x05
34#define SAA711X_HORIZONTAL_SYNC_START 0x06
35#define SAA711X_HORIZONTAL_SYNC_STOP 0x07
36#define SAA711X_SYNC_CONTROL 0x08
37#define SAA711X_LUMINANCE_CONTROL 0x09
38#define SAA711X_LUMINANCE_BRIGHTNESS 0x0A
39#define SAA711X_LUMINANCE_CONTRAST 0x0B
40#define SAA711X_CHROMA_SATURATION 0x0C
41#define SAA711X_CHROMA_HUE_CONTROL 0x0D
42#define SAA711X_CHROMA_CONTROL 0x0E
43#define SAA711X_FORMAT_DELAY_CONTROL 0x10
44#define SAA711X_OUTPUT_CONTROL_1 0x11
45#define SAA711X_OUTPUT_CONTROL_2 0x12
46#define SAA711X_OUTPUT_CONTROL_3 0x13
47#define SAA711X_V_GATE_1_START 0x15
48#define SAA711X_V_GATE_1_STOP 0x16
49#define SAA711X_V_GATE_1_MSB 0x17
50#define SAA711X_TEXT_SLICER_STATUS 0x1A
51#define SAA711X_DECODED_BYTES_OF_TS_1 0x1B
52#define SAA711X_DECODED_BYTES_OF_TS_2 0x1C
53#define SAA711X_STATUS_BYTE 0x1F
54
55#define DPC_BOARD_CAN_DO_VBI(dev) (dev->revision != 0)
56
57static int debug = 0;
58module_param(debug, int, 0);
59MODULE_PARM_DESC(debug, "debug verbosity");
60
61static int dpc_num = 0;
62
63#define DPC_INPUTS 2
64static struct v4l2_input dpc_inputs[DPC_INPUTS] = {
65 { 0, "Port A", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
66 { 1, "Port B", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
67};
68
69#define DPC_AUDIOS 0
70
71static struct saa7146_extension_ioctls ioctls[] = {
72 { VIDIOC_G_INPUT, SAA7146_EXCLUSIVE },
73 { VIDIOC_S_INPUT, SAA7146_EXCLUSIVE },
74 { VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE },
75 { VIDIOC_S_STD, SAA7146_AFTER },
76 { 0, 0 }
77};
78
79struct dpc
80{
81 struct video_device *video_dev;
82 struct video_device *vbi_dev;
83
84 struct i2c_adapter i2c_adapter;
85 struct i2c_client *saa7111a;
86
87 int cur_input; /* current input */
88};
89
90/* fixme: add vbi stuff here */
91static int dpc_probe(struct saa7146_dev* dev)
92{
93 struct dpc* dpc = NULL;
94 struct i2c_client *client;
95 struct list_head *item;
96
97 dpc = (struct dpc*)kmalloc(sizeof(struct dpc), GFP_KERNEL);
98 if( NULL == dpc ) {
99 printk("dpc_v4l2.o: dpc_probe: not enough kernel memory.\n");
100 return -ENOMEM;
101 }
102 memset(dpc, 0x0, sizeof(struct dpc));
103
104 /* FIXME: enable i2c-port pins, video-port-pins
105 video port pins should be enabled here ?! */
106 saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26));
107
108 dpc->i2c_adapter = (struct i2c_adapter) {
109 .class = I2C_CLASS_TV_ANALOG,
110 .name = "dpc7146",
111 };
112 saa7146_i2c_adapter_prepare(dev, &dpc->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
113 if(i2c_add_adapter(&dpc->i2c_adapter) < 0) {
114 DEB_S(("cannot register i2c-device. skipping.\n"));
115 kfree(dpc);
116 return -EFAULT;
117 }
118
119 /* loop through all i2c-devices on the bus and look who is there */
120 list_for_each(item,&dpc->i2c_adapter.clients) {
121 client = list_entry(item, struct i2c_client, list);
122 if( I2C_SAA7111A == client->addr )
123 dpc->saa7111a = client;
124 }
125
126 /* check if all devices are present */
127 if( 0 == dpc->saa7111a ) {
128 DEB_D(("dpc_v4l2.o: dpc_attach failed for this device.\n"));
129 i2c_del_adapter(&dpc->i2c_adapter);
130 kfree(dpc);
131 return -ENODEV;
132 }
133
134 /* all devices are present, probe was successful */
135 DEB_D(("dpc_v4l2.o: dpc_probe succeeded for this device.\n"));
136
137 /* we store the pointer in our private data field */
138 dev->ext_priv = dpc;
139
140 return 0;
141}
142
143/* bring hardware to a sane state. this has to be done, just in case someone
144 wants to capture from this device before it has been properly initialized.
145 the capture engine would badly fail, because no valid signal arrives on the
146 saa7146, thus leading to timeouts and stuff. */
147static int dpc_init_done(struct saa7146_dev* dev)
148{
149 struct dpc* dpc = (struct dpc*)dev->ext_priv;
150
151 DEB_D(("dpc_v4l2.o: dpc_init_done called.\n"));
152
153 /* initialize the helper ics to useful values */
154 i2c_smbus_write_byte_data(dpc->saa7111a, 0x00, 0x11);
155
156 i2c_smbus_write_byte_data(dpc->saa7111a, 0x02, 0xc0);
157 i2c_smbus_write_byte_data(dpc->saa7111a, 0x03, 0x30);
158 i2c_smbus_write_byte_data(dpc->saa7111a, 0x04, 0x00);
159 i2c_smbus_write_byte_data(dpc->saa7111a, 0x05, 0x00);
160 i2c_smbus_write_byte_data(dpc->saa7111a, 0x06, 0xde);
161 i2c_smbus_write_byte_data(dpc->saa7111a, 0x07, 0xad);
162 i2c_smbus_write_byte_data(dpc->saa7111a, 0x08, 0xa8);
163 i2c_smbus_write_byte_data(dpc->saa7111a, 0x09, 0x00);
164 i2c_smbus_write_byte_data(dpc->saa7111a, 0x0a, 0x80);
165 i2c_smbus_write_byte_data(dpc->saa7111a, 0x0b, 0x47);
166 i2c_smbus_write_byte_data(dpc->saa7111a, 0x0c, 0x40);
167 i2c_smbus_write_byte_data(dpc->saa7111a, 0x0d, 0x00);
168 i2c_smbus_write_byte_data(dpc->saa7111a, 0x0e, 0x03);
169
170 i2c_smbus_write_byte_data(dpc->saa7111a, 0x10, 0xd0);
171 i2c_smbus_write_byte_data(dpc->saa7111a, 0x11, 0x1c);
172 i2c_smbus_write_byte_data(dpc->saa7111a, 0x12, 0xc1);
173 i2c_smbus_write_byte_data(dpc->saa7111a, 0x13, 0x30);
174
175 i2c_smbus_write_byte_data(dpc->saa7111a, 0x1f, 0x81);
176
177 return 0;
178}
179
180static struct saa7146_ext_vv vv_data;
181
182/* this function only gets called when the probing was successful */
183static int dpc_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data *info)
184{
185 struct dpc* dpc = (struct dpc*)dev->ext_priv;
186
187 DEB_D(("dpc_v4l2.o: dpc_attach called.\n"));
188
189 /* checking for i2c-devices can be omitted here, because we
190 already did this in "dpc_vl42_probe" */
191
192 saa7146_vv_init(dev,&vv_data);
193 if( 0 != saa7146_register_device(&dpc->video_dev, dev, "dpc", VFL_TYPE_GRABBER)) {
194 ERR(("cannot register capture v4l2 device. skipping.\n"));
195 return -1;
196 }
197
198 /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/
199 if( 0 != DPC_BOARD_CAN_DO_VBI(dev)) {
200 if( 0 != saa7146_register_device(&dpc->vbi_dev, dev, "dpc", VFL_TYPE_VBI)) {
201 ERR(("cannot register vbi v4l2 device. skipping.\n"));
202 }
203 }
204
205 i2c_use_client(dpc->saa7111a);
206
207 printk("dpc: found 'dpc7146 demonstration board'-%d.\n",dpc_num);
208 dpc_num++;
209
210 /* the rest */
211 dpc->cur_input = 0;
212 dpc_init_done(dev);
213
214 return 0;
215}
216
217static int dpc_detach(struct saa7146_dev* dev)
218{
219 struct dpc* dpc = (struct dpc*)dev->ext_priv;
220
221 DEB_EE(("dev:%p\n",dev));
222
223 i2c_release_client(dpc->saa7111a);
224
225 saa7146_unregister_device(&dpc->video_dev,dev);
226 if( 0 != DPC_BOARD_CAN_DO_VBI(dev)) {
227 saa7146_unregister_device(&dpc->vbi_dev,dev);
228 }
229 saa7146_vv_release(dev);
230
231 dpc_num--;
232
233 i2c_del_adapter(&dpc->i2c_adapter);
234 kfree(dpc);
235 return 0;
236}
237
238#ifdef axa
239int dpc_vbi_bypass(struct saa7146_dev* dev)
240{
241 struct dpc* dpc = (struct dpc*)dev->ext_priv;
242
243 int i = 1;
244
245 /* switch bypass in saa7111a */
246 if ( 0 != dpc->saa7111a->driver->command(dpc->saa7111a,SAA711X_VBI_BYPASS, &i)) {
247 printk("dpc_v4l2.o: VBI_BYPASS: could not address saa7111a.\n");
248 return -1;
249 }
250
251 return 0;
252}
253#endif
254
255static int dpc_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
256{
257 struct saa7146_dev *dev = fh->dev;
258 struct dpc* dpc = (struct dpc*)dev->ext_priv;
259/*
260 struct saa7146_vv *vv = dev->vv_data;
261*/
262 switch(cmd)
263 {
264 case VIDIOC_ENUMINPUT:
265 {
266 struct v4l2_input *i = arg;
267 DEB_EE(("VIDIOC_ENUMINPUT %d.\n",i->index));
268
269 if( i->index < 0 || i->index >= DPC_INPUTS) {
270 return -EINVAL;
271 }
272
273 memcpy(i, &dpc_inputs[i->index], sizeof(struct v4l2_input));
274
275 DEB_D(("dpc_v4l2.o: v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n",i->index));
276 return 0;
277 }
278 case VIDIOC_G_INPUT:
279 {
280 int *input = (int *)arg;
281 *input = dpc->cur_input;
282
283 DEB_D(("dpc_v4l2.o: VIDIOC_G_INPUT: %d\n",*input));
284 return 0;
285 }
286 case VIDIOC_S_INPUT:
287 {
288 int input = *(int *)arg;
289
290 if (input < 0 || input >= DPC_INPUTS) {
291 return -EINVAL;
292 }
293
294 dpc->cur_input = input;
295
296 /* fixme: switch input here, switch audio, too! */
297// saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source, input_port_selection[input].hps_sync);
298 printk("dpc_v4l2.o: VIDIOC_S_INPUT: fixme switch input.\n");
299
300 return 0;
301 }
302 default:
303/*
304 DEB_D(("dpc_v4l2.o: v4l2_ioctl does not handle this ioctl.\n"));
305*/
306 return -ENOIOCTLCMD;
307 }
308 return 0;
309}
310
311static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std)
312{
313 return 0;
314}
315
316static struct saa7146_standard standard[] = {
317 {
318 .name = "PAL", .id = V4L2_STD_PAL,
319 .v_offset = 0x17, .v_field = 288,
320 .h_offset = 0x14, .h_pixels = 680,
321 .v_max_out = 576, .h_max_out = 768,
322 }, {
323 .name = "NTSC", .id = V4L2_STD_NTSC,
324 .v_offset = 0x16, .v_field = 240,
325 .h_offset = 0x06, .h_pixels = 708,
326 .v_max_out = 480, .h_max_out = 640,
327 }, {
328 .name = "SECAM", .id = V4L2_STD_SECAM,
329 .v_offset = 0x14, .v_field = 288,
330 .h_offset = 0x14, .h_pixels = 720,
331 .v_max_out = 576, .h_max_out = 768,
332 }
333};
334
335static struct saa7146_extension extension;
336
337static struct saa7146_pci_extension_data dpc = {
338 .ext_priv = "Multimedia eXtension Board",
339 .ext = &extension,
340};
341
342static struct pci_device_id pci_tbl[] = {
343 {
344 .vendor = PCI_VENDOR_ID_PHILIPS,
345 .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
346 .subvendor = 0x0000,
347 .subdevice = 0x0000,
348 .driver_data = (unsigned long)&dpc,
349 }, {
350 .vendor = 0,
351 }
352};
353
354MODULE_DEVICE_TABLE(pci, pci_tbl);
355
356static struct saa7146_ext_vv vv_data = {
357 .inputs = DPC_INPUTS,
358 .capabilities = V4L2_CAP_VBI_CAPTURE,
359 .stds = &standard[0],
360 .num_stds = sizeof(standard)/sizeof(struct saa7146_standard),
361 .std_callback = &std_callback,
362 .ioctls = &ioctls[0],
363 .ioctl = dpc_ioctl,
364};
365
366static struct saa7146_extension extension = {
367 .name = "dpc7146 demonstration board",
368 .flags = SAA7146_USE_I2C_IRQ,
369
370 .pci_tbl = &pci_tbl[0],
371 .module = THIS_MODULE,
372
373 .probe = dpc_probe,
374 .attach = dpc_attach,
375 .detach = dpc_detach,
376
377 .irq_mask = 0,
378 .irq_func = NULL,
379};
380
381static int __init dpc_init_module(void)
382{
383 if( 0 != saa7146_register_extension(&extension)) {
384 DEB_S(("failed to register extension.\n"));
385 return -ENODEV;
386 }
387
388 return 0;
389}
390
391static void __exit dpc_cleanup_module(void)
392{
393 saa7146_unregister_extension(&extension);
394}
395
396module_init(dpc_init_module);
397module_exit(dpc_cleanup_module);
398
399MODULE_DESCRIPTION("video4linux-2 driver for the 'dpc7146 demonstration board'");
400MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
401MODULE_LICENSE("GPL");