1/*
2 * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
3 *
4 * Original author:
5 * Ben Collins <bcollins@ubuntu.com>
6 *
7 * Additional work by:
8 * John Brooks <john.brooks@bluecherry.net>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 * GNU General Public License for more details.
19 */
20
21#include <linux/kernel.h>
22#include <linux/module.h>
23#include <linux/pci.h>
24#include <linux/interrupt.h>
25#include <linux/videodev2.h>
26#include <linux/delay.h>
27#include <linux/sysfs.h>
28#include <linux/ktime.h>
29#include <linux/slab.h>
30
31#include "solo6x10.h"
32#include "solo6x10-tw28.h"
33
34MODULE_DESCRIPTION("Softlogic 6x10 MPEG4/H.264/G.723 CODEC V4L2/ALSA Driver");
35MODULE_AUTHOR("Bluecherry <maintainers@bluecherrydvr.com>");
36MODULE_VERSION(SOLO6X10_VERSION);
37MODULE_LICENSE("GPL");
38
39static unsigned video_nr = -1;
40module_param(video_nr, uint, 0644);
41MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect (default)");
42
43static int full_eeprom; /* default is only top 64B */
44module_param(full_eeprom, uint, 0644);
45MODULE_PARM_DESC(full_eeprom, "Allow access to full 128B EEPROM (dangerous)");
46
47
48static void solo_set_time(struct solo_dev *solo_dev)
49{
50	struct timespec ts;
51
52	ktime_get_ts(&ts);
53
54	solo_reg_write(solo_dev, SOLO_TIMER_SEC, ts.tv_sec);
55	solo_reg_write(solo_dev, SOLO_TIMER_USEC, ts.tv_nsec / NSEC_PER_USEC);
56}
57
58static void solo_timer_sync(struct solo_dev *solo_dev)
59{
60	u32 sec, usec;
61	struct timespec ts;
62	long diff;
63
64	if (solo_dev->type != SOLO_DEV_6110)
65		return;
66
67	if (++solo_dev->time_sync < 60)
68		return;
69
70	solo_dev->time_sync = 0;
71
72	sec = solo_reg_read(solo_dev, SOLO_TIMER_SEC);
73	usec = solo_reg_read(solo_dev, SOLO_TIMER_USEC);
74
75	ktime_get_ts(&ts);
76
77	diff = (long)ts.tv_sec - (long)sec;
78	diff = (diff * 1000000)
79		+ ((long)(ts.tv_nsec / NSEC_PER_USEC) - (long)usec);
80
81	if (diff > 1000 || diff < -1000) {
82		solo_set_time(solo_dev);
83	} else if (diff) {
84		long usec_lsb = solo_dev->usec_lsb;
85
86		usec_lsb -= diff / 4;
87		if (usec_lsb < 0)
88			usec_lsb = 0;
89		else if (usec_lsb > 255)
90			usec_lsb = 255;
91
92		solo_dev->usec_lsb = usec_lsb;
93		solo_reg_write(solo_dev, SOLO_TIMER_USEC_LSB,
94			       solo_dev->usec_lsb);
95	}
96}
97
98static irqreturn_t solo_isr(int irq, void *data)
99{
100	struct solo_dev *solo_dev = data;
101	u32 status;
102	int i;
103
104	status = solo_reg_read(solo_dev, SOLO_IRQ_STAT);
105	if (!status)
106		return IRQ_NONE;
107
108	/* Acknowledge all interrupts immediately */
109	solo_reg_write(solo_dev, SOLO_IRQ_STAT, status);
110
111	if (status & SOLO_IRQ_PCI_ERR)
112		solo_p2m_error_isr(solo_dev);
113
114	for (i = 0; i < SOLO_NR_P2M; i++)
115		if (status & SOLO_IRQ_P2M(i))
116			solo_p2m_isr(solo_dev, i);
117
118	if (status & SOLO_IRQ_IIC)
119		solo_i2c_isr(solo_dev);
120
121	if (status & SOLO_IRQ_VIDEO_IN) {
122		solo_video_in_isr(solo_dev);
123		solo_timer_sync(solo_dev);
124	}
125
126	if (status & SOLO_IRQ_ENCODER)
127		solo_enc_v4l2_isr(solo_dev);
128
129	if (status & SOLO_IRQ_G723)
130		solo_g723_isr(solo_dev);
131
132	return IRQ_HANDLED;
133}
134
135static void free_solo_dev(struct solo_dev *solo_dev)
136{
137	struct pci_dev *pdev;
138
139	if (!solo_dev)
140		return;
141
142	if (solo_dev->dev.parent)
143		device_unregister(&solo_dev->dev);
144
145	pdev = solo_dev->pdev;
146
147	/* If we never initialized the PCI device, then nothing else
148	 * below here needs cleanup */
149	if (!pdev) {
150		kfree(solo_dev);
151		return;
152	}
153
154	if (solo_dev->reg_base) {
155		/* Bring down the sub-devices first */
156		solo_g723_exit(solo_dev);
157		solo_enc_v4l2_exit(solo_dev);
158		solo_enc_exit(solo_dev);
159		solo_v4l2_exit(solo_dev);
160		solo_disp_exit(solo_dev);
161		solo_gpio_exit(solo_dev);
162		solo_p2m_exit(solo_dev);
163		solo_i2c_exit(solo_dev);
164
165		/* Now cleanup the PCI device */
166		solo_irq_off(solo_dev, ~0);
167		pci_iounmap(pdev, solo_dev->reg_base);
168		if (pdev->irq)
169			free_irq(pdev->irq, solo_dev);
170	}
171
172	pci_release_regions(pdev);
173	pci_disable_device(pdev);
174	v4l2_device_unregister(&solo_dev->v4l2_dev);
175	pci_set_drvdata(pdev, NULL);
176
177	kfree(solo_dev);
178}
179
180static ssize_t eeprom_store(struct device *dev, struct device_attribute *attr,
181			    const char *buf, size_t count)
182{
183	struct solo_dev *solo_dev =
184		container_of(dev, struct solo_dev, dev);
185	u16 *p = (u16 *)buf;
186	int i;
187
188	if (count & 0x1)
189		dev_warn(dev, "EEPROM Write not aligned (truncating)\n");
190
191	if (!full_eeprom && count > 64) {
192		dev_warn(dev, "EEPROM Write truncated to 64 bytes\n");
193		count = 64;
194	} else if (full_eeprom && count > 128) {
195		dev_warn(dev, "EEPROM Write truncated to 128 bytes\n");
196		count = 128;
197	}
198
199	solo_eeprom_ewen(solo_dev, 1);
200
201	for (i = full_eeprom ? 0 : 32; i < min((int)(full_eeprom ? 64 : 32),
202					       (int)(count / 2)); i++)
203		solo_eeprom_write(solo_dev, i, cpu_to_be16(p[i]));
204
205	solo_eeprom_ewen(solo_dev, 0);
206
207	return count;
208}
209
210static ssize_t eeprom_show(struct device *dev, struct device_attribute *attr,
211			   char *buf)
212{
213	struct solo_dev *solo_dev =
214		container_of(dev, struct solo_dev, dev);
215	u16 *p = (u16 *)buf;
216	int count = (full_eeprom ? 128 : 64);
217	int i;
218
219	for (i = (full_eeprom ? 0 : 32); i < (count / 2); i++)
220		p[i] = be16_to_cpu(solo_eeprom_read(solo_dev, i));
221
222	return count;
223}
224
225static ssize_t p2m_timeouts_show(struct device *dev,
226				 struct device_attribute *attr,
227				 char *buf)
228{
229	struct solo_dev *solo_dev =
230		container_of(dev, struct solo_dev, dev);
231
232	return sprintf(buf, "%d\n", solo_dev->p2m_timeouts);
233}
234
235static ssize_t sdram_size_show(struct device *dev,
236			       struct device_attribute *attr,
237			       char *buf)
238{
239	struct solo_dev *solo_dev =
240		container_of(dev, struct solo_dev, dev);
241
242	return sprintf(buf, "%dMegs\n", solo_dev->sdram_size >> 20);
243}
244
245static ssize_t tw28xx_show(struct device *dev,
246			   struct device_attribute *attr,
247			   char *buf)
248{
249	struct solo_dev *solo_dev =
250		container_of(dev, struct solo_dev, dev);
251
252	return sprintf(buf, "tw2815[%d] tw2864[%d] tw2865[%d]\n",
253		       hweight32(solo_dev->tw2815),
254		       hweight32(solo_dev->tw2864),
255		       hweight32(solo_dev->tw2865));
256}
257
258static ssize_t input_map_show(struct device *dev,
259			      struct device_attribute *attr,
260			      char *buf)
261{
262	struct solo_dev *solo_dev =
263		container_of(dev, struct solo_dev, dev);
264	unsigned int val;
265	char *out = buf;
266
267	val = solo_reg_read(solo_dev, SOLO_VI_CH_SWITCH_0);
268	out += sprintf(out, "Channel 0   => Input %d\n", val & 0x1f);
269	out += sprintf(out, "Channel 1   => Input %d\n", (val >> 5) & 0x1f);
270	out += sprintf(out, "Channel 2   => Input %d\n", (val >> 10) & 0x1f);
271	out += sprintf(out, "Channel 3   => Input %d\n", (val >> 15) & 0x1f);
272	out += sprintf(out, "Channel 4   => Input %d\n", (val >> 20) & 0x1f);
273	out += sprintf(out, "Channel 5   => Input %d\n", (val >> 25) & 0x1f);
274
275	val = solo_reg_read(solo_dev, SOLO_VI_CH_SWITCH_1);
276	out += sprintf(out, "Channel 6   => Input %d\n", val & 0x1f);
277	out += sprintf(out, "Channel 7   => Input %d\n", (val >> 5) & 0x1f);
278	out += sprintf(out, "Channel 8   => Input %d\n", (val >> 10) & 0x1f);
279	out += sprintf(out, "Channel 9   => Input %d\n", (val >> 15) & 0x1f);
280	out += sprintf(out, "Channel 10  => Input %d\n", (val >> 20) & 0x1f);
281	out += sprintf(out, "Channel 11  => Input %d\n", (val >> 25) & 0x1f);
282
283	val = solo_reg_read(solo_dev, SOLO_VI_CH_SWITCH_2);
284	out += sprintf(out, "Channel 12  => Input %d\n", val & 0x1f);
285	out += sprintf(out, "Channel 13  => Input %d\n", (val >> 5) & 0x1f);
286	out += sprintf(out, "Channel 14  => Input %d\n", (val >> 10) & 0x1f);
287	out += sprintf(out, "Channel 15  => Input %d\n", (val >> 15) & 0x1f);
288	out += sprintf(out, "Spot Output => Input %d\n", (val >> 20) & 0x1f);
289
290	return out - buf;
291}
292
293static ssize_t p2m_timeout_store(struct device *dev,
294				 struct device_attribute *attr,
295				 const char *buf, size_t count)
296{
297	struct solo_dev *solo_dev =
298		container_of(dev, struct solo_dev, dev);
299	unsigned long ms;
300	int ret = kstrtoul(buf, 10, &ms);
301
302	if (ret < 0 || ms > 200)
303		return -EINVAL;
304	solo_dev->p2m_jiffies = msecs_to_jiffies(ms);
305
306	return count;
307}
308
309static ssize_t p2m_timeout_show(struct device *dev,
310				struct device_attribute *attr,
311				char *buf)
312{
313	struct solo_dev *solo_dev =
314		container_of(dev, struct solo_dev, dev);
315
316	return sprintf(buf, "%ums\n", jiffies_to_msecs(solo_dev->p2m_jiffies));
317}
318
319static ssize_t intervals_show(struct device *dev,
320			      struct device_attribute *attr,
321			      char *buf)
322{
323	struct solo_dev *solo_dev =
324		container_of(dev, struct solo_dev, dev);
325	char *out = buf;
326	int fps = solo_dev->fps;
327	int i;
328
329	for (i = 0; i < solo_dev->nr_chans; i++) {
330		out += sprintf(out, "Channel %d: %d/%d (0x%08x)\n",
331			       i, solo_dev->v4l2_enc[i]->interval, fps,
332			       solo_reg_read(solo_dev, SOLO_CAP_CH_INTV(i)));
333	}
334
335	return out - buf;
336}
337
338static ssize_t sdram_offsets_show(struct device *dev,
339				  struct device_attribute *attr,
340				  char *buf)
341{
342	struct solo_dev *solo_dev =
343		container_of(dev, struct solo_dev, dev);
344	char *out = buf;
345
346	out += sprintf(out, "DISP: 0x%08x @ 0x%08x\n",
347		       SOLO_DISP_EXT_ADDR,
348		       SOLO_DISP_EXT_SIZE);
349
350	out += sprintf(out, "EOSD: 0x%08x @ 0x%08x (0x%08x * %d)\n",
351		       SOLO_EOSD_EXT_ADDR,
352		       SOLO_EOSD_EXT_AREA(solo_dev),
353		       SOLO_EOSD_EXT_SIZE(solo_dev),
354		       SOLO_EOSD_EXT_AREA(solo_dev) /
355		       SOLO_EOSD_EXT_SIZE(solo_dev));
356
357	out += sprintf(out, "MOTI: 0x%08x @ 0x%08x\n",
358		       SOLO_MOTION_EXT_ADDR(solo_dev),
359		       SOLO_MOTION_EXT_SIZE);
360
361	out += sprintf(out, "G723: 0x%08x @ 0x%08x\n",
362		       SOLO_G723_EXT_ADDR(solo_dev),
363		       SOLO_G723_EXT_SIZE);
364
365	out += sprintf(out, "CAPT: 0x%08x @ 0x%08x (0x%08x * %d)\n",
366		       SOLO_CAP_EXT_ADDR(solo_dev),
367		       SOLO_CAP_EXT_SIZE(solo_dev),
368		       SOLO_CAP_PAGE_SIZE,
369		       SOLO_CAP_EXT_SIZE(solo_dev) / SOLO_CAP_PAGE_SIZE);
370
371	out += sprintf(out, "EREF: 0x%08x @ 0x%08x (0x%08x * %d)\n",
372		       SOLO_EREF_EXT_ADDR(solo_dev),
373		       SOLO_EREF_EXT_AREA(solo_dev),
374		       SOLO_EREF_EXT_SIZE,
375		       SOLO_EREF_EXT_AREA(solo_dev) / SOLO_EREF_EXT_SIZE);
376
377	out += sprintf(out, "MPEG: 0x%08x @ 0x%08x\n",
378		       SOLO_MP4E_EXT_ADDR(solo_dev),
379		       SOLO_MP4E_EXT_SIZE(solo_dev));
380
381	out += sprintf(out, "JPEG: 0x%08x @ 0x%08x\n",
382		       SOLO_JPEG_EXT_ADDR(solo_dev),
383		       SOLO_JPEG_EXT_SIZE(solo_dev));
384
385	return out - buf;
386}
387
388static ssize_t sdram_show(struct file *file, struct kobject *kobj,
389			  struct bin_attribute *a, char *buf,
390			  loff_t off, size_t count)
391{
392	struct device *dev = container_of(kobj, struct device, kobj);
393	struct solo_dev *solo_dev =
394		container_of(dev, struct solo_dev, dev);
395	const int size = solo_dev->sdram_size;
396
397	if (off >= size)
398		return 0;
399
400	if (off + count > size)
401		count = size - off;
402
403	if (solo_p2m_dma(solo_dev, 0, buf, off, count, 0, 0))
404		return -EIO;
405
406	return count;
407}
408
409static const struct device_attribute solo_dev_attrs[] = {
410	__ATTR(eeprom, 0640, eeprom_show, eeprom_store),
411	__ATTR(p2m_timeout, 0644, p2m_timeout_show, p2m_timeout_store),
412	__ATTR_RO(p2m_timeouts),
413	__ATTR_RO(sdram_size),
414	__ATTR_RO(tw28xx),
415	__ATTR_RO(input_map),
416	__ATTR_RO(intervals),
417	__ATTR_RO(sdram_offsets),
418};
419
420static void solo_device_release(struct device *dev)
421{
422	/* Do nothing */
423}
424
425static int solo_sysfs_init(struct solo_dev *solo_dev)
426{
427	struct bin_attribute *sdram_attr = &solo_dev->sdram_attr;
428	struct device *dev = &solo_dev->dev;
429	const char *driver;
430	int i;
431
432	if (solo_dev->type == SOLO_DEV_6110)
433		driver = "solo6110";
434	else
435		driver = "solo6010";
436
437	dev->release = solo_device_release;
438	dev->parent = &solo_dev->pdev->dev;
439	set_dev_node(dev, dev_to_node(&solo_dev->pdev->dev));
440	dev_set_name(dev, "%s-%d-%d", driver, solo_dev->vfd->num,
441		     solo_dev->nr_chans);
442
443	if (device_register(dev)) {
444		dev->parent = NULL;
445		return -ENOMEM;
446	}
447
448	for (i = 0; i < ARRAY_SIZE(solo_dev_attrs); i++) {
449		if (device_create_file(dev, &solo_dev_attrs[i])) {
450			device_unregister(dev);
451			return -ENOMEM;
452		}
453	}
454
455	sysfs_attr_init(&sdram_attr->attr);
456	sdram_attr->attr.name = "sdram";
457	sdram_attr->attr.mode = 0440;
458	sdram_attr->read = sdram_show;
459	sdram_attr->size = solo_dev->sdram_size;
460
461	if (device_create_bin_file(dev, sdram_attr)) {
462		device_unregister(dev);
463		return -ENOMEM;
464	}
465
466	return 0;
467}
468
469static int solo_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
470{
471	struct solo_dev *solo_dev;
472	int ret;
473	u8 chip_id;
474
475	solo_dev = kzalloc(sizeof(*solo_dev), GFP_KERNEL);
476	if (solo_dev == NULL)
477		return -ENOMEM;
478
479	if (id->driver_data == SOLO_DEV_6010)
480		dev_info(&pdev->dev, "Probing Softlogic 6010\n");
481	else
482		dev_info(&pdev->dev, "Probing Softlogic 6110\n");
483
484	solo_dev->type = id->driver_data;
485	solo_dev->pdev = pdev;
486	spin_lock_init(&solo_dev->reg_io_lock);
487	ret = v4l2_device_register(&pdev->dev, &solo_dev->v4l2_dev);
488	if (ret)
489		goto fail_probe;
490
491	/* Only for during init */
492	solo_dev->p2m_jiffies = msecs_to_jiffies(100);
493
494	ret = pci_enable_device(pdev);
495	if (ret)
496		goto fail_probe;
497
498	pci_set_master(pdev);
499
500	/* RETRY/TRDY Timeout disabled */
501	pci_write_config_byte(pdev, 0x40, 0x00);
502	pci_write_config_byte(pdev, 0x41, 0x00);
503
504	ret = pci_request_regions(pdev, SOLO6X10_NAME);
505	if (ret)
506		goto fail_probe;
507
508	solo_dev->reg_base = pci_ioremap_bar(pdev, 0);
509	if (solo_dev->reg_base == NULL) {
510		ret = -ENOMEM;
511		goto fail_probe;
512	}
513
514	chip_id = solo_reg_read(solo_dev, SOLO_CHIP_OPTION) &
515				SOLO_CHIP_ID_MASK;
516	switch (chip_id) {
517	case 7:
518		solo_dev->nr_chans = 16;
519		solo_dev->nr_ext = 5;
520		break;
521	case 6:
522		solo_dev->nr_chans = 8;
523		solo_dev->nr_ext = 2;
524		break;
525	default:
526		dev_warn(&pdev->dev, "Invalid chip_id 0x%02x, assuming 4 ch\n",
527			 chip_id);
528	case 5:
529		solo_dev->nr_chans = 4;
530		solo_dev->nr_ext = 1;
531	}
532
533	/* Disable all interrupts to start */
534	solo_irq_off(solo_dev, ~0);
535
536	/* Initial global settings */
537	if (solo_dev->type == SOLO_DEV_6010) {
538		solo_dev->clock_mhz = 108;
539		solo_dev->sys_config = SOLO_SYS_CFG_SDRAM64BIT
540			| SOLO_SYS_CFG_INPUTDIV(25)
541			| SOLO_SYS_CFG_FEEDBACKDIV(solo_dev->clock_mhz * 2 - 2)
542			| SOLO_SYS_CFG_OUTDIV(3);
543		solo_reg_write(solo_dev, SOLO_SYS_CFG, solo_dev->sys_config);
544	} else {
545		u32 divq, divf;
546
547		solo_dev->clock_mhz = 135;
548
549		if (solo_dev->clock_mhz < 125) {
550			divq = 3;
551			divf = (solo_dev->clock_mhz * 4) / 3 - 1;
552		} else {
553			divq = 2;
554			divf = (solo_dev->clock_mhz * 2) / 3 - 1;
555		}
556
557		solo_reg_write(solo_dev, SOLO_PLL_CONFIG,
558			       (1 << 20) | /* PLL_RANGE */
559			       (8 << 15) | /* PLL_DIVR  */
560			       (divq << 12) |
561			       (divf <<  4) |
562			       (1 <<  1)   /* PLL_FSEN */);
563
564		solo_dev->sys_config = SOLO_SYS_CFG_SDRAM64BIT;
565	}
566
567	solo_reg_write(solo_dev, SOLO_SYS_CFG, solo_dev->sys_config);
568	solo_reg_write(solo_dev, SOLO_TIMER_CLOCK_NUM,
569		       solo_dev->clock_mhz - 1);
570
571	/* PLL locking time of 1ms */
572	mdelay(1);
573
574	ret = request_irq(pdev->irq, solo_isr, IRQF_SHARED, SOLO6X10_NAME,
575			  solo_dev);
576	if (ret)
577		goto fail_probe;
578
579	/* Handle this from the start */
580	solo_irq_on(solo_dev, SOLO_IRQ_PCI_ERR);
581
582	ret = solo_i2c_init(solo_dev);
583	if (ret)
584		goto fail_probe;
585
586	/* Setup the DMA engine */
587	solo_reg_write(solo_dev, SOLO_DMA_CTRL,
588		       SOLO_DMA_CTRL_REFRESH_CYCLE(1) |
589		       SOLO_DMA_CTRL_SDRAM_SIZE(2) |
590		       SOLO_DMA_CTRL_SDRAM_CLK_INVERT |
591		       SOLO_DMA_CTRL_READ_CLK_SELECT |
592		       SOLO_DMA_CTRL_LATENCY(1));
593
594	/* Undocumented crap */
595	solo_reg_write(solo_dev, SOLO_DMA_CTRL1,
596		       solo_dev->type == SOLO_DEV_6010 ? 0x100 : 0x300);
597
598	if (solo_dev->type != SOLO_DEV_6010) {
599		solo_dev->usec_lsb = 0x3f;
600		solo_set_time(solo_dev);
601	}
602
603	/* Disable watchdog */
604	solo_reg_write(solo_dev, SOLO_WATCHDOG, 0);
605
606	/* Initialize sub components */
607
608	ret = solo_p2m_init(solo_dev);
609	if (ret)
610		goto fail_probe;
611
612	ret = solo_disp_init(solo_dev);
613	if (ret)
614		goto fail_probe;
615
616	ret = solo_gpio_init(solo_dev);
617	if (ret)
618		goto fail_probe;
619
620	ret = solo_tw28_init(solo_dev);
621	if (ret)
622		goto fail_probe;
623
624	ret = solo_v4l2_init(solo_dev, video_nr);
625	if (ret)
626		goto fail_probe;
627
628	ret = solo_enc_init(solo_dev);
629	if (ret)
630		goto fail_probe;
631
632	ret = solo_enc_v4l2_init(solo_dev, video_nr);
633	if (ret)
634		goto fail_probe;
635
636	ret = solo_g723_init(solo_dev);
637	if (ret)
638		goto fail_probe;
639
640	ret = solo_sysfs_init(solo_dev);
641	if (ret)
642		goto fail_probe;
643
644	/* Now that init is over, set this lower */
645	solo_dev->p2m_jiffies = msecs_to_jiffies(20);
646
647	return 0;
648
649fail_probe:
650	free_solo_dev(solo_dev);
651	return ret;
652}
653
654static void solo_pci_remove(struct pci_dev *pdev)
655{
656	struct v4l2_device *v4l2_dev = pci_get_drvdata(pdev);
657	struct solo_dev *solo_dev = container_of(v4l2_dev, struct solo_dev, v4l2_dev);
658
659	free_solo_dev(solo_dev);
660}
661
662static const struct pci_device_id solo_id_table[] = {
663	/* 6010 based cards */
664	{ PCI_DEVICE(PCI_VENDOR_ID_SOFTLOGIC, PCI_DEVICE_ID_SOLO6010),
665	  .driver_data = SOLO_DEV_6010 },
666	{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_4),
667	  .driver_data = SOLO_DEV_6010 },
668	{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_9),
669	  .driver_data = SOLO_DEV_6010 },
670	{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_16),
671	  .driver_data = SOLO_DEV_6010 },
672	{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_4),
673	  .driver_data = SOLO_DEV_6010 },
674	{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_9),
675	  .driver_data = SOLO_DEV_6010 },
676	{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_16),
677	  .driver_data = SOLO_DEV_6010 },
678	/* 6110 based cards */
679	{ PCI_DEVICE(PCI_VENDOR_ID_SOFTLOGIC, PCI_DEVICE_ID_SOLO6110),
680	  .driver_data = SOLO_DEV_6110 },
681	{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_4),
682	  .driver_data = SOLO_DEV_6110 },
683	{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_8),
684	  .driver_data = SOLO_DEV_6110 },
685	{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_16),
686	  .driver_data = SOLO_DEV_6110 },
687	{0,}
688};
689
690MODULE_DEVICE_TABLE(pci, solo_id_table);
691
692static struct pci_driver solo_pci_driver = {
693	.name = SOLO6X10_NAME,
694	.id_table = solo_id_table,
695	.probe = solo_pci_probe,
696	.remove = solo_pci_remove,
697};
698
699module_pci_driver(solo_pci_driver);
700