0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0018
0019 #include <linux/module.h>
0020 #include <linux/init.h>
0021 #include <linux/delay.h>
0022 #include <linux/device.h>
0023 #include <linux/slab.h>
0024 #include <asm/io.h>
0025
0026 #include "bttvp.h"
0027
0028
0029
0030
0031 static int bttv_sub_bus_match(struct device *dev, struct device_driver *drv)
0032 {
0033 struct bttv_sub_driver *sub = to_bttv_sub_drv(drv);
0034 int len = strlen(sub->wanted);
0035
0036 if (0 == strncmp(dev_name(dev), sub->wanted, len))
0037 return 1;
0038 return 0;
0039 }
0040
0041 static int bttv_sub_probe(struct device *dev)
0042 {
0043 struct bttv_sub_device *sdev = to_bttv_sub_dev(dev);
0044 struct bttv_sub_driver *sub = to_bttv_sub_drv(dev->driver);
0045
0046 return sub->probe ? sub->probe(sdev) : -ENODEV;
0047 }
0048
0049 static void bttv_sub_remove(struct device *dev)
0050 {
0051 struct bttv_sub_device *sdev = to_bttv_sub_dev(dev);
0052 struct bttv_sub_driver *sub = to_bttv_sub_drv(dev->driver);
0053
0054 if (sub->remove)
0055 sub->remove(sdev);
0056 }
0057
0058 struct bus_type bttv_sub_bus_type = {
0059 .name = "bttv-sub",
0060 .match = &bttv_sub_bus_match,
0061 .probe = bttv_sub_probe,
0062 .remove = bttv_sub_remove,
0063 };
0064
0065 static void release_sub_device(struct device *dev)
0066 {
0067 struct bttv_sub_device *sub = to_bttv_sub_dev(dev);
0068 kfree(sub);
0069 }
0070
0071 int bttv_sub_add_device(struct bttv_core *core, char *name)
0072 {
0073 struct bttv_sub_device *sub;
0074 int err;
0075
0076 sub = kzalloc(sizeof(*sub),GFP_KERNEL);
0077 if (NULL == sub)
0078 return -ENOMEM;
0079
0080 sub->core = core;
0081 sub->dev.parent = &core->pci->dev;
0082 sub->dev.bus = &bttv_sub_bus_type;
0083 sub->dev.release = release_sub_device;
0084 dev_set_name(&sub->dev, "%s%d", name, core->nr);
0085
0086 err = device_register(&sub->dev);
0087 if (0 != err) {
0088 put_device(&sub->dev);
0089 return err;
0090 }
0091 pr_info("%d: add subdevice \"%s\"\n", core->nr, dev_name(&sub->dev));
0092 list_add_tail(&sub->list,&core->subs);
0093 return 0;
0094 }
0095
0096 int bttv_sub_del_devices(struct bttv_core *core)
0097 {
0098 struct bttv_sub_device *sub, *save;
0099
0100 list_for_each_entry_safe(sub, save, &core->subs, list) {
0101 list_del(&sub->list);
0102 device_unregister(&sub->dev);
0103 }
0104 return 0;
0105 }
0106
0107
0108
0109
0110 int bttv_sub_register(struct bttv_sub_driver *sub, char *wanted)
0111 {
0112 sub->drv.bus = &bttv_sub_bus_type;
0113 snprintf(sub->wanted,sizeof(sub->wanted),"%s",wanted);
0114 return driver_register(&sub->drv);
0115 }
0116 EXPORT_SYMBOL(bttv_sub_register);
0117
0118 int bttv_sub_unregister(struct bttv_sub_driver *sub)
0119 {
0120 driver_unregister(&sub->drv);
0121 return 0;
0122 }
0123 EXPORT_SYMBOL(bttv_sub_unregister);
0124
0125
0126
0127
0128 void bttv_gpio_inout(struct bttv_core *core, u32 mask, u32 outbits)
0129 {
0130 struct bttv *btv = container_of(core, struct bttv, c);
0131 unsigned long flags;
0132 u32 data;
0133
0134 spin_lock_irqsave(&btv->gpio_lock,flags);
0135 data = btread(BT848_GPIO_OUT_EN);
0136 data = data & ~mask;
0137 data = data | (mask & outbits);
0138 btwrite(data,BT848_GPIO_OUT_EN);
0139 spin_unlock_irqrestore(&btv->gpio_lock,flags);
0140 }
0141
0142 u32 bttv_gpio_read(struct bttv_core *core)
0143 {
0144 struct bttv *btv = container_of(core, struct bttv, c);
0145 u32 value;
0146
0147 value = btread(BT848_GPIO_DATA);
0148 return value;
0149 }
0150
0151 void bttv_gpio_write(struct bttv_core *core, u32 value)
0152 {
0153 struct bttv *btv = container_of(core, struct bttv, c);
0154
0155 btwrite(value,BT848_GPIO_DATA);
0156 }
0157
0158 void bttv_gpio_bits(struct bttv_core *core, u32 mask, u32 bits)
0159 {
0160 struct bttv *btv = container_of(core, struct bttv, c);
0161 unsigned long flags;
0162 u32 data;
0163
0164 spin_lock_irqsave(&btv->gpio_lock,flags);
0165 data = btread(BT848_GPIO_DATA);
0166 data = data & ~mask;
0167 data = data | (mask & bits);
0168 btwrite(data,BT848_GPIO_DATA);
0169 spin_unlock_irqrestore(&btv->gpio_lock,flags);
0170 }