1/*
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
90static int dpc_probe(struct saa7146_dev* dev)
91{
92	struct dpc* dpc = NULL;
93	struct i2c_client *client;
94	struct list_head *item;
95
96	dpc = kzalloc(sizeof(struct dpc), GFP_KERNEL);
97	if( NULL == dpc ) {
98		printk("dpc_v4l2.o: dpc_probe: not enough kernel memory.\n");
99		return -ENOMEM;
100	}
101
102	saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26));
103
104	dpc->i2c_adapter = (struct i2c_adapter) {
105		.class = I2C_CLASS_TV_ANALOG,
106		.name = "dpc7146",
107	};
108	saa7146_i2c_adapter_prepare(dev, &dpc->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
109	if(i2c_add_adapter(&dpc->i2c_adapter) < 0) {
110		DEB_S(("cannot register i2c-device. skipping.\n"));
111		kfree(dpc);
112		return -EFAULT;
113	}
114
115	/* loop through all i2c-devices on the bus and look who is there */
116	list_for_each(item,&dpc->i2c_adapter.clients) {
117		client = list_entry(item, struct i2c_client, list);
118		if( I2C_SAA7111A == client->addr )
119			dpc->saa7111a = client;
120	}
121
122	/* check if all devices are present */
123	if( 0 == dpc->saa7111a ) {
124		DEB_D(("dpc_v4l2.o: dpc_attach failed for this device.\n"));
125		i2c_del_adapter(&dpc->i2c_adapter);
126		kfree(dpc);
127		return -ENODEV;
128	}
129
130	/* all devices are present, probe was successful */
131	DEB_D(("dpc_v4l2.o: dpc_probe succeeded for this device.\n"));
132
133	/* we store the pointer in our private data field */
134	dev->ext_priv = dpc;
135
136	return 0;
137}
138
139/* bring hardware to a sane state. this has to be done, just in case someone
140   wants to capture from this device before it has been properly initialized.
141   the capture engine would badly fail, because no valid signal arrives on the
142   saa7146, thus leading to timeouts and stuff. */
143static int dpc_init_done(struct saa7146_dev* dev)
144{
145	struct dpc* dpc = (struct dpc*)dev->ext_priv;
146
147	DEB_D(("dpc_v4l2.o: dpc_init_done called.\n"));
148
149	/* initialize the helper ics to useful values */
150	i2c_smbus_write_byte_data(dpc->saa7111a, 0x00, 0x11);
151
152	i2c_smbus_write_byte_data(dpc->saa7111a, 0x02, 0xc0);
153	i2c_smbus_write_byte_data(dpc->saa7111a, 0x03, 0x30);
154	i2c_smbus_write_byte_data(dpc->saa7111a, 0x04, 0x00);
155	i2c_smbus_write_byte_data(dpc->saa7111a, 0x05, 0x00);
156	i2c_smbus_write_byte_data(dpc->saa7111a, 0x06, 0xde);
157	i2c_smbus_write_byte_data(dpc->saa7111a, 0x07, 0xad);
158	i2c_smbus_write_byte_data(dpc->saa7111a, 0x08, 0xa8);
159	i2c_smbus_write_byte_data(dpc->saa7111a, 0x09, 0x00);
160	i2c_smbus_write_byte_data(dpc->saa7111a, 0x0a, 0x80);
161	i2c_smbus_write_byte_data(dpc->saa7111a, 0x0b, 0x47);
162	i2c_smbus_write_byte_data(dpc->saa7111a, 0x0c, 0x40);
163	i2c_smbus_write_byte_data(dpc->saa7111a, 0x0d, 0x00);
164	i2c_smbus_write_byte_data(dpc->saa7111a, 0x0e, 0x03);
165
166	i2c_smbus_write_byte_data(dpc->saa7111a, 0x10, 0xd0);
167	i2c_smbus_write_byte_data(dpc->saa7111a, 0x11, 0x1c);
168	i2c_smbus_write_byte_data(dpc->saa7111a, 0x12, 0xc1);
169	i2c_smbus_write_byte_data(dpc->saa7111a, 0x13, 0x30);
170
171	i2c_smbus_write_byte_data(dpc->saa7111a, 0x1f, 0x81);
172
173	return 0;
174}
175
176static struct saa7146_ext_vv vv_data;
177
178/* this function only gets called when the probing was successful */
179static int dpc_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data *info)
180{
181	struct dpc* dpc = (struct dpc*)dev->ext_priv;
182
183	DEB_D(("dpc_v4l2.o: dpc_attach called.\n"));
184
185	/* checking for i2c-devices can be omitted here, because we
186	   already did this in "dpc_vl42_probe" */
187
188	saa7146_vv_init(dev,&vv_data);
189	if( 0 != saa7146_register_device(&dpc->video_dev, dev, "dpc", VFL_TYPE_GRABBER)) {
190		ERR(("cannot register capture v4l2 device. skipping.\n"));
191		return -1;
192	}
193
194	/* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/
195	if( 0 != DPC_BOARD_CAN_DO_VBI(dev)) {
196		if( 0 != saa7146_register_device(&dpc->vbi_dev, dev, "dpc", VFL_TYPE_VBI)) {
197			ERR(("cannot register vbi v4l2 device. skipping.\n"));
198		}
199	}
200
201	i2c_use_client(dpc->saa7111a);
202
203	printk("dpc: found 'dpc7146 demonstration board'-%d.\n",dpc_num);
204	dpc_num++;
205
206	/* the rest */
207	dpc->cur_input = 0;
208	dpc_init_done(dev);
209
210	return 0;
211}
212
213static int dpc_detach(struct saa7146_dev* dev)
214{
215	struct dpc* dpc = (struct dpc*)dev->ext_priv;
216
217	DEB_EE(("dev:%p\n",dev));
218
219	i2c_release_client(dpc->saa7111a);
220
221	saa7146_unregister_device(&dpc->video_dev,dev);
222	if( 0 != DPC_BOARD_CAN_DO_VBI(dev)) {
223		saa7146_unregister_device(&dpc->vbi_dev,dev);
224	}
225	saa7146_vv_release(dev);
226
227	dpc_num--;
228
229	i2c_del_adapter(&dpc->i2c_adapter);
230	kfree(dpc);
231	return 0;
232}
233
234#ifdef axa
235int dpc_vbi_bypass(struct saa7146_dev* dev)
236{
237	struct dpc* dpc = (struct dpc*)dev->ext_priv;
238
239	int i = 1;
240
241	/* switch bypass in saa7111a */
242	if ( 0 != dpc->saa7111a->driver->command(dpc->saa7111a,SAA711X_VBI_BYPASS, &i)) {
243		printk("dpc_v4l2.o: VBI_BYPASS: could not address saa7111a.\n");
244		return -1;
245	}
246
247	return 0;
248}
249#endif
250
251static int dpc_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
252{
253	struct saa7146_dev *dev = fh->dev;
254	struct dpc* dpc = (struct dpc*)dev->ext_priv;
255/*
256	struct saa7146_vv *vv = dev->vv_data;
257*/
258	switch(cmd)
259	{
260	case VIDIOC_ENUMINPUT:
261	{
262		struct v4l2_input *i = arg;
263		DEB_EE(("VIDIOC_ENUMINPUT %d.\n",i->index));
264
265		if( i->index < 0 || i->index >= DPC_INPUTS) {
266			return -EINVAL;
267		}
268
269		memcpy(i, &dpc_inputs[i->index], sizeof(struct v4l2_input));
270
271		DEB_D(("dpc_v4l2.o: v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n",i->index));
272		return 0;
273	}
274	case VIDIOC_G_INPUT:
275	{
276		int *input = (int *)arg;
277		*input = dpc->cur_input;
278
279		DEB_D(("dpc_v4l2.o: VIDIOC_G_INPUT: %d\n",*input));
280		return 0;
281	}
282	case VIDIOC_S_INPUT:
283	{
284		int	input = *(int *)arg;
285
286		if (input < 0 || input >= DPC_INPUTS) {
287			return -EINVAL;
288		}
289
290		dpc->cur_input = input;
291
292//		saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source, input_port_selection[input].hps_sync);
293		printk("dpc_v4l2.o: VIDIOC_S_INPUT: fixme switch input.\n");
294
295		return 0;
296	}
297	default:
298/*
299		DEB_D(("dpc_v4l2.o: v4l2_ioctl does not handle this ioctl.\n"));
300*/
301		return -ENOIOCTLCMD;
302	}
303	return 0;
304}
305
306static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std)
307{
308	return 0;
309}
310
311static struct saa7146_standard standard[] = {
312	{
313		.name	= "PAL", 	.id	= V4L2_STD_PAL,
314		.v_offset	= 0x17,	.v_field 	= 288,
315		.h_offset	= 0x14,	.h_pixels 	= 680,
316		.v_max_out	= 576,	.h_max_out	= 768,
317	}, {
318		.name	= "NTSC", 	.id	= V4L2_STD_NTSC,
319		.v_offset	= 0x16,	.v_field 	= 240,
320		.h_offset	= 0x06,	.h_pixels 	= 708,
321		.v_max_out	= 480,	.h_max_out	= 640,
322	}, {
323		.name	= "SECAM", 	.id	= V4L2_STD_SECAM,
324		.v_offset	= 0x14,	.v_field 	= 288,
325		.h_offset	= 0x14,	.h_pixels 	= 720,
326		.v_max_out	= 576,	.h_max_out	= 768,
327	}
328};
329
330static struct saa7146_extension extension;
331
332static struct saa7146_pci_extension_data dpc = {
333	.ext_priv = "Multimedia eXtension Board",
334	.ext = &extension,
335};
336
337static struct pci_device_id pci_tbl[] = {
338	{
339		.vendor    = PCI_VENDOR_ID_PHILIPS,
340		.device	   = PCI_DEVICE_ID_PHILIPS_SAA7146,
341		.subvendor = 0x0000,
342		.subdevice = 0x0000,
343		.driver_data = (unsigned long)&dpc,
344	}, {
345		.vendor = 0,
346	}
347};
348
349MODULE_DEVICE_TABLE(pci, pci_tbl);
350
351static struct saa7146_ext_vv vv_data = {
352	.inputs		= DPC_INPUTS,
353	.capabilities	= V4L2_CAP_VBI_CAPTURE,
354	.stds		= &standard[0],
355	.num_stds	= sizeof(standard)/sizeof(struct saa7146_standard),
356	.std_callback	= &std_callback,
357	.ioctls		= &ioctls[0],
358	.ioctl		= dpc_ioctl,
359};
360
361static struct saa7146_extension extension = {
362	.name		= "dpc7146 demonstration board",
363	.flags		= SAA7146_USE_I2C_IRQ,
364
365	.pci_tbl	= &pci_tbl[0],
366	.module		= THIS_MODULE,
367
368	.probe		= dpc_probe,
369	.attach		= dpc_attach,
370	.detach		= dpc_detach,
371
372	.irq_mask	= 0,
373	.irq_func	= NULL,
374};
375
376static int __init dpc_init_module(void)
377{
378	if( 0 != saa7146_register_extension(&extension)) {
379		DEB_S(("failed to register extension.\n"));
380		return -ENODEV;
381	}
382
383	return 0;
384}
385
386static void __exit dpc_cleanup_module(void)
387{
388	saa7146_unregister_extension(&extension);
389}
390
391module_init(dpc_init_module);
392module_exit(dpc_cleanup_module);
393
394MODULE_DESCRIPTION("video4linux-2 driver for the 'dpc7146 demonstration board'");
395MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
396MODULE_LICENSE("GPL");
397