Merge tag 'iio-for-4.8b' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio...
[deliverable/linux.git] / drivers / staging / media / tw686x-kh / tw686x-kh-core.c
1 /*
2 * Copyright (C) 2015 Industrial Research Institute for Automation
3 * and Measurements PIAP
4 *
5 * Written by Krzysztof Ha?asa.
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of version 2 of the GNU General Public License
9 * as published by the Free Software Foundation.
10 */
11
12 #include <linux/init.h>
13 #include <linux/interrupt.h>
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/slab.h>
17 #include "tw686x-kh.h"
18 #include "tw686x-kh-regs.h"
19
20 static irqreturn_t tw686x_irq(int irq, void *dev_id)
21 {
22 struct tw686x_dev *dev = (struct tw686x_dev *)dev_id;
23 u32 int_status = reg_read(dev, INT_STATUS); /* cleared on read */
24 unsigned long flags;
25 unsigned int handled = 0;
26
27 if (int_status) {
28 spin_lock_irqsave(&dev->irq_lock, flags);
29 dev->dma_requests |= int_status;
30 spin_unlock_irqrestore(&dev->irq_lock, flags);
31
32 if (int_status & 0xFF0000FF)
33 handled = tw686x_kh_video_irq(dev);
34 }
35
36 return IRQ_RETVAL(handled);
37 }
38
39 static int tw686x_probe(struct pci_dev *pci_dev,
40 const struct pci_device_id *pci_id)
41 {
42 struct tw686x_dev *dev;
43 int err;
44
45 dev = devm_kzalloc(&pci_dev->dev, sizeof(*dev) +
46 (pci_id->driver_data & TYPE_MAX_CHANNELS) *
47 sizeof(dev->video_channels[0]), GFP_KERNEL);
48 if (!dev)
49 return -ENOMEM;
50
51 sprintf(dev->name, "TW%04X", pci_dev->device);
52 dev->type = pci_id->driver_data;
53
54 pr_info("%s: PCI %s, IRQ %d, MMIO 0x%lx\n", dev->name,
55 pci_name(pci_dev), pci_dev->irq,
56 (unsigned long)pci_resource_start(pci_dev, 0));
57
58 dev->pci_dev = pci_dev;
59 if (pcim_enable_device(pci_dev))
60 return -EIO;
61
62 pci_set_master(pci_dev);
63
64 if (pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32))) {
65 pr_err("%s: 32-bit PCI DMA not supported\n", dev->name);
66 return -EIO;
67 }
68
69 err = pci_request_regions(pci_dev, dev->name);
70 if (err < 0) {
71 pr_err("%s: Unable to get MMIO region\n", dev->name);
72 return err;
73 }
74
75 dev->mmio = pci_ioremap_bar(pci_dev, 0);
76 if (!dev->mmio) {
77 pr_err("%s: Unable to remap MMIO region\n", dev->name);
78 return -EIO;
79 }
80
81 reg_write(dev, SYS_SOFT_RST, 0x0F); /* Reset all subsystems */
82 mdelay(1);
83
84 reg_write(dev, SRST[0], 0x3F);
85 if (max_channels(dev) > 4)
86 reg_write(dev, SRST[1], 0x3F);
87 reg_write(dev, DMA_CMD, 0);
88 reg_write(dev, DMA_CHANNEL_ENABLE, 0);
89 reg_write(dev, DMA_CHANNEL_TIMEOUT, 0x3EFF0FF0);
90 reg_write(dev, DMA_TIMER_INTERVAL, 0x38000);
91 reg_write(dev, DMA_CONFIG, 0xFFFFFF04);
92
93 spin_lock_init(&dev->irq_lock);
94
95 err = devm_request_irq(&pci_dev->dev, pci_dev->irq, tw686x_irq,
96 IRQF_SHARED, dev->name, dev);
97 if (err < 0) {
98 pr_err("%s: Unable to get IRQ\n", dev->name);
99 return err;
100 }
101
102 err = tw686x_kh_video_init(dev);
103 if (err)
104 return err;
105
106 pci_set_drvdata(pci_dev, dev);
107 return 0;
108 }
109
110 static void tw686x_remove(struct pci_dev *pci_dev)
111 {
112 struct tw686x_dev *dev = pci_get_drvdata(pci_dev);
113
114 tw686x_kh_video_free(dev);
115 }
116
117 /* driver_data is number of A/V channels */
118 static const struct pci_device_id tw686x_pci_tbl[] = {
119 {PCI_DEVICE(0x1797, 0x6864), .driver_data = 4},
120 /* not tested */
121 {PCI_DEVICE(0x1797, 0x6865), .driver_data = 4 | TYPE_SECOND_GEN},
122 /* TW6868 supports 8 A/V channels with an external TW2865 chip -
123 not supported by the driver */
124 {PCI_DEVICE(0x1797, 0x6868), .driver_data = 4}, /* not tested */
125 {PCI_DEVICE(0x1797, 0x6869), .driver_data = 8 | TYPE_SECOND_GEN},
126 {}
127 };
128
129 static struct pci_driver tw686x_pci_driver = {
130 .name = "tw686x-kh",
131 .id_table = tw686x_pci_tbl,
132 .probe = tw686x_probe,
133 .remove = tw686x_remove,
134 };
135
136 MODULE_DESCRIPTION("Driver for video frame grabber cards based on Intersil/Techwell TW686[4589]");
137 MODULE_AUTHOR("Krzysztof Halasa");
138 MODULE_LICENSE("GPL v2");
139 MODULE_DEVICE_TABLE(pci, tw686x_pci_tbl);
140 module_pci_driver(tw686x_pci_driver);
This page took 0.035021 seconds and 6 git commands to generate.