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