Linux Audio

Check our new training course

Loading...
v3.15
  1/*
  2
  3    bt8xx GPIO abuser
  4
  5    Copyright (C) 2008 Michael Buesch <m@bues.ch>
  6
  7    Please do _only_ contact the people listed _above_ with issues related to this driver.
  8    All the other people listed below are not related to this driver. Their names
  9    are only here, because this driver is derived from the bt848 driver.
 10
 11
 12    Derived from the bt848 driver:
 13
 14    Copyright (C) 1996,97,98 Ralph  Metzler
 15			   & Marcus Metzler
 16    (c) 1999-2002 Gerd Knorr
 17
 18    some v4l2 code lines are taken from Justin's bttv2 driver which is
 19    (c) 2000 Justin Schoeman
 20
 21    V4L1 removal from:
 22    (c) 2005-2006 Nickolay V. Shmyrev
 23
 24    Fixes to be fully V4L2 compliant by
 25    (c) 2006 Mauro Carvalho Chehab
 26
 27    Cropping and overscan support
 28    Copyright (C) 2005, 2006 Michael H. Schimek
 29    Sponsored by OPQ Systems AB
 30
 31    This program is free software; you can redistribute it and/or modify
 32    it under the terms of the GNU General Public License as published by
 33    the Free Software Foundation; either version 2 of the License, or
 34    (at your option) any later version.
 35
 36    This program is distributed in the hope that it will be useful,
 37    but WITHOUT ANY WARRANTY; without even the implied warranty of
 38    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 39    GNU General Public License for more details.
 40
 41    You should have received a copy of the GNU General Public License
 42    along with this program; if not, write to the Free Software
 43    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 44*/
 45
 46#include <linux/module.h>
 47#include <linux/pci.h>
 48#include <linux/spinlock.h>
 49#include <linux/gpio.h>
 50#include <linux/slab.h>
 51
 52/* Steal the hardware definitions from the bttv driver. */
 53#include "../media/pci/bt8xx/bt848.h"
 54
 55
 56#define BT8XXGPIO_NR_GPIOS		24 /* We have 24 GPIO pins */
 57
 58
 59struct bt8xxgpio {
 60	spinlock_t lock;
 61
 62	void __iomem *mmio;
 63	struct pci_dev *pdev;
 64	struct gpio_chip gpio;
 65
 66#ifdef CONFIG_PM
 67	u32 saved_outen;
 68	u32 saved_data;
 69#endif
 70};
 71
 72#define bgwrite(dat, adr)	writel((dat), bg->mmio+(adr))
 73#define bgread(adr)		readl(bg->mmio+(adr))
 74
 75
 76static int modparam_gpiobase = -1/* dynamic */;
 77module_param_named(gpiobase, modparam_gpiobase, int, 0444);
 78MODULE_PARM_DESC(gpiobase, "The GPIO number base. -1 means dynamic, which is the default.");
 79
 80
 81static int bt8xxgpio_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
 82{
 83	struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
 84	unsigned long flags;
 85	u32 outen, data;
 86
 87	spin_lock_irqsave(&bg->lock, flags);
 88
 89	data = bgread(BT848_GPIO_DATA);
 90	data &= ~(1 << nr);
 91	bgwrite(data, BT848_GPIO_DATA);
 92
 93	outen = bgread(BT848_GPIO_OUT_EN);
 94	outen &= ~(1 << nr);
 95	bgwrite(outen, BT848_GPIO_OUT_EN);
 96
 97	spin_unlock_irqrestore(&bg->lock, flags);
 98
 99	return 0;
100}
101
102static int bt8xxgpio_gpio_get(struct gpio_chip *gpio, unsigned nr)
103{
104	struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
105	unsigned long flags;
106	u32 val;
107
108	spin_lock_irqsave(&bg->lock, flags);
109	val = bgread(BT848_GPIO_DATA);
110	spin_unlock_irqrestore(&bg->lock, flags);
111
112	return !!(val & (1 << nr));
113}
114
115static int bt8xxgpio_gpio_direction_output(struct gpio_chip *gpio,
116					unsigned nr, int val)
117{
118	struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
119	unsigned long flags;
120	u32 outen, data;
121
122	spin_lock_irqsave(&bg->lock, flags);
123
124	outen = bgread(BT848_GPIO_OUT_EN);
125	outen |= (1 << nr);
126	bgwrite(outen, BT848_GPIO_OUT_EN);
127
128	data = bgread(BT848_GPIO_DATA);
129	if (val)
130		data |= (1 << nr);
131	else
132		data &= ~(1 << nr);
133	bgwrite(data, BT848_GPIO_DATA);
134
135	spin_unlock_irqrestore(&bg->lock, flags);
136
137	return 0;
138}
139
140static void bt8xxgpio_gpio_set(struct gpio_chip *gpio,
141			    unsigned nr, int val)
142{
143	struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
144	unsigned long flags;
145	u32 data;
146
147	spin_lock_irqsave(&bg->lock, flags);
148
149	data = bgread(BT848_GPIO_DATA);
150	if (val)
151		data |= (1 << nr);
152	else
153		data &= ~(1 << nr);
154	bgwrite(data, BT848_GPIO_DATA);
155
156	spin_unlock_irqrestore(&bg->lock, flags);
157}
158
159static void bt8xxgpio_gpio_setup(struct bt8xxgpio *bg)
160{
161	struct gpio_chip *c = &bg->gpio;
162
163	c->label = dev_name(&bg->pdev->dev);
164	c->owner = THIS_MODULE;
165	c->direction_input = bt8xxgpio_gpio_direction_input;
166	c->get = bt8xxgpio_gpio_get;
167	c->direction_output = bt8xxgpio_gpio_direction_output;
168	c->set = bt8xxgpio_gpio_set;
169	c->dbg_show = NULL;
170	c->base = modparam_gpiobase;
171	c->ngpio = BT8XXGPIO_NR_GPIOS;
172	c->can_sleep = false;
173}
174
175static int bt8xxgpio_probe(struct pci_dev *dev,
176			const struct pci_device_id *pci_id)
177{
178	struct bt8xxgpio *bg;
179	int err;
180
181	bg = kzalloc(sizeof(*bg), GFP_KERNEL);
182	if (!bg)
183		return -ENOMEM;
184
185	bg->pdev = dev;
186	spin_lock_init(&bg->lock);
187
188	err = pci_enable_device(dev);
189	if (err) {
190		printk(KERN_ERR "bt8xxgpio: Can't enable device.\n");
191		goto err_freebg;
192	}
193	if (!request_mem_region(pci_resource_start(dev, 0),
194				pci_resource_len(dev, 0),
195				"bt8xxgpio")) {
196		printk(KERN_WARNING "bt8xxgpio: Can't request iomem (0x%llx).\n",
197		       (unsigned long long)pci_resource_start(dev, 0));
198		err = -EBUSY;
199		goto err_disable;
200	}
201	pci_set_master(dev);
202	pci_set_drvdata(dev, bg);
203
204	bg->mmio = ioremap(pci_resource_start(dev, 0), 0x1000);
205	if (!bg->mmio) {
206		printk(KERN_ERR "bt8xxgpio: ioremap() failed\n");
207		err = -EIO;
208		goto err_release_mem;
209	}
210
211	/* Disable interrupts */
212	bgwrite(0, BT848_INT_MASK);
213
214	/* gpio init */
215	bgwrite(0, BT848_GPIO_DMA_CTL);
216	bgwrite(0, BT848_GPIO_REG_INP);
217	bgwrite(0, BT848_GPIO_OUT_EN);
218
219	bt8xxgpio_gpio_setup(bg);
220	err = gpiochip_add(&bg->gpio);
221	if (err) {
222		printk(KERN_ERR "bt8xxgpio: Failed to register GPIOs\n");
223		goto err_release_mem;
224	}
225
226	return 0;
227
228err_release_mem:
229	release_mem_region(pci_resource_start(dev, 0),
230			   pci_resource_len(dev, 0));
231err_disable:
232	pci_disable_device(dev);
233err_freebg:
234	kfree(bg);
235
236	return err;
237}
238
239static void bt8xxgpio_remove(struct pci_dev *pdev)
240{
241	struct bt8xxgpio *bg = pci_get_drvdata(pdev);
242
243	gpiochip_remove(&bg->gpio);
244
245	bgwrite(0, BT848_INT_MASK);
246	bgwrite(~0x0, BT848_INT_STAT);
247	bgwrite(0x0, BT848_GPIO_OUT_EN);
248
249	iounmap(bg->mmio);
250	release_mem_region(pci_resource_start(pdev, 0),
251			   pci_resource_len(pdev, 0));
252	pci_disable_device(pdev);
253
254	kfree(bg);
255}
256
257#ifdef CONFIG_PM
258static int bt8xxgpio_suspend(struct pci_dev *pdev, pm_message_t state)
259{
260	struct bt8xxgpio *bg = pci_get_drvdata(pdev);
261	unsigned long flags;
262
263	spin_lock_irqsave(&bg->lock, flags);
264
265	bg->saved_outen = bgread(BT848_GPIO_OUT_EN);
266	bg->saved_data = bgread(BT848_GPIO_DATA);
267
268	bgwrite(0, BT848_INT_MASK);
269	bgwrite(~0x0, BT848_INT_STAT);
270	bgwrite(0x0, BT848_GPIO_OUT_EN);
271
272	spin_unlock_irqrestore(&bg->lock, flags);
273
274	pci_save_state(pdev);
275	pci_disable_device(pdev);
276	pci_set_power_state(pdev, pci_choose_state(pdev, state));
277
278	return 0;
279}
280
281static int bt8xxgpio_resume(struct pci_dev *pdev)
282{
283	struct bt8xxgpio *bg = pci_get_drvdata(pdev);
284	unsigned long flags;
285	int err;
286
287	pci_set_power_state(pdev, PCI_D0);
288	err = pci_enable_device(pdev);
289	if (err)
290		return err;
291	pci_restore_state(pdev);
292
293	spin_lock_irqsave(&bg->lock, flags);
294
295	bgwrite(0, BT848_INT_MASK);
296	bgwrite(0, BT848_GPIO_DMA_CTL);
297	bgwrite(0, BT848_GPIO_REG_INP);
298	bgwrite(bg->saved_outen, BT848_GPIO_OUT_EN);
299	bgwrite(bg->saved_data & bg->saved_outen,
300		BT848_GPIO_DATA);
301
302	spin_unlock_irqrestore(&bg->lock, flags);
303
304	return 0;
305}
306#else
307#define bt8xxgpio_suspend NULL
308#define bt8xxgpio_resume NULL
309#endif /* CONFIG_PM */
310
311static const struct pci_device_id bt8xxgpio_pci_tbl[] = {
312	{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848) },
313	{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849) },
314	{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878) },
315	{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879) },
316	{ 0, },
317};
318MODULE_DEVICE_TABLE(pci, bt8xxgpio_pci_tbl);
319
320static struct pci_driver bt8xxgpio_pci_driver = {
321	.name		= "bt8xxgpio",
322	.id_table	= bt8xxgpio_pci_tbl,
323	.probe		= bt8xxgpio_probe,
324	.remove		= bt8xxgpio_remove,
325	.suspend	= bt8xxgpio_suspend,
326	.resume		= bt8xxgpio_resume,
327};
328
329module_pci_driver(bt8xxgpio_pci_driver);
330
331MODULE_LICENSE("GPL");
332MODULE_AUTHOR("Michael Buesch");
333MODULE_DESCRIPTION("Abuse a BT8xx framegrabber card as generic GPIO card");
v4.6
  1/*
  2
  3    bt8xx GPIO abuser
  4
  5    Copyright (C) 2008 Michael Buesch <m@bues.ch>
  6
  7    Please do _only_ contact the people listed _above_ with issues related to this driver.
  8    All the other people listed below are not related to this driver. Their names
  9    are only here, because this driver is derived from the bt848 driver.
 10
 11
 12    Derived from the bt848 driver:
 13
 14    Copyright (C) 1996,97,98 Ralph  Metzler
 15			   & Marcus Metzler
 16    (c) 1999-2002 Gerd Knorr
 17
 18    some v4l2 code lines are taken from Justin's bttv2 driver which is
 19    (c) 2000 Justin Schoeman
 20
 21    V4L1 removal from:
 22    (c) 2005-2006 Nickolay V. Shmyrev
 23
 24    Fixes to be fully V4L2 compliant by
 25    (c) 2006 Mauro Carvalho Chehab
 26
 27    Cropping and overscan support
 28    Copyright (C) 2005, 2006 Michael H. Schimek
 29    Sponsored by OPQ Systems AB
 30
 31    This program is free software; you can redistribute it and/or modify
 32    it under the terms of the GNU General Public License as published by
 33    the Free Software Foundation; either version 2 of the License, or
 34    (at your option) any later version.
 35
 36    This program is distributed in the hope that it will be useful,
 37    but WITHOUT ANY WARRANTY; without even the implied warranty of
 38    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 39    GNU General Public License for more details.
 40
 41    You should have received a copy of the GNU General Public License
 42    along with this program; if not, write to the Free Software
 43    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 44*/
 45
 46#include <linux/module.h>
 47#include <linux/pci.h>
 48#include <linux/spinlock.h>
 49#include <linux/gpio.h>
 50#include <linux/slab.h>
 51
 52/* Steal the hardware definitions from the bttv driver. */
 53#include "../media/pci/bt8xx/bt848.h"
 54
 55
 56#define BT8XXGPIO_NR_GPIOS		24 /* We have 24 GPIO pins */
 57
 58
 59struct bt8xxgpio {
 60	spinlock_t lock;
 61
 62	void __iomem *mmio;
 63	struct pci_dev *pdev;
 64	struct gpio_chip gpio;
 65
 66#ifdef CONFIG_PM
 67	u32 saved_outen;
 68	u32 saved_data;
 69#endif
 70};
 71
 72#define bgwrite(dat, adr)	writel((dat), bg->mmio+(adr))
 73#define bgread(adr)		readl(bg->mmio+(adr))
 74
 75
 76static int modparam_gpiobase = -1/* dynamic */;
 77module_param_named(gpiobase, modparam_gpiobase, int, 0444);
 78MODULE_PARM_DESC(gpiobase, "The GPIO number base. -1 means dynamic, which is the default.");
 79
 80
 81static int bt8xxgpio_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
 82{
 83	struct bt8xxgpio *bg = gpiochip_get_data(gpio);
 84	unsigned long flags;
 85	u32 outen, data;
 86
 87	spin_lock_irqsave(&bg->lock, flags);
 88
 89	data = bgread(BT848_GPIO_DATA);
 90	data &= ~(1 << nr);
 91	bgwrite(data, BT848_GPIO_DATA);
 92
 93	outen = bgread(BT848_GPIO_OUT_EN);
 94	outen &= ~(1 << nr);
 95	bgwrite(outen, BT848_GPIO_OUT_EN);
 96
 97	spin_unlock_irqrestore(&bg->lock, flags);
 98
 99	return 0;
100}
101
102static int bt8xxgpio_gpio_get(struct gpio_chip *gpio, unsigned nr)
103{
104	struct bt8xxgpio *bg = gpiochip_get_data(gpio);
105	unsigned long flags;
106	u32 val;
107
108	spin_lock_irqsave(&bg->lock, flags);
109	val = bgread(BT848_GPIO_DATA);
110	spin_unlock_irqrestore(&bg->lock, flags);
111
112	return !!(val & (1 << nr));
113}
114
115static int bt8xxgpio_gpio_direction_output(struct gpio_chip *gpio,
116					unsigned nr, int val)
117{
118	struct bt8xxgpio *bg = gpiochip_get_data(gpio);
119	unsigned long flags;
120	u32 outen, data;
121
122	spin_lock_irqsave(&bg->lock, flags);
123
124	outen = bgread(BT848_GPIO_OUT_EN);
125	outen |= (1 << nr);
126	bgwrite(outen, BT848_GPIO_OUT_EN);
127
128	data = bgread(BT848_GPIO_DATA);
129	if (val)
130		data |= (1 << nr);
131	else
132		data &= ~(1 << nr);
133	bgwrite(data, BT848_GPIO_DATA);
134
135	spin_unlock_irqrestore(&bg->lock, flags);
136
137	return 0;
138}
139
140static void bt8xxgpio_gpio_set(struct gpio_chip *gpio,
141			    unsigned nr, int val)
142{
143	struct bt8xxgpio *bg = gpiochip_get_data(gpio);
144	unsigned long flags;
145	u32 data;
146
147	spin_lock_irqsave(&bg->lock, flags);
148
149	data = bgread(BT848_GPIO_DATA);
150	if (val)
151		data |= (1 << nr);
152	else
153		data &= ~(1 << nr);
154	bgwrite(data, BT848_GPIO_DATA);
155
156	spin_unlock_irqrestore(&bg->lock, flags);
157}
158
159static void bt8xxgpio_gpio_setup(struct bt8xxgpio *bg)
160{
161	struct gpio_chip *c = &bg->gpio;
162
163	c->label = dev_name(&bg->pdev->dev);
164	c->owner = THIS_MODULE;
165	c->direction_input = bt8xxgpio_gpio_direction_input;
166	c->get = bt8xxgpio_gpio_get;
167	c->direction_output = bt8xxgpio_gpio_direction_output;
168	c->set = bt8xxgpio_gpio_set;
169	c->dbg_show = NULL;
170	c->base = modparam_gpiobase;
171	c->ngpio = BT8XXGPIO_NR_GPIOS;
172	c->can_sleep = false;
173}
174
175static int bt8xxgpio_probe(struct pci_dev *dev,
176			const struct pci_device_id *pci_id)
177{
178	struct bt8xxgpio *bg;
179	int err;
180
181	bg = devm_kzalloc(&dev->dev, sizeof(struct bt8xxgpio), GFP_KERNEL);
182	if (!bg)
183		return -ENOMEM;
184
185	bg->pdev = dev;
186	spin_lock_init(&bg->lock);
187
188	err = pci_enable_device(dev);
189	if (err) {
190		printk(KERN_ERR "bt8xxgpio: Can't enable device.\n");
191		return err;
192	}
193	if (!devm_request_mem_region(&dev->dev, pci_resource_start(dev, 0),
194				pci_resource_len(dev, 0),
195				"bt8xxgpio")) {
196		printk(KERN_WARNING "bt8xxgpio: Can't request iomem (0x%llx).\n",
197		       (unsigned long long)pci_resource_start(dev, 0));
198		err = -EBUSY;
199		goto err_disable;
200	}
201	pci_set_master(dev);
202	pci_set_drvdata(dev, bg);
203
204	bg->mmio = devm_ioremap(&dev->dev, pci_resource_start(dev, 0), 0x1000);
205	if (!bg->mmio) {
206		printk(KERN_ERR "bt8xxgpio: ioremap() failed\n");
207		err = -EIO;
208		goto err_disable;
209	}
210
211	/* Disable interrupts */
212	bgwrite(0, BT848_INT_MASK);
213
214	/* gpio init */
215	bgwrite(0, BT848_GPIO_DMA_CTL);
216	bgwrite(0, BT848_GPIO_REG_INP);
217	bgwrite(0, BT848_GPIO_OUT_EN);
218
219	bt8xxgpio_gpio_setup(bg);
220	err = gpiochip_add_data(&bg->gpio, bg);
221	if (err) {
222		printk(KERN_ERR "bt8xxgpio: Failed to register GPIOs\n");
223		goto err_disable;
224	}
225
226	return 0;
227
 
 
 
228err_disable:
229	pci_disable_device(dev);
 
 
230
231	return err;
232}
233
234static void bt8xxgpio_remove(struct pci_dev *pdev)
235{
236	struct bt8xxgpio *bg = pci_get_drvdata(pdev);
237
238	gpiochip_remove(&bg->gpio);
239
240	bgwrite(0, BT848_INT_MASK);
241	bgwrite(~0x0, BT848_INT_STAT);
242	bgwrite(0x0, BT848_GPIO_OUT_EN);
243
 
 
 
244	pci_disable_device(pdev);
 
 
245}
246
247#ifdef CONFIG_PM
248static int bt8xxgpio_suspend(struct pci_dev *pdev, pm_message_t state)
249{
250	struct bt8xxgpio *bg = pci_get_drvdata(pdev);
251	unsigned long flags;
252
253	spin_lock_irqsave(&bg->lock, flags);
254
255	bg->saved_outen = bgread(BT848_GPIO_OUT_EN);
256	bg->saved_data = bgread(BT848_GPIO_DATA);
257
258	bgwrite(0, BT848_INT_MASK);
259	bgwrite(~0x0, BT848_INT_STAT);
260	bgwrite(0x0, BT848_GPIO_OUT_EN);
261
262	spin_unlock_irqrestore(&bg->lock, flags);
263
264	pci_save_state(pdev);
265	pci_disable_device(pdev);
266	pci_set_power_state(pdev, pci_choose_state(pdev, state));
267
268	return 0;
269}
270
271static int bt8xxgpio_resume(struct pci_dev *pdev)
272{
273	struct bt8xxgpio *bg = pci_get_drvdata(pdev);
274	unsigned long flags;
275	int err;
276
277	pci_set_power_state(pdev, PCI_D0);
278	err = pci_enable_device(pdev);
279	if (err)
280		return err;
281	pci_restore_state(pdev);
282
283	spin_lock_irqsave(&bg->lock, flags);
284
285	bgwrite(0, BT848_INT_MASK);
286	bgwrite(0, BT848_GPIO_DMA_CTL);
287	bgwrite(0, BT848_GPIO_REG_INP);
288	bgwrite(bg->saved_outen, BT848_GPIO_OUT_EN);
289	bgwrite(bg->saved_data & bg->saved_outen,
290		BT848_GPIO_DATA);
291
292	spin_unlock_irqrestore(&bg->lock, flags);
293
294	return 0;
295}
296#else
297#define bt8xxgpio_suspend NULL
298#define bt8xxgpio_resume NULL
299#endif /* CONFIG_PM */
300
301static const struct pci_device_id bt8xxgpio_pci_tbl[] = {
302	{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848) },
303	{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849) },
304	{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878) },
305	{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879) },
306	{ 0, },
307};
308MODULE_DEVICE_TABLE(pci, bt8xxgpio_pci_tbl);
309
310static struct pci_driver bt8xxgpio_pci_driver = {
311	.name		= "bt8xxgpio",
312	.id_table	= bt8xxgpio_pci_tbl,
313	.probe		= bt8xxgpio_probe,
314	.remove		= bt8xxgpio_remove,
315	.suspend	= bt8xxgpio_suspend,
316	.resume		= bt8xxgpio_resume,
317};
318
319module_pci_driver(bt8xxgpio_pci_driver);
320
321MODULE_LICENSE("GPL");
322MODULE_AUTHOR("Michael Buesch");
323MODULE_DESCRIPTION("Abuse a BT8xx framegrabber card as generic GPIO card");