From: Domenico Andreoli <cavokz@gmail.com>
To: David Brownell <david-b@pacbell.net>
Cc: video4linux-list@redhat.com, Michael Buesch <mb@bu3sch.de>,
Mauro Carvalho Chehab <mchehab@infradead.org>
Subject: Re: [PATCH v3] Add bt8xxgpio driver
Date: Mon, 14 Jul 2008 09:27:33 +0200 [thread overview]
Message-ID: <20080714072733.GA29908@ska.dandreoli.com> (raw)
In-Reply-To: <200807132259.54360.david-b@pacbell.net>
On Sun, Jul 13, 2008 at 10:59:54PM -0700, David Brownell wrote:
> On Sunday 13 July 2008, Domenico Andreoli wrote:
> > Say that a given card has 4 relays attached to its GPIOs. Only the
> > card's driver may know about these relays and only the driver should
> > be able to set those GPIO directions. Moreover, driver should prevent
> > direction change for them, which are intended for output only.
> >
> > While I figure out how to prevent user direction tampering, how about
> > making gpiolib know which are the initial directions?
>
> I don't quite follow. If you export the GPIOs to userspace using
> the (pending, to-appear-in-2.6.27) sysfs interface, you can use
I already tried it, very nifty. I used it to show my driver is working,
I could hear the relays and see the tester.. yuk!
Anyway I was too free to play with GPIOs, I would like to be able to
set limits at driver level. i.e. relay GPIOs should be output only and
no one, being another driver or user-space, should be able to change
their direction.
While I am able to enforce direction policy, I am not able to setup the
initial direction. Indeed it is set by gpiolib basing on the presence
of chip.direction_input.
cheers,
Domenico
This patch adds the gpiolib bttv sub-driver.
Every bttv card may define a set of available gpio ports which are
registered to gpiolib and then made available through kernel's generic
gpio interface.
--
State of the patch: working. RFC.
Index: v4l-dvb.git/drivers/media/video/bt8xx/Kconfig
===================================================================
--- v4l-dvb.git.orig/drivers/media/video/bt8xx/Kconfig 2008-07-14 06:33:54.000000000 +0200
+++ v4l-dvb.git/drivers/media/video/bt8xx/Kconfig 2008-07-14 06:33:58.000000000 +0200
@@ -21,6 +21,12 @@
To compile this driver as a module, choose M here: the
module will be called bttv.
+config VIDEO_BT848_GPIO
+ tristate "GPIO support for bt848 cards"
+ depends on VIDEO_BT848 && GPIOLIB
+ ---help---
+ This enables GPIOLIB bindings on BT848 boards.
+
config VIDEO_BT848_DVB
bool "DVB/ATSC Support for bt878 based TV cards"
depends on VIDEO_BT848 && DVB_CORE
Index: v4l-dvb.git/drivers/media/video/bt8xx/Makefile
===================================================================
--- v4l-dvb.git.orig/drivers/media/video/bt8xx/Makefile 2008-07-14 06:33:54.000000000 +0200
+++ v4l-dvb.git/drivers/media/video/bt8xx/Makefile 2008-07-14 06:33:58.000000000 +0200
@@ -7,6 +7,7 @@
bttv-input.o bttv-audio-hook.o
obj-$(CONFIG_VIDEO_BT848) += bttv.o
+obj-$(CONFIG_VIDEO_BT848_GPIO) += bttv-gpiolib.o
EXTRA_CFLAGS += -Idrivers/media/video
EXTRA_CFLAGS += -Idrivers/media/common/tuners
Index: v4l-dvb.git/drivers/media/video/bt8xx/bttv-cards.c
===================================================================
--- v4l-dvb.git.orig/drivers/media/video/bt8xx/bttv-cards.c 2008-07-14 06:33:54.000000000 +0200
+++ v4l-dvb.git/drivers/media/video/bt8xx/bttv-cards.c 2008-07-14 06:33:58.000000000 +0200
@@ -2162,6 +2162,7 @@
.gpiomask = 0xdf,
.muxsel = { 2 },
.pll = PLL_28,
+ .has_gpiolib = 1,
},
[BTTV_BOARD_XGUARD] = {
.name = "Grand X-Guard / Trust 814PCI",
Index: v4l-dvb.git/drivers/media/video/bt8xx/bttv-driver.c
===================================================================
--- v4l-dvb.git.orig/drivers/media/video/bt8xx/bttv-driver.c 2008-07-14 06:33:55.000000000 +0200
+++ v4l-dvb.git/drivers/media/video/bt8xx/bttv-driver.c 2008-07-14 06:33:58.000000000 +0200
@@ -4455,6 +4455,12 @@
request_modules(btv);
}
+#ifdef CONFIG_VIDEO_BT848_GPIO_MODULE
+ /* add gpiolib subdevice */
+ if (bttv_tvcards[btv->c.type].has_gpiolib)
+ bttv_sub_add_device(&btv->c, "gpiolib");
+#endif
+
bttv_input_init(btv);
/* everything is fine */
Index: v4l-dvb.git/drivers/media/video/bt8xx/bttv-gpiolib.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ v4l-dvb.git/drivers/media/video/bt8xx/bttv-gpiolib.c 2008-07-14 08:32:01.000000000 +0200
@@ -0,0 +1,235 @@
+/*
+ * Bt8xx based GPIOLIB driver
+ *
+ * Copyright (C) 2008 Domenico Andreoli <cavok@dandreoli.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+
+#include <asm/gpio.h>
+
+#include "bttvp.h"
+
+struct bttv_gpiolib_device {
+ struct bttv_sub_device *sub;
+ struct gpio_chip chip;
+
+ u32 in_mask;
+ u32 out_mask;
+ u32 out;
+};
+
+static u32 nr_to_mask(struct bttv_gpiolib_device *dev, unsigned nr)
+{
+ u32 io_mask = dev->in_mask | dev->out_mask;
+ int shift = 0;
+
+ while(io_mask && nr) {
+ nr -= io_mask & 1;
+ io_mask >>= 1;
+ shift++;
+ }
+
+ return 1 << shift;
+}
+
+static void bttv_gpiolib_inout(struct bttv_core *core, u32 mask, u32 outbits, u32 outvals)
+{
+ struct bttv *btv = container_of(core, struct bttv, c);
+ unsigned long flags;
+ u32 data;
+
+ spin_lock_irqsave(&btv->gpio_lock, flags);
+
+ /* set direction */
+ data = btread(BT848_GPIO_OUT_EN);
+ data &= ~mask;
+ data |= mask & outbits;
+ btwrite(data, BT848_GPIO_OUT_EN);
+
+ mask &= outbits;
+ if(mask) {
+ /* set output values */
+ data = btread(BT848_GPIO_DATA);
+ data &= ~mask;
+ data |= mask & outvals;
+ btwrite(data, BT848_GPIO_DATA);
+ }
+
+ spin_unlock_irqrestore(&btv->gpio_lock, flags);
+}
+
+static int bttv_gpiolib_direction_input(struct gpio_chip *gpio, unsigned nr)
+{
+ struct bttv_gpiolib_device *dev = container_of(gpio, struct bttv_gpiolib_device, chip);
+ u32 mask = nr_to_mask(dev, nr);
+
+ if(!(mask & dev->in_mask))
+ return -EPERM;
+
+ bttv_gpiolib_inout(dev->sub->core, mask, 0, 0);
+ return 0;
+}
+
+static int bttv_gpiolib_direction_output(struct gpio_chip *gpio, unsigned nr, int val)
+{
+ struct bttv_gpiolib_device *dev = container_of(gpio, struct bttv_gpiolib_device, chip);
+ u32 mask = nr_to_mask(dev, nr);
+
+ if(!(mask & dev->out_mask))
+ return -EPERM;
+
+ bttv_gpiolib_inout(dev->sub->core, mask, mask, val ? mask : 0);
+ return 0;
+}
+
+static int bttv_gpiolib_get(struct gpio_chip *gpio, unsigned nr)
+{
+ u32 data;
+ unsigned long flags;
+ struct bttv_gpiolib_device *dev = container_of(gpio, struct bttv_gpiolib_device, chip);
+ struct bttv *btv = container_of(dev->sub->core, struct bttv, c);
+
+ spin_lock_irqsave(&btv->gpio_lock, flags);
+ data = btread(BT848_GPIO_DATA);
+ spin_unlock_irqrestore(&btv->gpio_lock, flags);
+
+ return !!(data & nr_to_mask(dev, nr));
+}
+
+static void bttv_gpiolib_set(struct gpio_chip *gpio, unsigned nr, int val)
+{
+ u32 data;
+ unsigned long flags;
+ struct bttv_gpiolib_device *dev = container_of(gpio, struct bttv_gpiolib_device, chip);
+ struct bttv *btv = container_of(dev->sub->core, struct bttv, c);
+ u32 mask = nr_to_mask(dev, nr);
+
+ spin_lock_irqsave(&btv->gpio_lock, flags);
+ data = btread(BT848_GPIO_DATA);
+ data &= ~mask;
+ data |= val ? mask : 0;
+ btwrite(data, BT848_GPIO_DATA);
+ spin_unlock_irqrestore(&btv->gpio_lock, flags);
+}
+
+static int bttv_gpiolib_setup(unsigned int type, struct bttv_gpiolib_device *dev)
+{
+ switch(type) {
+ case BTTV_BOARD_IVC200:
+ dev->in_mask = 0x0f;
+ dev->out_mask = 0xff;
+ break;
+
+ default:
+ printk(KERN_ERR "card type %d: missing gpiolib configuration\n", type);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int __devinit bttv_gpiolib_probe(struct bttv_sub_device *sub)
+{
+ struct bttv_gpiolib_device *dev;
+ u32 io_mask;
+ int ret;
+
+ dev = kzalloc(sizeof(struct bttv_gpiolib_device), GFP_KERNEL);
+ if(!dev)
+ return -ENOMEM;
+
+ ret = bttv_gpiolib_setup(sub->core->type, dev);
+ if(ret) {
+ kfree(dev);
+ return ret;
+ }
+
+ io_mask = dev->in_mask | dev->out_mask;
+ if(!io_mask) {
+ printk(KERN_ERR "card type %d: missing GPIOs configuration\n", sub->core->type);
+ kfree(dev);
+ return -EINVAL;
+ }
+
+ /* set direction and output values */
+ bttv_gpiolib_inout(sub->core, io_mask, dev->out_mask, dev->out);
+
+ while(io_mask) {
+ dev->chip.ngpio++;
+ io_mask >>= 1;
+ }
+
+ dev->sub = sub;
+ dev->chip.label = sub->dev.bus_id;
+ dev->chip.owner = THIS_MODULE;
+
+ dev->chip.base = -1;
+ dev->chip.direction_input = bttv_gpiolib_direction_input;
+ dev->chip.direction_output = bttv_gpiolib_direction_output;
+ dev->chip.get = bttv_gpiolib_get;
+ dev->chip.set = bttv_gpiolib_set;
+
+ ret = gpiochip_add(&dev->chip);
+ if(ret) {
+ printk(KERN_ERR "error adding gpio chip %s: %d\n", dev->chip.label, ret);
+ kfree(dev);
+ return ret;
+ }
+
+ dev_set_drvdata(&sub->dev, dev);
+ return 0;
+}
+
+static void __devexit bttv_gpiolib_remove(struct bttv_sub_device *sub)
+{
+ struct bttv_gpiolib_device *dev = dev_get_drvdata(&sub->dev);
+ int ret;
+
+ ret = gpiochip_remove(&dev->chip);
+ if(ret)
+ printk(KERN_ERR "error removing gpio chip %s: %d). leaking memory...\n", dev->chip.label, ret);
+ else
+ kfree(dev);
+}
+
+static struct bttv_sub_driver driver = {
+ .drv = {
+ .name = "bttv-gpiolib",
+ },
+ .probe = bttv_gpiolib_probe,
+ .remove = bttv_gpiolib_remove,
+};
+
+static int __init bttv_gpiolib_init(void)
+{
+ return bttv_sub_register(&driver, "gpiolib");
+}
+
+static void __exit bttv_gpiolib_exit(void)
+{
+ bttv_sub_unregister(&driver);
+}
+
+module_init(bttv_gpiolib_init);
+module_exit(bttv_gpiolib_exit);
+
+MODULE_DESCRIPTION("Bt8xx based GPIOLIB driver");
+MODULE_AUTHOR("Domenico Andreoli <cavok@dandreoli.com>");
+MODULE_LICENSE("GPL");
Index: v4l-dvb.git/drivers/media/video/bt8xx/bttv.h
===================================================================
--- v4l-dvb.git.orig/drivers/media/video/bt8xx/bttv.h 2008-07-14 06:33:54.000000000 +0200
+++ v4l-dvb.git/drivers/media/video/bt8xx/bttv.h 2008-07-14 06:33:58.000000000 +0200
@@ -249,6 +249,8 @@
void (*audio_mode_gpio)(struct bttv *btv, struct v4l2_tuner *tuner, int set);
void (*muxsel_hook)(struct bttv *btv, unsigned int input);
+
+ bool has_gpiolib;
};
extern struct tvcard bttv_tvcards[];
-----[ Domenico Andreoli, aka cavok
--[ http://www.dandreoli.com/gpgkey.asc
---[ 3A0F 2F80 F79C 678A 8936 4FEE 0677 9033 A20E BC50
--
video4linux-list mailing list
Unsubscribe mailto:video4linux-list-request@redhat.com?subject=unsubscribe
https://www.redhat.com/mailman/listinfo/video4linux-list
next prev parent reply other threads:[~2008-07-14 7:27 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <200807101914.10174.mb@bu3sch.de>
[not found] ` <20080710160258.4ddb5c61@gaivota>
2008-07-13 0:42 ` [PATCH v3] Add bt8xxgpio driver Domenico Andreoli
[not found] ` <200807131215.12082.mb@bu3sch.de>
2008-07-13 15:43 ` Domenico Andreoli
[not found] ` <200807131808.35599.mb@bu3sch.de>
2008-07-13 16:39 ` Domenico Andreoli
2008-07-15 8:46 ` Trent Piepho
[not found] ` <200807131300.35126.david-b@pacbell.net>
2008-07-14 5:25 ` Domenico Andreoli
[not found] ` <200807132259.54360.david-b@pacbell.net>
2008-07-14 7:27 ` Domenico Andreoli [this message]
[not found] ` <200807141558.29582.mb@bu3sch.de>
2008-07-14 15:25 ` Domenico Andreoli
[not found] ` <200807140926.28592.david-b@pacbell.net>
2008-07-14 17:08 ` Domenico Andreoli
[not found] ` <200807141951.39810.mb@bu3sch.de>
2008-07-14 19:21 ` Domenico Andreoli
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20080714072733.GA29908@ska.dandreoli.com \
--to=cavokz@gmail.com \
--cc=david-b@pacbell.net \
--cc=mb@bu3sch.de \
--cc=mchehab@infradead.org \
--cc=video4linux-list@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox