11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bttv-gpio.c -- gpio sub drivers 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sysfs-based sub driver interface for bttv 625985edcedea6396277003854657b5f3cb31a628Lucas De Marchi mainly intended for gpio access 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) 104ac97914c6c35f6bf132071c718e034d0846b9f5Mauro Carvalho Chehab & Marcus Metzler (mocm@thp.uni-koeln.de) 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (c) 1999-2003 Gerd Knorr <kraxel@bytesex.org> 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This program is free software; you can redistribute it and/or modify 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds it under the terms of the GNU General Public License as published by 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds the Free Software Foundation; either version 2 of the License, or 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (at your option) any later version. 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This program is distributed in the hope that it will be useful, 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds but WITHOUT ANY WARRANTY; without even the implied warranty of 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GNU General Public License for more details. 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds You should have received a copy of the GNU General Public License 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds along with this program; if not, write to the Free Software 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 298af443e581ab57a6a38f595eb40be3514ea55195Joe Perches#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 308af443e581ab57a6a38f595eb40be3514ea55195Joe Perches 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h> 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/device.h> 355a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h> 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "bttvp.h" 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ----------------------------------------------------------------------- */ 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* internal: the bttv "bus" */ 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int bttv_sub_bus_match(struct device *dev, struct device_driver *drv) 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct bttv_sub_driver *sub = to_bttv_sub_drv(drv); 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int len = strlen(sub->wanted); 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 48af128a102c4aee994b4ff6e422b3cfab17127578Kay Sievers if (0 == strncmp(dev_name(dev), sub->wanted, len)) 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 53348290a4ae143a692124330942b464ccdb0d0365Russell Kingstatic int bttv_sub_probe(struct device *dev) 54348290a4ae143a692124330942b464ccdb0d0365Russell King{ 55348290a4ae143a692124330942b464ccdb0d0365Russell King struct bttv_sub_device *sdev = to_bttv_sub_dev(dev); 56348290a4ae143a692124330942b464ccdb0d0365Russell King struct bttv_sub_driver *sub = to_bttv_sub_drv(dev->driver); 57348290a4ae143a692124330942b464ccdb0d0365Russell King 58348290a4ae143a692124330942b464ccdb0d0365Russell King return sub->probe ? sub->probe(sdev) : -ENODEV; 59348290a4ae143a692124330942b464ccdb0d0365Russell King} 60348290a4ae143a692124330942b464ccdb0d0365Russell King 61348290a4ae143a692124330942b464ccdb0d0365Russell Kingstatic int bttv_sub_remove(struct device *dev) 62348290a4ae143a692124330942b464ccdb0d0365Russell King{ 63348290a4ae143a692124330942b464ccdb0d0365Russell King struct bttv_sub_device *sdev = to_bttv_sub_dev(dev); 64348290a4ae143a692124330942b464ccdb0d0365Russell King struct bttv_sub_driver *sub = to_bttv_sub_drv(dev->driver); 65348290a4ae143a692124330942b464ccdb0d0365Russell King 66348290a4ae143a692124330942b464ccdb0d0365Russell King if (sub->remove) 67348290a4ae143a692124330942b464ccdb0d0365Russell King sub->remove(sdev); 68348290a4ae143a692124330942b464ccdb0d0365Russell King return 0; 69348290a4ae143a692124330942b464ccdb0d0365Russell King} 70348290a4ae143a692124330942b464ccdb0d0365Russell King 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct bus_type bttv_sub_bus_type = { 72348290a4ae143a692124330942b464ccdb0d0365Russell King .name = "bttv-sub", 73348290a4ae143a692124330942b464ccdb0d0365Russell King .match = &bttv_sub_bus_match, 74348290a4ae143a692124330942b464ccdb0d0365Russell King .probe = bttv_sub_probe, 75348290a4ae143a692124330942b464ccdb0d0365Russell King .remove = bttv_sub_remove, 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void release_sub_device(struct device *dev) 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct bttv_sub_device *sub = to_bttv_sub_dev(dev); 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(sub); 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint bttv_sub_add_device(struct bttv_core *core, char *name) 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct bttv_sub_device *sub; 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 897408187d223f63d46a13b6a35b8f96b032c2f623Panagiotis Issaris sub = kzalloc(sizeof(*sub),GFP_KERNEL); 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (NULL == sub) 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sub->core = core; 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sub->dev.parent = &core->pci->dev; 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sub->dev.bus = &bttv_sub_bus_type; 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sub->dev.release = release_sub_device; 97af128a102c4aee994b4ff6e422b3cfab17127578Kay Sievers dev_set_name(&sub->dev, "%s%d", name, core->nr); 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = device_register(&sub->dev); 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (0 != err) { 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(sub); 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1048af443e581ab57a6a38f595eb40be3514ea55195Joe Perches pr_info("%d: add subdevice \"%s\"\n", core->nr, dev_name(&sub->dev)); 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_add_tail(&sub->list,&core->subs); 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint bttv_sub_del_devices(struct bttv_core *core) 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 111a991f44b79fa49b281eb078eed4a76a42101012aTrent Piepho struct bttv_sub_device *sub, *save; 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 113a991f44b79fa49b281eb078eed4a76a42101012aTrent Piepho list_for_each_entry_safe(sub, save, &core->subs, list) { 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_del(&sub->list); 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_unregister(&sub->dev); 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ----------------------------------------------------------------------- */ 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* external: sub-driver register/unregister */ 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint bttv_sub_register(struct bttv_sub_driver *sub, char *wanted) 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sub->drv.bus = &bttv_sub_bus_type; 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds snprintf(sub->wanted,sizeof(sub->wanted),"%s",wanted); 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return driver_register(&sub->drv); 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(bttv_sub_register); 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint bttv_sub_unregister(struct bttv_sub_driver *sub) 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds driver_unregister(&sub->drv); 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(bttv_sub_unregister); 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ----------------------------------------------------------------------- */ 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* external: gpio access functions */ 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid bttv_gpio_inout(struct bttv_core *core, u32 mask, u32 outbits) 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct bttv *btv = container_of(core, struct bttv, c); 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 data; 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&btv->gpio_lock,flags); 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data = btread(BT848_GPIO_OUT_EN); 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data = data & ~mask; 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data = data | (mask & outbits); 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds btwrite(data,BT848_GPIO_OUT_EN); 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&btv->gpio_lock,flags); 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsu32 bttv_gpio_read(struct bttv_core *core) 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct bttv *btv = container_of(core, struct bttv, c); 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 value; 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value = btread(BT848_GPIO_DATA); 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return value; 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid bttv_gpio_write(struct bttv_core *core, u32 value) 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct bttv *btv = container_of(core, struct bttv, c); 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds btwrite(value,BT848_GPIO_DATA); 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid bttv_gpio_bits(struct bttv_core *core, u32 mask, u32 bits) 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct bttv *btv = container_of(core, struct bttv, c); 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 data; 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&btv->gpio_lock,flags); 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data = btread(BT848_GPIO_DATA); 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data = data & ~mask; 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data = data | (mask & bits); 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds btwrite(data,BT848_GPIO_DATA); 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&btv->gpio_lock,flags); 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Local variables: 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * c-basic-offset: 8 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * End: 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 190