1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3     hexium_gemini.c - v4l2 driver for Hexium Gemini frame grabber cards
4 
5     Visit http://www.mihu.de/linux/saa7146/ and follow the link
6     to "hexium" for further details about this card.
7 
8     Copyright (C) 2003 Michael Hunold <michael@mihu.de>
9 
10 */
11 
12 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13 
14 #define DEBUG_VARIABLE debug
15 
16 #include <media/drv-intf/saa7146_vv.h>
17 #include <linux/module.h>
18 #include <linux/kernel.h>
19 
20 static int debug;
21 module_param(debug, int, 0);
22 MODULE_PARM_DESC(debug, "debug verbosity");
23 
24 /* global variables */
25 static int hexium_num;
26 
27 #define HEXIUM_GEMINI			4
28 #define HEXIUM_GEMINI_DUAL		5
29 
30 #define HEXIUM_INPUTS	9
31 static struct v4l2_input hexium_inputs[HEXIUM_INPUTS] = {
32 	{ 0, "CVBS 1",	V4L2_INPUT_TYPE_CAMERA,	0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
33 	{ 1, "CVBS 2",	V4L2_INPUT_TYPE_CAMERA,	0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
34 	{ 2, "CVBS 3",	V4L2_INPUT_TYPE_CAMERA,	0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
35 	{ 3, "CVBS 4",	V4L2_INPUT_TYPE_CAMERA,	0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
36 	{ 4, "CVBS 5",	V4L2_INPUT_TYPE_CAMERA,	0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
37 	{ 5, "CVBS 6",	V4L2_INPUT_TYPE_CAMERA,	0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
38 	{ 6, "Y/C 1",	V4L2_INPUT_TYPE_CAMERA,	0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
39 	{ 7, "Y/C 2",	V4L2_INPUT_TYPE_CAMERA,	0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
40 	{ 8, "Y/C 3",	V4L2_INPUT_TYPE_CAMERA,	0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
41 };
42 
43 #define HEXIUM_AUDIOS	0
44 
45 struct hexium_data
46 {
47 	s8 adr;
48 	u8 byte;
49 };
50 
51 #define HEXIUM_GEMINI_V_1_0		1
52 #define HEXIUM_GEMINI_DUAL_V_1_0	2
53 
54 struct hexium
55 {
56 	int type;
57 
58 	struct video_device	video_dev;
59 	struct i2c_adapter	i2c_adapter;
60 
61 	int		cur_input;	/* current input */
62 	v4l2_std_id	cur_std;	/* current standard */
63 };
64 
65 /* Samsung KS0127B decoder default registers */
66 static u8 hexium_ks0127b[0x100]={
67 /*00*/ 0x00,0x52,0x30,0x40,0x01,0x0C,0x2A,0x10,
68 /*08*/ 0x00,0x00,0x00,0x60,0x00,0x00,0x0F,0x06,
69 /*10*/ 0x00,0x00,0xE4,0xC0,0x00,0x00,0x00,0x00,
70 /*18*/ 0x14,0x9B,0xFE,0xFF,0xFC,0xFF,0x03,0x22,
71 /*20*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
72 /*28*/ 0x00,0x00,0x00,0x00,0x00,0x2C,0x9B,0x00,
73 /*30*/ 0x00,0x00,0x10,0x80,0x80,0x10,0x80,0x80,
74 /*38*/ 0x01,0x04,0x00,0x00,0x00,0x29,0xC0,0x00,
75 /*40*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
76 /*48*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
77 /*50*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
78 /*58*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
79 /*60*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
80 /*68*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
81 /*70*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
82 /*78*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
83 /*80*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
84 /*88*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
85 /*90*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
86 /*98*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
87 /*A0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
88 /*A8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
89 /*B0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
90 /*B8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
91 /*C0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
92 /*C8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
93 /*D0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
94 /*D8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
95 /*E0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
96 /*E8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
97 /*F0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
98 /*F8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
99 };
100 
101 static struct hexium_data hexium_pal[] = {
102 	{ 0x01, 0x52 }, { 0x12, 0x64 }, { 0x2D, 0x2C }, { 0x2E, 0x9B }, { -1 , 0xFF }
103 };
104 
105 static struct hexium_data hexium_ntsc[] = {
106 	{ 0x01, 0x53 }, { 0x12, 0x04 }, { 0x2D, 0x23 }, { 0x2E, 0x81 }, { -1 , 0xFF }
107 };
108 
109 static struct hexium_data hexium_secam[] = {
110 	{ 0x01, 0x52 }, { 0x12, 0x64 }, { 0x2D, 0x2C }, { 0x2E, 0x9B }, { -1 , 0xFF }
111 };
112 
113 static struct hexium_data hexium_input_select[] = {
114 	{ 0x02, 0x60 },
115 	{ 0x02, 0x64 },
116 	{ 0x02, 0x61 },
117 	{ 0x02, 0x65 },
118 	{ 0x02, 0x62 },
119 	{ 0x02, 0x66 },
120 	{ 0x02, 0x68 },
121 	{ 0x02, 0x69 },
122 	{ 0x02, 0x6A },
123 };
124 
125 /* fixme: h_offset = 0 for Hexium Gemini *Dual*, which
126    are currently *not* supported*/
127 static struct saa7146_standard hexium_standards[] = {
128 	{
129 		.name	= "PAL",	.id	= V4L2_STD_PAL,
130 		.v_offset	= 28,	.v_field	= 288,
131 		.h_offset	= 1,	.h_pixels	= 680,
132 		.v_max_out	= 576,	.h_max_out	= 768,
133 	}, {
134 		.name	= "NTSC",	.id	= V4L2_STD_NTSC,
135 		.v_offset	= 28,	.v_field	= 240,
136 		.h_offset	= 1,	.h_pixels	= 640,
137 		.v_max_out	= 480,	.h_max_out	= 640,
138 	}, {
139 		.name	= "SECAM",	.id	= V4L2_STD_SECAM,
140 		.v_offset	= 28,	.v_field	= 288,
141 		.h_offset	= 1,	.h_pixels	= 720,
142 		.v_max_out	= 576,	.h_max_out	= 768,
143 	}
144 };
145 
146 /* bring hardware to a sane state. this has to be done, just in case someone
147    wants to capture from this device before it has been properly initialized.
148    the capture engine would badly fail, because no valid signal arrives on the
149    saa7146, thus leading to timeouts and stuff. */
150 static int hexium_init_done(struct saa7146_dev *dev)
151 {
152 	struct hexium *hexium = (struct hexium *) dev->ext_priv;
153 	union i2c_smbus_data data;
154 	int i = 0;
155 
156 	DEB_D("hexium_init_done called\n");
157 
158 	/* initialize the helper ics to useful values */
159 	for (i = 0; i < sizeof(hexium_ks0127b); i++) {
160 		data.byte = hexium_ks0127b[i];
161 		if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, i, I2C_SMBUS_BYTE_DATA, &data)) {
162 			pr_err("hexium_init_done() failed for address 0x%02x\n",
163 			       i);
164 		}
165 	}
166 
167 	return 0;
168 }
169 
170 static int hexium_set_input(struct hexium *hexium, int input)
171 {
172 	union i2c_smbus_data data;
173 
174 	DEB_D("\n");
175 
176 	data.byte = hexium_input_select[input].byte;
177 	if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, hexium_input_select[input].adr, I2C_SMBUS_BYTE_DATA, &data)) {
178 		return -1;
179 	}
180 
181 	return 0;
182 }
183 
184 static int hexium_set_standard(struct hexium *hexium, struct hexium_data *vdec)
185 {
186 	union i2c_smbus_data data;
187 	int i = 0;
188 
189 	DEB_D("\n");
190 
191 	while (vdec[i].adr != -1) {
192 		data.byte = vdec[i].byte;
193 		if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, vdec[i].adr, I2C_SMBUS_BYTE_DATA, &data)) {
194 			pr_err("hexium_init_done: hexium_set_standard() failed for address 0x%02x\n",
195 			       i);
196 			return -1;
197 		}
198 		i++;
199 	}
200 	return 0;
201 }
202 
203 static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
204 {
205 	DEB_EE("VIDIOC_ENUMINPUT %d\n", i->index);
206 
207 	if (i->index >= HEXIUM_INPUTS)
208 		return -EINVAL;
209 
210 	memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input));
211 
212 	DEB_D("v4l2_ioctl: VIDIOC_ENUMINPUT %d\n", i->index);
213 	return 0;
214 }
215 
216 static int vidioc_g_input(struct file *file, void *fh, unsigned int *input)
217 {
218 	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
219 	struct hexium *hexium = (struct hexium *) dev->ext_priv;
220 
221 	*input = hexium->cur_input;
222 
223 	DEB_D("VIDIOC_G_INPUT: %d\n", *input);
224 	return 0;
225 }
226 
227 static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
228 {
229 	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
230 	struct hexium *hexium = (struct hexium *) dev->ext_priv;
231 
232 	DEB_EE("VIDIOC_S_INPUT %d\n", input);
233 
234 	if (input >= HEXIUM_INPUTS)
235 		return -EINVAL;
236 
237 	hexium->cur_input = input;
238 	hexium_set_input(hexium, input);
239 	return 0;
240 }
241 
242 static struct saa7146_ext_vv vv_data;
243 
244 /* this function only gets called when the probing was successful */
245 static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
246 {
247 	struct hexium *hexium;
248 	int ret;
249 
250 	DEB_EE("\n");
251 
252 	hexium = kzalloc(sizeof(*hexium), GFP_KERNEL);
253 	if (!hexium)
254 		return -ENOMEM;
255 
256 	dev->ext_priv = hexium;
257 
258 	/* enable i2c-port pins */
259 	saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26));
260 
261 	strscpy(hexium->i2c_adapter.name, "hexium gemini",
262 		sizeof(hexium->i2c_adapter.name));
263 	saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
264 	if (i2c_add_adapter(&hexium->i2c_adapter) < 0) {
265 		DEB_S("cannot register i2c-device. skipping.\n");
266 		kfree(hexium);
267 		return -EFAULT;
268 	}
269 
270 	/*  set HWControl GPIO number 2 */
271 	saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
272 
273 	saa7146_write(dev, DD1_INIT, 0x07000700);
274 	saa7146_write(dev, DD1_STREAM_B, 0x00000000);
275 	saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
276 
277 	/* the rest */
278 	hexium->cur_input = 0;
279 	hexium_init_done(dev);
280 
281 	hexium_set_standard(hexium, hexium_pal);
282 	hexium->cur_std = V4L2_STD_PAL;
283 
284 	hexium_set_input(hexium, 0);
285 	hexium->cur_input = 0;
286 
287 	saa7146_vv_init(dev, &vv_data);
288 
289 	vv_data.vid_ops.vidioc_enum_input = vidioc_enum_input;
290 	vv_data.vid_ops.vidioc_g_input = vidioc_g_input;
291 	vv_data.vid_ops.vidioc_s_input = vidioc_s_input;
292 	ret = saa7146_register_device(&hexium->video_dev, dev, "hexium gemini", VFL_TYPE_GRABBER);
293 	if (ret < 0) {
294 		pr_err("cannot register capture v4l2 device. skipping.\n");
295 		return ret;
296 	}
297 
298 	pr_info("found 'hexium gemini' frame grabber-%d\n", hexium_num);
299 	hexium_num++;
300 
301 	return 0;
302 }
303 
304 static int hexium_detach(struct saa7146_dev *dev)
305 {
306 	struct hexium *hexium = (struct hexium *) dev->ext_priv;
307 
308 	DEB_EE("dev:%p\n", dev);
309 
310 	saa7146_unregister_device(&hexium->video_dev, dev);
311 	saa7146_vv_release(dev);
312 
313 	hexium_num--;
314 
315 	i2c_del_adapter(&hexium->i2c_adapter);
316 	kfree(hexium);
317 	return 0;
318 }
319 
320 static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *std)
321 {
322 	struct hexium *hexium = (struct hexium *) dev->ext_priv;
323 
324 	if (V4L2_STD_PAL == std->id) {
325 		hexium_set_standard(hexium, hexium_pal);
326 		hexium->cur_std = V4L2_STD_PAL;
327 		return 0;
328 	} else if (V4L2_STD_NTSC == std->id) {
329 		hexium_set_standard(hexium, hexium_ntsc);
330 		hexium->cur_std = V4L2_STD_NTSC;
331 		return 0;
332 	} else if (V4L2_STD_SECAM == std->id) {
333 		hexium_set_standard(hexium, hexium_secam);
334 		hexium->cur_std = V4L2_STD_SECAM;
335 		return 0;
336 	}
337 
338 	return -1;
339 }
340 
341 static struct saa7146_extension hexium_extension;
342 
343 static struct saa7146_pci_extension_data hexium_gemini_4bnc = {
344 	.ext_priv = "Hexium Gemini (4 BNC)",
345 	.ext = &hexium_extension,
346 };
347 
348 static struct saa7146_pci_extension_data hexium_gemini_dual_4bnc = {
349 	.ext_priv = "Hexium Gemini Dual (4 BNC)",
350 	.ext = &hexium_extension,
351 };
352 
353 static const struct pci_device_id pci_tbl[] = {
354 	{
355 	 .vendor = PCI_VENDOR_ID_PHILIPS,
356 	 .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
357 	 .subvendor = 0x17c8,
358 	 .subdevice = 0x2401,
359 	 .driver_data = (unsigned long) &hexium_gemini_4bnc,
360 	 },
361 	{
362 	 .vendor = PCI_VENDOR_ID_PHILIPS,
363 	 .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
364 	 .subvendor = 0x17c8,
365 	 .subdevice = 0x2402,
366 	 .driver_data = (unsigned long) &hexium_gemini_dual_4bnc,
367 	 },
368 	{
369 	 .vendor = 0,
370 	 }
371 };
372 
373 MODULE_DEVICE_TABLE(pci, pci_tbl);
374 
375 static struct saa7146_ext_vv vv_data = {
376 	.inputs = HEXIUM_INPUTS,
377 	.capabilities = 0,
378 	.stds = &hexium_standards[0],
379 	.num_stds = ARRAY_SIZE(hexium_standards),
380 	.std_callback = &std_callback,
381 };
382 
383 static struct saa7146_extension hexium_extension = {
384 	.name = "hexium gemini",
385 	.flags = SAA7146_USE_I2C_IRQ,
386 
387 	.pci_tbl = &pci_tbl[0],
388 	.module = THIS_MODULE,
389 
390 	.attach = hexium_attach,
391 	.detach = hexium_detach,
392 
393 	.irq_mask = 0,
394 	.irq_func = NULL,
395 };
396 
397 static int __init hexium_init_module(void)
398 {
399 	if (0 != saa7146_register_extension(&hexium_extension)) {
400 		DEB_S("failed to register extension\n");
401 		return -ENODEV;
402 	}
403 
404 	return 0;
405 }
406 
407 static void __exit hexium_cleanup_module(void)
408 {
409 	saa7146_unregister_extension(&hexium_extension);
410 }
411 
412 module_init(hexium_init_module);
413 module_exit(hexium_cleanup_module);
414 
415 MODULE_DESCRIPTION("video4linux-2 driver for Hexium Gemini frame grabber cards");
416 MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
417 MODULE_LICENSE("GPL");
418