diff options
author | David S. Miller <davem@davemloft.net> | 2008-08-27 01:26:21 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-08-29 05:13:09 -0400 |
commit | 7f06a3b2c162573c924f425053227a52b4bd7cb1 (patch) | |
tree | 32ae30d8cc16ee6ea2320f927f354fa47339babd /drivers/sbus/char | |
parent | 902663f6ea4a2603bee0d88450aae2d653a46f5d (diff) |
sparc: Kill videopix SBUS driver.
This has been marked BROKEN for a long time and it's more likely
to get rewritten from scratch than to be fixed up and made usable.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/sbus/char')
-rw-r--r-- | drivers/sbus/char/Kconfig | 9 | ||||
-rw-r--r-- | drivers/sbus/char/Makefile | 2 | ||||
-rw-r--r-- | drivers/sbus/char/vfc.h | 171 | ||||
-rw-r--r-- | drivers/sbus/char/vfc_dev.c | 736 | ||||
-rw-r--r-- | drivers/sbus/char/vfc_i2c.c | 335 | ||||
-rw-r--r-- | drivers/sbus/char/vfc_i2c.h | 44 |
6 files changed, 0 insertions, 1297 deletions
diff --git a/drivers/sbus/char/Kconfig b/drivers/sbus/char/Kconfig index 9cd54ec63aef..3fd2bc95b514 100644 --- a/drivers/sbus/char/Kconfig +++ b/drivers/sbus/char/Kconfig | |||
@@ -30,15 +30,6 @@ config OBP_FLASH | |||
30 | The OpenBoot PROM on Ultra systems is flashable. If you want to be | 30 | The OpenBoot PROM on Ultra systems is flashable. If you want to be |
31 | able to upgrade the OBP firmware, say Y here. | 31 | able to upgrade the OBP firmware, say Y here. |
32 | 32 | ||
33 | config SUN_VIDEOPIX | ||
34 | tristate "Videopix Frame Grabber (EXPERIMENTAL)" | ||
35 | depends on EXPERIMENTAL && (BROKEN || !64BIT) | ||
36 | help | ||
37 | Say Y here to support the Videopix Frame Grabber from Sun | ||
38 | Microsystems, commonly found on SPARCstations. This card, which is | ||
39 | based on the Phillips SAA9051, can handle NTSC and PAL/SECAM and | ||
40 | SVIDEO signals. | ||
41 | |||
42 | config TADPOLE_TS102_UCTRL | 33 | config TADPOLE_TS102_UCTRL |
43 | tristate "Tadpole TS102 Microcontroller support (EXPERIMENTAL)" | 34 | tristate "Tadpole TS102 Microcontroller support (EXPERIMENTAL)" |
44 | depends on EXPERIMENTAL && SPARC32 | 35 | depends on EXPERIMENTAL && SPARC32 |
diff --git a/drivers/sbus/char/Makefile b/drivers/sbus/char/Makefile index d8b2d0c0ebd5..e15bd5e39463 100644 --- a/drivers/sbus/char/Makefile +++ b/drivers/sbus/char/Makefile | |||
@@ -7,7 +7,6 @@ | |||
7 | # Rewritten to use lists instead of if-statements. | 7 | # Rewritten to use lists instead of if-statements. |
8 | # | 8 | # |
9 | 9 | ||
10 | vfc-objs := vfc_dev.o vfc_i2c.o | ||
11 | bbc-objs := bbc_i2c.o bbc_envctrl.o | 10 | bbc-objs := bbc_i2c.o bbc_envctrl.o |
12 | 11 | ||
13 | obj-$(CONFIG_ENVCTRL) += envctrl.o | 12 | obj-$(CONFIG_ENVCTRL) += envctrl.o |
@@ -17,7 +16,6 @@ obj-$(CONFIG_WATCHDOG_RIO) += riowatchdog.o | |||
17 | obj-$(CONFIG_OBP_FLASH) += flash.o | 16 | obj-$(CONFIG_OBP_FLASH) += flash.o |
18 | obj-$(CONFIG_SUN_OPENPROMIO) += openprom.o | 17 | obj-$(CONFIG_SUN_OPENPROMIO) += openprom.o |
19 | obj-$(CONFIG_SUN_MOSTEK_RTC) += rtc.o | 18 | obj-$(CONFIG_SUN_MOSTEK_RTC) += rtc.o |
20 | obj-$(CONFIG_SUN_VIDEOPIX) += vfc.o | ||
21 | obj-$(CONFIG_TADPOLE_TS102_UCTRL) += uctrl.o | 19 | obj-$(CONFIG_TADPOLE_TS102_UCTRL) += uctrl.o |
22 | obj-$(CONFIG_SUN_JSFLASH) += jsflash.o | 20 | obj-$(CONFIG_SUN_JSFLASH) += jsflash.o |
23 | obj-$(CONFIG_BBC_I2C) += bbc.o | 21 | obj-$(CONFIG_BBC_I2C) += bbc.o |
diff --git a/drivers/sbus/char/vfc.h b/drivers/sbus/char/vfc.h deleted file mode 100644 index a5240c52aa0b..000000000000 --- a/drivers/sbus/char/vfc.h +++ /dev/null | |||
@@ -1,171 +0,0 @@ | |||
1 | #ifndef _LINUX_VFC_H_ | ||
2 | #define _LINUX_VFC_H_ | ||
3 | |||
4 | /* | ||
5 | * The control register for the vfc is at offset 0x4000 | ||
6 | * The first field ram bank is located at offset 0x5000 | ||
7 | * The second field ram bank is at offset 0x7000 | ||
8 | * i2c_reg address the Phillips PCF8584(see notes in vfc_i2c.c) | ||
9 | * data and transmit register. | ||
10 | * i2c_s1 controls register s1 of the PCF8584 | ||
11 | * i2c_write seems to be similar to i2c_write but I am not | ||
12 | * quite sure why sun uses it | ||
13 | * | ||
14 | * I am also not sure whether or not you can read the fram bank as a | ||
15 | * whole or whether you must read each word individually from offset | ||
16 | * 0x5000 as soon as I figure it out I will update this file */ | ||
17 | |||
18 | struct vfc_regs { | ||
19 | char pad1[0x4000]; | ||
20 | unsigned int control; /* Offset 0x4000 */ | ||
21 | char pad2[0xffb]; /* from offset 0x4004 to 0x5000 */ | ||
22 | unsigned int fram_bank1; /* Offset 0x5000 */ | ||
23 | char pad3[0xffb]; /* from offset 0x5004 to 0x6000 */ | ||
24 | unsigned int i2c_reg; /* Offset 0x6000 */ | ||
25 | unsigned int i2c_magic2; /* Offset 0x6004 */ | ||
26 | unsigned int i2c_s1; /* Offset 0x6008 */ | ||
27 | unsigned int i2c_write; /* Offset 0x600c */ | ||
28 | char pad4[0xff0]; /* from offset 0x6010 to 0x7000 */ | ||
29 | unsigned int fram_bank2; /* Offset 0x7000 */ | ||
30 | char pad5[0x1000]; | ||
31 | }; | ||
32 | |||
33 | #define VFC_SAA9051_NR (13) | ||
34 | #define VFC_SAA9051_ADDR (0x8a) | ||
35 | /* The saa9051 returns the following for its status | ||
36 | * bit 0 - 0 | ||
37 | * bit 1 - SECAM color detected (1=found,0=not found) | ||
38 | * bit 2 - COLOR detected (1=found,0=not found) | ||
39 | * bit 3 - 0 | ||
40 | * bit 4 - Field frequency bit (1=60Hz (NTSC), 0=50Hz (PAL)) | ||
41 | * bit 5 - 1 | ||
42 | * bit 6 - horizontal frequency lock (1=transmitter found, | ||
43 | * 0=no transmitter) | ||
44 | * bit 7 - Power on reset bit (1=reset,0=at least one successful | ||
45 | * read of the status byte) | ||
46 | */ | ||
47 | |||
48 | #define VFC_SAA9051_PONRES (0x80) | ||
49 | #define VFC_SAA9051_HLOCK (0x40) | ||
50 | #define VFC_SAA9051_FD (0x10) | ||
51 | #define VFC_SAA9051_CD (0x04) | ||
52 | #define VFC_SAA9051_CS (0x02) | ||
53 | |||
54 | |||
55 | /* The various saa9051 sub addresses */ | ||
56 | |||
57 | #define VFC_SAA9051_IDEL (0) | ||
58 | #define VFC_SAA9051_HSY_START (1) | ||
59 | #define VFC_SAA9051_HSY_STOP (2) | ||
60 | #define VFC_SAA9051_HC_START (3) | ||
61 | #define VFC_SAA9051_HC_STOP (4) | ||
62 | #define VFC_SAA9051_HS_START (5) | ||
63 | #define VFC_SAA9051_HORIZ_PEAK (6) | ||
64 | #define VFC_SAA9051_HUE (7) | ||
65 | #define VFC_SAA9051_C1 (8) | ||
66 | #define VFC_SAA9051_C2 (9) | ||
67 | #define VFC_SAA9051_C3 (0xa) | ||
68 | #define VFC_SAA9051_SECAM_DELAY (0xb) | ||
69 | |||
70 | |||
71 | /* Bit settings for saa9051 sub address 0x06 */ | ||
72 | |||
73 | #define VFC_SAA9051_AP1 (0x01) | ||
74 | #define VFC_SAA9051_AP2 (0x02) | ||
75 | #define VFC_SAA9051_COR1 (0x04) | ||
76 | #define VFC_SAA9051_COR2 (0x08) | ||
77 | #define VFC_SAA9051_BP1 (0x10) | ||
78 | #define VFC_SAA9051_BP2 (0x20) | ||
79 | #define VFC_SAA9051_PF (0x40) | ||
80 | #define VFC_SAA9051_BY (0x80) | ||
81 | |||
82 | |||
83 | /* Bit settings for saa9051 sub address 0x08 */ | ||
84 | |||
85 | #define VFC_SAA9051_CCFR0 (0x01) | ||
86 | #define VFC_SAA9051_CCFR1 (0x02) | ||
87 | #define VFC_SAA9051_YPN (0x04) | ||
88 | #define VFC_SAA9051_ALT (0x08) | ||
89 | #define VFC_SAA9051_CO (0x10) | ||
90 | #define VFC_SAA9051_VTR (0x20) | ||
91 | #define VFC_SAA9051_FS (0x40) | ||
92 | #define VFC_SAA9051_HPLL (0x80) | ||
93 | |||
94 | |||
95 | /* Bit settings for saa9051 sub address 9 */ | ||
96 | |||
97 | #define VFC_SAA9051_SS0 (0x01) | ||
98 | #define VFC_SAA9051_SS1 (0x02) | ||
99 | #define VFC_SAA9051_AFCC (0x04) | ||
100 | #define VFC_SAA9051_CI (0x08) | ||
101 | #define VFC_SAA9051_SA9D4 (0x10) /* Don't care bit */ | ||
102 | #define VFC_SAA9051_OEC (0x20) | ||
103 | #define VFC_SAA9051_OEY (0x40) | ||
104 | #define VFC_SAA9051_VNL (0x80) | ||
105 | |||
106 | |||
107 | /* Bit settings for saa9051 sub address 0x0A */ | ||
108 | |||
109 | #define VFC_SAA9051_YDL0 (0x01) | ||
110 | #define VFC_SAA9051_YDL1 (0x02) | ||
111 | #define VFC_SAA9051_YDL2 (0x04) | ||
112 | #define VFC_SAA9051_SS2 (0x08) | ||
113 | #define VFC_SAA9051_SS3 (0x10) | ||
114 | #define VFC_SAA9051_YC (0x20) | ||
115 | #define VFC_SAA9051_CT (0x40) | ||
116 | #define VFC_SAA9051_SYC (0x80) | ||
117 | |||
118 | |||
119 | #define VFC_SAA9051_SA(a,b) ((a)->saa9051_state_array[(b)+1]) | ||
120 | #define vfc_update_saa9051(a) (vfc_i2c_sendbuf((a),VFC_SAA9051_ADDR,\ | ||
121 | (a)->saa9051_state_array,\ | ||
122 | VFC_SAA9051_NR)) | ||
123 | |||
124 | |||
125 | struct vfc_dev { | ||
126 | volatile struct vfc_regs __iomem *regs; | ||
127 | struct vfc_regs *phys_regs; | ||
128 | unsigned int control_reg; | ||
129 | struct mutex device_lock_mtx; | ||
130 | int instance; | ||
131 | int busy; | ||
132 | unsigned long which_io; | ||
133 | unsigned char saa9051_state_array[VFC_SAA9051_NR]; | ||
134 | }; | ||
135 | |||
136 | void captstat_reset(struct vfc_dev *); | ||
137 | void memptr_reset(struct vfc_dev *); | ||
138 | |||
139 | int vfc_pcf8584_init(struct vfc_dev *); | ||
140 | void vfc_i2c_delay_no_busy(struct vfc_dev *, unsigned long); | ||
141 | void vfc_i2c_delay(struct vfc_dev *); | ||
142 | int vfc_i2c_sendbuf(struct vfc_dev *, unsigned char, char *, int) ; | ||
143 | int vfc_i2c_recvbuf(struct vfc_dev *, unsigned char, char *, int) ; | ||
144 | int vfc_i2c_reset_bus(struct vfc_dev *); | ||
145 | int vfc_init_i2c_bus(struct vfc_dev *); | ||
146 | |||
147 | #define VFC_CONTROL_DIAGMODE 0x10000000 | ||
148 | #define VFC_CONTROL_MEMPTR 0x20000000 | ||
149 | #define VFC_CONTROL_CAPTURE 0x02000000 | ||
150 | #define VFC_CONTROL_CAPTRESET 0x04000000 | ||
151 | |||
152 | #define VFC_STATUS_CAPTURE 0x08000000 | ||
153 | |||
154 | #ifdef VFC_IOCTL_DEBUG | ||
155 | #define VFC_IOCTL_DEBUG_PRINTK(a) printk a | ||
156 | #else | ||
157 | #define VFC_IOCTL_DEBUG_PRINTK(a) | ||
158 | #endif | ||
159 | |||
160 | #ifdef VFC_I2C_DEBUG | ||
161 | #define VFC_I2C_DEBUG_PRINTK(a) printk a | ||
162 | #else | ||
163 | #define VFC_I2C_DEBUG_PRINTK(a) | ||
164 | #endif | ||
165 | |||
166 | #endif /* _LINUX_VFC_H_ */ | ||
167 | |||
168 | |||
169 | |||
170 | |||
171 | |||
diff --git a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c deleted file mode 100644 index 25181bb7d627..000000000000 --- a/drivers/sbus/char/vfc_dev.c +++ /dev/null | |||
@@ -1,736 +0,0 @@ | |||
1 | /* | ||
2 | * drivers/sbus/char/vfc_dev.c | ||
3 | * | ||
4 | * Driver for the Videopix Frame Grabber. | ||
5 | * | ||
6 | * In order to use the VFC you need to program the video controller | ||
7 | * chip. This chip is the Phillips SAA9051. You need to call their | ||
8 | * documentation ordering line to get the docs. | ||
9 | * | ||
10 | * There is very little documentation on the VFC itself. There is | ||
11 | * some useful info that can be found in the manuals that come with | ||
12 | * the card. I will hopefully write some better docs at a later date. | ||
13 | * | ||
14 | * Copyright (C) 1996 Manish Vachharajani (mvachhar@noc.rutgers.edu) | ||
15 | * */ | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/string.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/errno.h> | ||
22 | #include <linux/fs.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <linux/spinlock.h> | ||
25 | #include <linux/mutex.h> | ||
26 | #include <linux/mm.h> | ||
27 | #include <linux/smp_lock.h> | ||
28 | |||
29 | #include <asm/openprom.h> | ||
30 | #include <asm/oplib.h> | ||
31 | #include <asm/io.h> | ||
32 | #include <asm/system.h> | ||
33 | #include <asm/sbus.h> | ||
34 | #include <asm/page.h> | ||
35 | #include <asm/pgtable.h> | ||
36 | #include <asm/uaccess.h> | ||
37 | |||
38 | #define VFC_MAJOR (60) | ||
39 | |||
40 | #if 0 | ||
41 | #define VFC_IOCTL_DEBUG | ||
42 | #endif | ||
43 | |||
44 | #include "vfc.h" | ||
45 | #include <asm/vfc_ioctls.h> | ||
46 | |||
47 | static const struct file_operations vfc_fops; | ||
48 | static struct vfc_dev **vfc_dev_lst; | ||
49 | static char vfcstr[]="vfc"; | ||
50 | static unsigned char saa9051_init_array[VFC_SAA9051_NR] = { | ||
51 | 0x00, 0x64, 0x72, 0x52, | ||
52 | 0x36, 0x18, 0xff, 0x20, | ||
53 | 0xfc, 0x77, 0xe3, 0x50, | ||
54 | 0x3e | ||
55 | }; | ||
56 | |||
57 | static void vfc_lock_device(struct vfc_dev *dev) | ||
58 | { | ||
59 | mutex_lock(&dev->device_lock_mtx); | ||
60 | } | ||
61 | |||
62 | static void vfc_unlock_device(struct vfc_dev *dev) | ||
63 | { | ||
64 | mutex_unlock(&dev->device_lock_mtx); | ||
65 | } | ||
66 | |||
67 | |||
68 | static void vfc_captstat_reset(struct vfc_dev *dev) | ||
69 | { | ||
70 | dev->control_reg |= VFC_CONTROL_CAPTRESET; | ||
71 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
72 | dev->control_reg &= ~VFC_CONTROL_CAPTRESET; | ||
73 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
74 | dev->control_reg |= VFC_CONTROL_CAPTRESET; | ||
75 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
76 | } | ||
77 | |||
78 | static void vfc_memptr_reset(struct vfc_dev *dev) | ||
79 | { | ||
80 | dev->control_reg |= VFC_CONTROL_MEMPTR; | ||
81 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
82 | dev->control_reg &= ~VFC_CONTROL_MEMPTR; | ||
83 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
84 | dev->control_reg |= VFC_CONTROL_MEMPTR; | ||
85 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
86 | } | ||
87 | |||
88 | static int vfc_csr_init(struct vfc_dev *dev) | ||
89 | { | ||
90 | dev->control_reg = 0x80000000; | ||
91 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
92 | udelay(200); | ||
93 | dev->control_reg &= ~0x80000000; | ||
94 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
95 | udelay(100); | ||
96 | sbus_writel(0x0f000000, &dev->regs->i2c_magic2); | ||
97 | |||
98 | vfc_memptr_reset(dev); | ||
99 | |||
100 | dev->control_reg &= ~VFC_CONTROL_DIAGMODE; | ||
101 | dev->control_reg &= ~VFC_CONTROL_CAPTURE; | ||
102 | dev->control_reg |= 0x40000000; | ||
103 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
104 | |||
105 | vfc_captstat_reset(dev); | ||
106 | |||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | static int vfc_saa9051_init(struct vfc_dev *dev) | ||
111 | { | ||
112 | int i; | ||
113 | |||
114 | for (i = 0; i < VFC_SAA9051_NR; i++) | ||
115 | dev->saa9051_state_array[i] = saa9051_init_array[i]; | ||
116 | |||
117 | vfc_i2c_sendbuf(dev,VFC_SAA9051_ADDR, | ||
118 | dev->saa9051_state_array, VFC_SAA9051_NR); | ||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | static int init_vfc_hw(struct vfc_dev *dev) | ||
123 | { | ||
124 | vfc_lock_device(dev); | ||
125 | vfc_csr_init(dev); | ||
126 | |||
127 | vfc_pcf8584_init(dev); | ||
128 | vfc_init_i2c_bus(dev); /* hopefully this doesn't undo the magic | ||
129 | sun code above*/ | ||
130 | vfc_saa9051_init(dev); | ||
131 | vfc_unlock_device(dev); | ||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | static int init_vfc_devstruct(struct vfc_dev *dev, int instance) | ||
136 | { | ||
137 | dev->instance=instance; | ||
138 | mutex_init(&dev->device_lock_mtx); | ||
139 | dev->control_reg=0; | ||
140 | dev->busy=0; | ||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static int init_vfc_device(struct sbus_dev *sdev,struct vfc_dev *dev, | ||
145 | int instance) | ||
146 | { | ||
147 | if(dev == NULL) { | ||
148 | printk(KERN_ERR "VFC: Bogus pointer passed\n"); | ||
149 | return -ENOMEM; | ||
150 | } | ||
151 | printk("Initializing vfc%d\n",instance); | ||
152 | dev->regs = NULL; | ||
153 | dev->regs = (volatile struct vfc_regs __iomem *) | ||
154 | sbus_ioremap(&sdev->resource[0], 0, | ||
155 | sizeof(struct vfc_regs), vfcstr); | ||
156 | dev->which_io = sdev->reg_addrs[0].which_io; | ||
157 | dev->phys_regs = (struct vfc_regs *) sdev->reg_addrs[0].phys_addr; | ||
158 | if (dev->regs == NULL) | ||
159 | return -EIO; | ||
160 | |||
161 | printk("vfc%d: registers mapped at phys_addr: 0x%lx\n virt_addr: 0x%lx\n", | ||
162 | instance,(unsigned long)sdev->reg_addrs[0].phys_addr,(unsigned long)dev->regs); | ||
163 | |||
164 | if (init_vfc_devstruct(dev, instance)) | ||
165 | return -EINVAL; | ||
166 | if (init_vfc_hw(dev)) | ||
167 | return -EIO; | ||
168 | return 0; | ||
169 | } | ||
170 | |||
171 | |||
172 | static struct vfc_dev *vfc_get_dev_ptr(int instance) | ||
173 | { | ||
174 | return vfc_dev_lst[instance]; | ||
175 | } | ||
176 | |||
177 | static DEFINE_SPINLOCK(vfc_dev_lock); | ||
178 | |||
179 | static int vfc_open(struct inode *inode, struct file *file) | ||
180 | { | ||
181 | struct vfc_dev *dev; | ||
182 | |||
183 | lock_kernel(); | ||
184 | spin_lock(&vfc_dev_lock); | ||
185 | dev = vfc_get_dev_ptr(iminor(inode)); | ||
186 | if (dev == NULL) { | ||
187 | spin_unlock(&vfc_dev_lock); | ||
188 | unlock_kernel(); | ||
189 | return -ENODEV; | ||
190 | } | ||
191 | if (dev->busy) { | ||
192 | spin_unlock(&vfc_dev_lock); | ||
193 | unlock_kernel(); | ||
194 | return -EBUSY; | ||
195 | } | ||
196 | |||
197 | dev->busy = 1; | ||
198 | spin_unlock(&vfc_dev_lock); | ||
199 | |||
200 | vfc_lock_device(dev); | ||
201 | |||
202 | vfc_csr_init(dev); | ||
203 | vfc_pcf8584_init(dev); | ||
204 | vfc_init_i2c_bus(dev); | ||
205 | vfc_saa9051_init(dev); | ||
206 | vfc_memptr_reset(dev); | ||
207 | vfc_captstat_reset(dev); | ||
208 | |||
209 | vfc_unlock_device(dev); | ||
210 | unlock_kernel(); | ||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | static int vfc_release(struct inode *inode,struct file *file) | ||
215 | { | ||
216 | struct vfc_dev *dev; | ||
217 | |||
218 | spin_lock(&vfc_dev_lock); | ||
219 | dev = vfc_get_dev_ptr(iminor(inode)); | ||
220 | if (!dev || !dev->busy) { | ||
221 | spin_unlock(&vfc_dev_lock); | ||
222 | return -EINVAL; | ||
223 | } | ||
224 | dev->busy = 0; | ||
225 | spin_unlock(&vfc_dev_lock); | ||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | static int vfc_debug(struct vfc_dev *dev, int cmd, void __user *argp) | ||
230 | { | ||
231 | struct vfc_debug_inout inout; | ||
232 | unsigned char *buffer; | ||
233 | |||
234 | if (!capable(CAP_SYS_ADMIN)) | ||
235 | return -EPERM; | ||
236 | |||
237 | switch(cmd) { | ||
238 | case VFC_I2C_SEND: | ||
239 | if(copy_from_user(&inout, argp, sizeof(inout))) | ||
240 | return -EFAULT; | ||
241 | |||
242 | buffer = kmalloc(inout.len, GFP_KERNEL); | ||
243 | if (buffer == NULL) | ||
244 | return -ENOMEM; | ||
245 | |||
246 | if(copy_from_user(buffer, inout.buffer, inout.len)) { | ||
247 | kfree(buffer); | ||
248 | return -EFAULT; | ||
249 | } | ||
250 | |||
251 | |||
252 | vfc_lock_device(dev); | ||
253 | inout.ret= | ||
254 | vfc_i2c_sendbuf(dev,inout.addr & 0xff, | ||
255 | buffer,inout.len); | ||
256 | |||
257 | if (copy_to_user(argp,&inout,sizeof(inout))) { | ||
258 | vfc_unlock_device(dev); | ||
259 | kfree(buffer); | ||
260 | return -EFAULT; | ||
261 | } | ||
262 | vfc_unlock_device(dev); | ||
263 | |||
264 | break; | ||
265 | case VFC_I2C_RECV: | ||
266 | if (copy_from_user(&inout, argp, sizeof(inout))) | ||
267 | return -EFAULT; | ||
268 | |||
269 | buffer = kzalloc(inout.len, GFP_KERNEL); | ||
270 | if (buffer == NULL) | ||
271 | return -ENOMEM; | ||
272 | |||
273 | vfc_lock_device(dev); | ||
274 | inout.ret= | ||
275 | vfc_i2c_recvbuf(dev,inout.addr & 0xff | ||
276 | ,buffer,inout.len); | ||
277 | vfc_unlock_device(dev); | ||
278 | |||
279 | if (copy_to_user(inout.buffer, buffer, inout.len)) { | ||
280 | kfree(buffer); | ||
281 | return -EFAULT; | ||
282 | } | ||
283 | if (copy_to_user(argp,&inout,sizeof(inout))) { | ||
284 | kfree(buffer); | ||
285 | return -EFAULT; | ||
286 | } | ||
287 | kfree(buffer); | ||
288 | break; | ||
289 | default: | ||
290 | return -EINVAL; | ||
291 | }; | ||
292 | |||
293 | return 0; | ||
294 | } | ||
295 | |||
296 | static int vfc_capture_start(struct vfc_dev *dev) | ||
297 | { | ||
298 | vfc_captstat_reset(dev); | ||
299 | dev->control_reg = sbus_readl(&dev->regs->control); | ||
300 | if((dev->control_reg & VFC_STATUS_CAPTURE)) { | ||
301 | printk(KERN_ERR "vfc%d: vfc capture status not reset\n", | ||
302 | dev->instance); | ||
303 | return -EIO; | ||
304 | } | ||
305 | |||
306 | vfc_lock_device(dev); | ||
307 | dev->control_reg &= ~VFC_CONTROL_CAPTURE; | ||
308 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
309 | dev->control_reg |= VFC_CONTROL_CAPTURE; | ||
310 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
311 | dev->control_reg &= ~VFC_CONTROL_CAPTURE; | ||
312 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
313 | vfc_unlock_device(dev); | ||
314 | |||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | static int vfc_capture_poll(struct vfc_dev *dev) | ||
319 | { | ||
320 | int timeout = 1000; | ||
321 | |||
322 | while (!timeout--) { | ||
323 | if (sbus_readl(&dev->regs->control) & VFC_STATUS_CAPTURE) | ||
324 | break; | ||
325 | vfc_i2c_delay_no_busy(dev, 100); | ||
326 | } | ||
327 | if(!timeout) { | ||
328 | printk(KERN_WARNING "vfc%d: capture timed out\n", | ||
329 | dev->instance); | ||
330 | return -ETIMEDOUT; | ||
331 | } | ||
332 | return 0; | ||
333 | } | ||
334 | |||
335 | |||
336 | |||
337 | static int vfc_set_control_ioctl(struct inode *inode, struct file *file, | ||
338 | struct vfc_dev *dev, unsigned long arg) | ||
339 | { | ||
340 | int setcmd, ret = 0; | ||
341 | |||
342 | if (copy_from_user(&setcmd,(void __user *)arg,sizeof(unsigned int))) | ||
343 | return -EFAULT; | ||
344 | |||
345 | VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCSCTRL) arg=0x%x\n", | ||
346 | dev->instance,setcmd)); | ||
347 | |||
348 | switch(setcmd) { | ||
349 | case MEMPRST: | ||
350 | vfc_lock_device(dev); | ||
351 | vfc_memptr_reset(dev); | ||
352 | vfc_unlock_device(dev); | ||
353 | ret=0; | ||
354 | break; | ||
355 | case CAPTRCMD: | ||
356 | vfc_capture_start(dev); | ||
357 | vfc_capture_poll(dev); | ||
358 | break; | ||
359 | case DIAGMODE: | ||
360 | if(capable(CAP_SYS_ADMIN)) { | ||
361 | vfc_lock_device(dev); | ||
362 | dev->control_reg |= VFC_CONTROL_DIAGMODE; | ||
363 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
364 | vfc_unlock_device(dev); | ||
365 | ret = 0; | ||
366 | } else { | ||
367 | ret = -EPERM; | ||
368 | } | ||
369 | break; | ||
370 | case NORMMODE: | ||
371 | vfc_lock_device(dev); | ||
372 | dev->control_reg &= ~VFC_CONTROL_DIAGMODE; | ||
373 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
374 | vfc_unlock_device(dev); | ||
375 | ret = 0; | ||
376 | break; | ||
377 | case CAPTRSTR: | ||
378 | vfc_capture_start(dev); | ||
379 | ret = 0; | ||
380 | break; | ||
381 | case CAPTRWAIT: | ||
382 | vfc_capture_poll(dev); | ||
383 | ret = 0; | ||
384 | break; | ||
385 | default: | ||
386 | ret = -EINVAL; | ||
387 | break; | ||
388 | }; | ||
389 | |||
390 | return ret; | ||
391 | } | ||
392 | |||
393 | |||
394 | static int vfc_port_change_ioctl(struct inode *inode, struct file *file, | ||
395 | struct vfc_dev *dev, unsigned long arg) | ||
396 | { | ||
397 | int ret = 0; | ||
398 | int cmd; | ||
399 | |||
400 | if(copy_from_user(&cmd, (void __user *)arg, sizeof(unsigned int))) { | ||
401 | VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to " | ||
402 | "vfc_port_change_ioctl\n", | ||
403 | dev->instance)); | ||
404 | return -EFAULT; | ||
405 | } | ||
406 | |||
407 | VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCPORTCHG) arg=0x%x\n", | ||
408 | dev->instance, cmd)); | ||
409 | |||
410 | switch(cmd) { | ||
411 | case 1: | ||
412 | case 2: | ||
413 | VFC_SAA9051_SA(dev,VFC_SAA9051_HSY_START) = 0x72; | ||
414 | VFC_SAA9051_SA(dev,VFC_SAA9051_HSY_STOP) = 0x52; | ||
415 | VFC_SAA9051_SA(dev,VFC_SAA9051_HC_START) = 0x36; | ||
416 | VFC_SAA9051_SA(dev,VFC_SAA9051_HC_STOP) = 0x18; | ||
417 | VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) = VFC_SAA9051_BP2; | ||
418 | VFC_SAA9051_SA(dev,VFC_SAA9051_C3) = VFC_SAA9051_CT | VFC_SAA9051_SS3; | ||
419 | VFC_SAA9051_SA(dev,VFC_SAA9051_SECAM_DELAY) = 0x3e; | ||
420 | break; | ||
421 | case 3: | ||
422 | VFC_SAA9051_SA(dev,VFC_SAA9051_HSY_START) = 0x3a; | ||
423 | VFC_SAA9051_SA(dev,VFC_SAA9051_HSY_STOP) = 0x17; | ||
424 | VFC_SAA9051_SA(dev,VFC_SAA9051_HC_START) = 0xfa; | ||
425 | VFC_SAA9051_SA(dev,VFC_SAA9051_HC_STOP) = 0xde; | ||
426 | VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) = | ||
427 | VFC_SAA9051_BY | VFC_SAA9051_PF | VFC_SAA9051_BP2; | ||
428 | VFC_SAA9051_SA(dev,VFC_SAA9051_C3) = VFC_SAA9051_YC; | ||
429 | VFC_SAA9051_SA(dev,VFC_SAA9051_SECAM_DELAY) = 0; | ||
430 | VFC_SAA9051_SA(dev,VFC_SAA9051_C2) &= | ||
431 | ~(VFC_SAA9051_SS0 | VFC_SAA9051_SS1); | ||
432 | break; | ||
433 | default: | ||
434 | ret = -EINVAL; | ||
435 | return ret; | ||
436 | break; | ||
437 | } | ||
438 | |||
439 | switch(cmd) { | ||
440 | case 1: | ||
441 | VFC_SAA9051_SA(dev,VFC_SAA9051_C2) |= | ||
442 | (VFC_SAA9051_SS0 | VFC_SAA9051_SS1); | ||
443 | break; | ||
444 | case 2: | ||
445 | VFC_SAA9051_SA(dev,VFC_SAA9051_C2) &= | ||
446 | ~(VFC_SAA9051_SS0 | VFC_SAA9051_SS1); | ||
447 | VFC_SAA9051_SA(dev,VFC_SAA9051_C2) |= VFC_SAA9051_SS0; | ||
448 | break; | ||
449 | case 3: | ||
450 | break; | ||
451 | default: | ||
452 | ret = -EINVAL; | ||
453 | return ret; | ||
454 | break; | ||
455 | } | ||
456 | VFC_SAA9051_SA(dev,VFC_SAA9051_C3) &= ~(VFC_SAA9051_SS2); | ||
457 | ret=vfc_update_saa9051(dev); | ||
458 | udelay(500); | ||
459 | VFC_SAA9051_SA(dev,VFC_SAA9051_C3) |= (VFC_SAA9051_SS2); | ||
460 | ret=vfc_update_saa9051(dev); | ||
461 | return ret; | ||
462 | } | ||
463 | |||
464 | static int vfc_set_video_ioctl(struct inode *inode, struct file *file, | ||
465 | struct vfc_dev *dev, unsigned long arg) | ||
466 | { | ||
467 | int ret = 0; | ||
468 | int cmd; | ||
469 | |||
470 | if(copy_from_user(&cmd, (void __user *)arg, sizeof(unsigned int))) { | ||
471 | VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to " | ||
472 | "vfc_set_video_ioctl\n", | ||
473 | dev->instance)); | ||
474 | return ret; | ||
475 | } | ||
476 | |||
477 | VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCSVID) arg=0x%x\n", | ||
478 | dev->instance, cmd)); | ||
479 | switch(cmd) { | ||
480 | case STD_NTSC: | ||
481 | VFC_SAA9051_SA(dev,VFC_SAA9051_C1) &= ~VFC_SAA9051_ALT; | ||
482 | VFC_SAA9051_SA(dev,VFC_SAA9051_C1) |= VFC_SAA9051_YPN | | ||
483 | VFC_SAA9051_CCFR0 | VFC_SAA9051_CCFR1 | VFC_SAA9051_FS; | ||
484 | ret = vfc_update_saa9051(dev); | ||
485 | break; | ||
486 | case STD_PAL: | ||
487 | VFC_SAA9051_SA(dev,VFC_SAA9051_C1) &= ~(VFC_SAA9051_YPN | | ||
488 | VFC_SAA9051_CCFR1 | | ||
489 | VFC_SAA9051_CCFR0 | | ||
490 | VFC_SAA9051_FS); | ||
491 | VFC_SAA9051_SA(dev,VFC_SAA9051_C1) |= VFC_SAA9051_ALT; | ||
492 | ret = vfc_update_saa9051(dev); | ||
493 | break; | ||
494 | |||
495 | case COLOR_ON: | ||
496 | VFC_SAA9051_SA(dev,VFC_SAA9051_C1) |= VFC_SAA9051_CO; | ||
497 | VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) &= | ||
498 | ~(VFC_SAA9051_BY | VFC_SAA9051_PF); | ||
499 | ret = vfc_update_saa9051(dev); | ||
500 | break; | ||
501 | case MONO: | ||
502 | VFC_SAA9051_SA(dev,VFC_SAA9051_C1) &= ~(VFC_SAA9051_CO); | ||
503 | VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) |= | ||
504 | (VFC_SAA9051_BY | VFC_SAA9051_PF); | ||
505 | ret = vfc_update_saa9051(dev); | ||
506 | break; | ||
507 | default: | ||
508 | ret = -EINVAL; | ||
509 | break; | ||
510 | }; | ||
511 | |||
512 | return ret; | ||
513 | } | ||
514 | |||
515 | static int vfc_get_video_ioctl(struct inode *inode, struct file *file, | ||
516 | struct vfc_dev *dev, unsigned long arg) | ||
517 | { | ||
518 | int ret = 0; | ||
519 | unsigned int status = NO_LOCK; | ||
520 | unsigned char buf[1]; | ||
521 | |||
522 | if(vfc_i2c_recvbuf(dev, VFC_SAA9051_ADDR, buf, 1)) { | ||
523 | printk(KERN_ERR "vfc%d: Unable to get status\n", | ||
524 | dev->instance); | ||
525 | return -EIO; | ||
526 | } | ||
527 | |||
528 | if(buf[0] & VFC_SAA9051_HLOCK) { | ||
529 | status = NO_LOCK; | ||
530 | } else if(buf[0] & VFC_SAA9051_FD) { | ||
531 | if(buf[0] & VFC_SAA9051_CD) | ||
532 | status = NTSC_COLOR; | ||
533 | else | ||
534 | status = NTSC_NOCOLOR; | ||
535 | } else { | ||
536 | if(buf[0] & VFC_SAA9051_CD) | ||
537 | status = PAL_COLOR; | ||
538 | else | ||
539 | status = PAL_NOCOLOR; | ||
540 | } | ||
541 | VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCGVID) returning status 0x%x; " | ||
542 | "buf[0]=%x\n", dev->instance, status, buf[0])); | ||
543 | |||
544 | if (copy_to_user((void __user *)arg,&status,sizeof(unsigned int))) { | ||
545 | VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to " | ||
546 | "vfc_get_video_ioctl\n", | ||
547 | dev->instance)); | ||
548 | return ret; | ||
549 | } | ||
550 | return ret; | ||
551 | } | ||
552 | |||
553 | static int vfc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | ||
554 | unsigned long arg) | ||
555 | { | ||
556 | int ret = 0; | ||
557 | unsigned int tmp; | ||
558 | struct vfc_dev *dev; | ||
559 | void __user *argp = (void __user *)arg; | ||
560 | |||
561 | dev = vfc_get_dev_ptr(iminor(inode)); | ||
562 | if(dev == NULL) | ||
563 | return -ENODEV; | ||
564 | |||
565 | switch(cmd & 0x0000ffff) { | ||
566 | case VFCGCTRL: | ||
567 | #if 0 | ||
568 | VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCGCTRL)\n", dev->instance)); | ||
569 | #endif | ||
570 | tmp = sbus_readl(&dev->regs->control); | ||
571 | if(copy_to_user(argp, &tmp, sizeof(unsigned int))) { | ||
572 | ret = -EFAULT; | ||
573 | break; | ||
574 | } | ||
575 | ret = 0; | ||
576 | break; | ||
577 | case VFCSCTRL: | ||
578 | ret = vfc_set_control_ioctl(inode, file, dev, arg); | ||
579 | break; | ||
580 | case VFCGVID: | ||
581 | ret = vfc_get_video_ioctl(inode, file, dev, arg); | ||
582 | break; | ||
583 | case VFCSVID: | ||
584 | ret = vfc_set_video_ioctl(inode, file, dev, arg); | ||
585 | break; | ||
586 | case VFCHUE: | ||
587 | VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCHUE)\n", dev->instance)); | ||
588 | if(copy_from_user(&tmp,argp,sizeof(unsigned int))) { | ||
589 | VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer " | ||
590 | "to IOCTL(VFCHUE)", dev->instance)); | ||
591 | ret = -EFAULT; | ||
592 | } else { | ||
593 | VFC_SAA9051_SA(dev,VFC_SAA9051_HUE) = tmp; | ||
594 | vfc_update_saa9051(dev); | ||
595 | ret = 0; | ||
596 | } | ||
597 | break; | ||
598 | case VFCPORTCHG: | ||
599 | ret = vfc_port_change_ioctl(inode, file, dev, arg); | ||
600 | break; | ||
601 | case VFCRDINFO: | ||
602 | ret = -EINVAL; | ||
603 | VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCRDINFO)\n", dev->instance)); | ||
604 | break; | ||
605 | default: | ||
606 | ret = vfc_debug(vfc_get_dev_ptr(iminor(inode)), cmd, argp); | ||
607 | break; | ||
608 | }; | ||
609 | |||
610 | return ret; | ||
611 | } | ||
612 | |||
613 | static int vfc_mmap(struct file *file, struct vm_area_struct *vma) | ||
614 | { | ||
615 | unsigned int map_size, ret, map_offset; | ||
616 | struct vfc_dev *dev; | ||
617 | |||
618 | dev = vfc_get_dev_ptr(iminor(file->f_path.dentry->d_inode)); | ||
619 | if(dev == NULL) | ||
620 | return -ENODEV; | ||
621 | |||
622 | map_size = vma->vm_end - vma->vm_start; | ||
623 | if(map_size > sizeof(struct vfc_regs)) | ||
624 | map_size = sizeof(struct vfc_regs); | ||
625 | |||
626 | vma->vm_flags |= | ||
627 | (VM_MAYREAD | VM_MAYWRITE | VM_MAYSHARE); | ||
628 | map_offset = (unsigned int) (long)dev->phys_regs; | ||
629 | ret = io_remap_pfn_range(vma, vma->vm_start, | ||
630 | MK_IOSPACE_PFN(dev->which_io, | ||
631 | map_offset >> PAGE_SHIFT), | ||
632 | map_size, vma->vm_page_prot); | ||
633 | |||
634 | if(ret) | ||
635 | return -EAGAIN; | ||
636 | |||
637 | return 0; | ||
638 | } | ||
639 | |||
640 | |||
641 | static const struct file_operations vfc_fops = { | ||
642 | .owner = THIS_MODULE, | ||
643 | .llseek = no_llseek, | ||
644 | .ioctl = vfc_ioctl, | ||
645 | .mmap = vfc_mmap, | ||
646 | .open = vfc_open, | ||
647 | .release = vfc_release, | ||
648 | }; | ||
649 | |||
650 | static int vfc_probe(void) | ||
651 | { | ||
652 | struct sbus_bus *sbus; | ||
653 | struct sbus_dev *sdev = NULL; | ||
654 | int ret; | ||
655 | int instance = 0, cards = 0; | ||
656 | |||
657 | for_all_sbusdev(sdev, sbus) { | ||
658 | if (strcmp(sdev->prom_name, "vfc") == 0) { | ||
659 | cards++; | ||
660 | continue; | ||
661 | } | ||
662 | } | ||
663 | |||
664 | if (!cards) | ||
665 | return -ENODEV; | ||
666 | |||
667 | vfc_dev_lst = kcalloc(cards + 1, sizeof(struct vfc_dev*), GFP_KERNEL); | ||
668 | if (vfc_dev_lst == NULL) | ||
669 | return -ENOMEM; | ||
670 | vfc_dev_lst[cards] = NULL; | ||
671 | |||
672 | ret = register_chrdev(VFC_MAJOR, vfcstr, &vfc_fops); | ||
673 | if(ret) { | ||
674 | printk(KERN_ERR "Unable to get major number %d\n", VFC_MAJOR); | ||
675 | kfree(vfc_dev_lst); | ||
676 | return -EIO; | ||
677 | } | ||
678 | instance = 0; | ||
679 | for_all_sbusdev(sdev, sbus) { | ||
680 | if (strcmp(sdev->prom_name, "vfc") == 0) { | ||
681 | vfc_dev_lst[instance]=(struct vfc_dev *) | ||
682 | kmalloc(sizeof(struct vfc_dev), GFP_KERNEL); | ||
683 | if (vfc_dev_lst[instance] == NULL) | ||
684 | return -ENOMEM; | ||
685 | ret = init_vfc_device(sdev, | ||
686 | vfc_dev_lst[instance], | ||
687 | instance); | ||
688 | if(ret) { | ||
689 | printk(KERN_ERR "Unable to initialize" | ||
690 | " vfc%d device\n", | ||
691 | instance); | ||
692 | } else { | ||
693 | } | ||
694 | |||
695 | instance++; | ||
696 | continue; | ||
697 | } | ||
698 | } | ||
699 | |||
700 | return 0; | ||
701 | } | ||
702 | |||
703 | #ifdef MODULE | ||
704 | int init_module(void) | ||
705 | #else | ||
706 | int vfc_init(void) | ||
707 | #endif | ||
708 | { | ||
709 | return vfc_probe(); | ||
710 | } | ||
711 | |||
712 | #ifdef MODULE | ||
713 | static void deinit_vfc_device(struct vfc_dev *dev) | ||
714 | { | ||
715 | if(dev == NULL) | ||
716 | return; | ||
717 | sbus_iounmap(dev->regs, sizeof(struct vfc_regs)); | ||
718 | kfree(dev); | ||
719 | } | ||
720 | |||
721 | void cleanup_module(void) | ||
722 | { | ||
723 | struct vfc_dev **devp; | ||
724 | |||
725 | unregister_chrdev(VFC_MAJOR,vfcstr); | ||
726 | |||
727 | for (devp = vfc_dev_lst; *devp; devp++) | ||
728 | deinit_vfc_device(*devp); | ||
729 | |||
730 | kfree(vfc_dev_lst); | ||
731 | return; | ||
732 | } | ||
733 | #endif | ||
734 | |||
735 | MODULE_LICENSE("GPL"); | ||
736 | |||
diff --git a/drivers/sbus/char/vfc_i2c.c b/drivers/sbus/char/vfc_i2c.c deleted file mode 100644 index 32b986e0ed78..000000000000 --- a/drivers/sbus/char/vfc_i2c.c +++ /dev/null | |||
@@ -1,335 +0,0 @@ | |||
1 | /* | ||
2 | * drivers/sbus/char/vfc_i2c.c | ||
3 | * | ||
4 | * Driver for the Videopix Frame Grabber. | ||
5 | * | ||
6 | * Functions that support the Phillips i2c(I squared C) bus on the vfc | ||
7 | * Documentation for the Phillips I2C bus can be found on the | ||
8 | * phillips home page | ||
9 | * | ||
10 | * Copyright (C) 1996 Manish Vachharajani (mvachhar@noc.rutgers.edu) | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | /* NOTE: It seems to me that the documentation regarding the | ||
15 | pcd8584t/pcf8584 does not show the correct way to address the i2c bus. | ||
16 | Based on the information on the I2C bus itself and the remainder of | ||
17 | the Phillips docs the following algorithms appear to be correct. I am | ||
18 | fairly certain that the flowcharts in the phillips docs are wrong. */ | ||
19 | |||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/string.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/errno.h> | ||
25 | #include <linux/sched.h> | ||
26 | #include <linux/wait.h> | ||
27 | #include <linux/delay.h> | ||
28 | #include <asm/openprom.h> | ||
29 | #include <asm/oplib.h> | ||
30 | #include <asm/io.h> | ||
31 | #include <asm/system.h> | ||
32 | #include <asm/sbus.h> | ||
33 | |||
34 | #if 0 | ||
35 | #define VFC_I2C_DEBUG | ||
36 | #endif | ||
37 | |||
38 | #include "vfc.h" | ||
39 | #include "vfc_i2c.h" | ||
40 | |||
41 | #define WRITE_S1(__val) \ | ||
42 | sbus_writel(__val, &dev->regs->i2c_s1) | ||
43 | #define WRITE_REG(__val) \ | ||
44 | sbus_writel(__val, &dev->regs->i2c_reg) | ||
45 | |||
46 | #define VFC_I2C_READ (0x1) | ||
47 | #define VFC_I2C_WRITE (0x0) | ||
48 | |||
49 | /****** | ||
50 | The i2c bus controller chip on the VFC is a pcd8584t, but | ||
51 | phillips claims it doesn't exist. As far as I can tell it is | ||
52 | identical to the PCF8584 so I treat it like it is the pcf8584. | ||
53 | |||
54 | NOTE: The pcf8584 only cares | ||
55 | about the msb of the word you feed it | ||
56 | *****/ | ||
57 | |||
58 | int vfc_pcf8584_init(struct vfc_dev *dev) | ||
59 | { | ||
60 | /* This will also choose register S0_OWN so we can set it. */ | ||
61 | WRITE_S1(RESET); | ||
62 | |||
63 | /* The pcf8584 shifts this value left one bit and uses | ||
64 | * it as its i2c bus address. | ||
65 | */ | ||
66 | WRITE_REG(0x55000000); | ||
67 | |||
68 | /* This will set the i2c bus at the same speed sun uses, | ||
69 | * and set another magic bit. | ||
70 | */ | ||
71 | WRITE_S1(SELECT(S2)); | ||
72 | WRITE_REG(0x14000000); | ||
73 | |||
74 | /* Enable the serial port, idle the i2c bus and set | ||
75 | * the data reg to s0. | ||
76 | */ | ||
77 | WRITE_S1(CLEAR_I2C_BUS); | ||
78 | udelay(100); | ||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | void vfc_i2c_delay_no_busy(struct vfc_dev *dev, unsigned long usecs) | ||
83 | { | ||
84 | schedule_timeout_uninterruptible(usecs_to_jiffies(usecs)); | ||
85 | } | ||
86 | |||
87 | void inline vfc_i2c_delay(struct vfc_dev *dev) | ||
88 | { | ||
89 | vfc_i2c_delay_no_busy(dev, 100); | ||
90 | } | ||
91 | |||
92 | int vfc_init_i2c_bus(struct vfc_dev *dev) | ||
93 | { | ||
94 | WRITE_S1(ENABLE_SERIAL | SELECT(S0) | ACK); | ||
95 | vfc_i2c_reset_bus(dev); | ||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | int vfc_i2c_reset_bus(struct vfc_dev *dev) | ||
100 | { | ||
101 | VFC_I2C_DEBUG_PRINTK((KERN_DEBUG "vfc%d: Resetting the i2c bus\n", | ||
102 | dev->instance)); | ||
103 | if(dev == NULL) | ||
104 | return -EINVAL; | ||
105 | if(dev->regs == NULL) | ||
106 | return -EINVAL; | ||
107 | WRITE_S1(SEND_I2C_STOP); | ||
108 | WRITE_S1(SEND_I2C_STOP | ACK); | ||
109 | vfc_i2c_delay(dev); | ||
110 | WRITE_S1(CLEAR_I2C_BUS); | ||
111 | VFC_I2C_DEBUG_PRINTK((KERN_DEBUG "vfc%d: I2C status %x\n", | ||
112 | dev->instance, | ||
113 | sbus_readl(&dev->regs->i2c_s1))); | ||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | static int vfc_i2c_wait_for_bus(struct vfc_dev *dev) | ||
118 | { | ||
119 | int timeout = 1000; | ||
120 | |||
121 | while(!(sbus_readl(&dev->regs->i2c_s1) & BB)) { | ||
122 | if(!(timeout--)) | ||
123 | return -ETIMEDOUT; | ||
124 | vfc_i2c_delay(dev); | ||
125 | } | ||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | static int vfc_i2c_wait_for_pin(struct vfc_dev *dev, int ack) | ||
130 | { | ||
131 | int timeout = 1000; | ||
132 | int s1; | ||
133 | |||
134 | while ((s1 = sbus_readl(&dev->regs->i2c_s1)) & PIN) { | ||
135 | if (!(timeout--)) | ||
136 | return -ETIMEDOUT; | ||
137 | vfc_i2c_delay(dev); | ||
138 | } | ||
139 | if (ack == VFC_I2C_ACK_CHECK) { | ||
140 | if(s1 & LRB) | ||
141 | return -EIO; | ||
142 | } | ||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | #define SHIFT(a) ((a) << 24) | ||
147 | static int vfc_i2c_xmit_addr(struct vfc_dev *dev, unsigned char addr, | ||
148 | char mode) | ||
149 | { | ||
150 | int ret, raddr; | ||
151 | #if 1 | ||
152 | WRITE_S1(SEND_I2C_STOP | ACK); | ||
153 | WRITE_S1(SELECT(S0) | ENABLE_SERIAL); | ||
154 | vfc_i2c_delay(dev); | ||
155 | #endif | ||
156 | |||
157 | switch(mode) { | ||
158 | case VFC_I2C_READ: | ||
159 | raddr = SHIFT(((unsigned int)addr | 0x1)); | ||
160 | WRITE_REG(raddr); | ||
161 | VFC_I2C_DEBUG_PRINTK(("vfc%d: receiving from i2c addr 0x%x\n", | ||
162 | dev->instance, addr | 0x1)); | ||
163 | break; | ||
164 | case VFC_I2C_WRITE: | ||
165 | raddr = SHIFT((unsigned int)addr & ~0x1); | ||
166 | WRITE_REG(raddr); | ||
167 | VFC_I2C_DEBUG_PRINTK(("vfc%d: sending to i2c addr 0x%x\n", | ||
168 | dev->instance, addr & ~0x1)); | ||
169 | break; | ||
170 | default: | ||
171 | return -EINVAL; | ||
172 | }; | ||
173 | |||
174 | WRITE_S1(SEND_I2C_START); | ||
175 | vfc_i2c_delay(dev); | ||
176 | ret = vfc_i2c_wait_for_pin(dev,VFC_I2C_ACK_CHECK); /* We wait | ||
177 | for the | ||
178 | i2c send | ||
179 | to finish | ||
180 | here but | ||
181 | Sun | ||
182 | doesn't, | ||
183 | hmm */ | ||
184 | if (ret) { | ||
185 | printk(KERN_ERR "vfc%d: VFC xmit addr timed out or no ack\n", | ||
186 | dev->instance); | ||
187 | return ret; | ||
188 | } else if (mode == VFC_I2C_READ) { | ||
189 | if ((ret = sbus_readl(&dev->regs->i2c_reg) & 0xff000000) != raddr) { | ||
190 | printk(KERN_WARNING | ||
191 | "vfc%d: returned slave address " | ||
192 | "mismatch(%x,%x)\n", | ||
193 | dev->instance, raddr, ret); | ||
194 | } | ||
195 | } | ||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | static int vfc_i2c_xmit_byte(struct vfc_dev *dev,unsigned char *byte) | ||
200 | { | ||
201 | int ret; | ||
202 | u32 val = SHIFT((unsigned int)*byte); | ||
203 | |||
204 | WRITE_REG(val); | ||
205 | |||
206 | ret = vfc_i2c_wait_for_pin(dev, VFC_I2C_ACK_CHECK); | ||
207 | switch(ret) { | ||
208 | case -ETIMEDOUT: | ||
209 | printk(KERN_ERR "vfc%d: VFC xmit byte timed out or no ack\n", | ||
210 | dev->instance); | ||
211 | break; | ||
212 | case -EIO: | ||
213 | ret = XMIT_LAST_BYTE; | ||
214 | break; | ||
215 | default: | ||
216 | break; | ||
217 | }; | ||
218 | |||
219 | return ret; | ||
220 | } | ||
221 | |||
222 | static int vfc_i2c_recv_byte(struct vfc_dev *dev, unsigned char *byte, | ||
223 | int last) | ||
224 | { | ||
225 | int ret; | ||
226 | |||
227 | if (last) { | ||
228 | WRITE_REG(NEGATIVE_ACK); | ||
229 | VFC_I2C_DEBUG_PRINTK(("vfc%d: sending negative ack\n", | ||
230 | dev->instance)); | ||
231 | } else { | ||
232 | WRITE_S1(ACK); | ||
233 | } | ||
234 | |||
235 | ret = vfc_i2c_wait_for_pin(dev, VFC_I2C_NO_ACK_CHECK); | ||
236 | if(ret) { | ||
237 | printk(KERN_ERR "vfc%d: " | ||
238 | "VFC recv byte timed out\n", | ||
239 | dev->instance); | ||
240 | } | ||
241 | *byte = (sbus_readl(&dev->regs->i2c_reg)) >> 24; | ||
242 | return ret; | ||
243 | } | ||
244 | |||
245 | int vfc_i2c_recvbuf(struct vfc_dev *dev, unsigned char addr, | ||
246 | char *buf, int count) | ||
247 | { | ||
248 | int ret, last; | ||
249 | |||
250 | if(!(count && buf && dev && dev->regs) ) | ||
251 | return -EINVAL; | ||
252 | |||
253 | if ((ret = vfc_i2c_wait_for_bus(dev))) { | ||
254 | printk(KERN_ERR "vfc%d: VFC I2C bus busy\n", dev->instance); | ||
255 | return ret; | ||
256 | } | ||
257 | |||
258 | if ((ret = vfc_i2c_xmit_addr(dev, addr, VFC_I2C_READ))) { | ||
259 | WRITE_S1(SEND_I2C_STOP); | ||
260 | vfc_i2c_delay(dev); | ||
261 | return ret; | ||
262 | } | ||
263 | |||
264 | last = 0; | ||
265 | while (count--) { | ||
266 | if (!count) | ||
267 | last = 1; | ||
268 | if ((ret = vfc_i2c_recv_byte(dev, buf, last))) { | ||
269 | printk(KERN_ERR "vfc%d: " | ||
270 | "VFC error while receiving byte\n", | ||
271 | dev->instance); | ||
272 | WRITE_S1(SEND_I2C_STOP); | ||
273 | ret = -EINVAL; | ||
274 | } | ||
275 | buf++; | ||
276 | } | ||
277 | WRITE_S1(SEND_I2C_STOP | ACK); | ||
278 | vfc_i2c_delay(dev); | ||
279 | return ret; | ||
280 | } | ||
281 | |||
282 | int vfc_i2c_sendbuf(struct vfc_dev *dev, unsigned char addr, | ||
283 | char *buf, int count) | ||
284 | { | ||
285 | int ret; | ||
286 | |||
287 | if (!(buf && dev && dev->regs)) | ||
288 | return -EINVAL; | ||
289 | |||
290 | if ((ret = vfc_i2c_wait_for_bus(dev))) { | ||
291 | printk(KERN_ERR "vfc%d: VFC I2C bus busy\n", dev->instance); | ||
292 | return ret; | ||
293 | } | ||
294 | |||
295 | if ((ret = vfc_i2c_xmit_addr(dev, addr, VFC_I2C_WRITE))) { | ||
296 | WRITE_S1(SEND_I2C_STOP); | ||
297 | vfc_i2c_delay(dev); | ||
298 | return ret; | ||
299 | } | ||
300 | |||
301 | while(count--) { | ||
302 | ret = vfc_i2c_xmit_byte(dev, buf); | ||
303 | switch(ret) { | ||
304 | case XMIT_LAST_BYTE: | ||
305 | VFC_I2C_DEBUG_PRINTK(("vfc%d: " | ||
306 | "Receiver ended transmission with " | ||
307 | " %d bytes remaining\n", | ||
308 | dev->instance, count)); | ||
309 | ret = 0; | ||
310 | goto done; | ||
311 | break; | ||
312 | case 0: | ||
313 | break; | ||
314 | default: | ||
315 | printk(KERN_ERR "vfc%d: " | ||
316 | "VFC error while sending byte\n", dev->instance); | ||
317 | break; | ||
318 | }; | ||
319 | |||
320 | buf++; | ||
321 | } | ||
322 | done: | ||
323 | WRITE_S1(SEND_I2C_STOP | ACK); | ||
324 | vfc_i2c_delay(dev); | ||
325 | return ret; | ||
326 | } | ||
327 | |||
328 | |||
329 | |||
330 | |||
331 | |||
332 | |||
333 | |||
334 | |||
335 | |||
diff --git a/drivers/sbus/char/vfc_i2c.h b/drivers/sbus/char/vfc_i2c.h deleted file mode 100644 index a2e6973209d5..000000000000 --- a/drivers/sbus/char/vfc_i2c.h +++ /dev/null | |||
@@ -1,44 +0,0 @@ | |||
1 | #ifndef _LINUX_VFC_I2C_H_ | ||
2 | #define _LINUX_VFC_I2C_H_ | ||
3 | |||
4 | /* control bits */ | ||
5 | #define PIN (0x80000000) | ||
6 | #define ESO (0x40000000) | ||
7 | #define ES1 (0x20000000) | ||
8 | #define ES2 (0x10000000) | ||
9 | #define ENI (0x08000000) | ||
10 | #define STA (0x04000000) | ||
11 | #define STO (0x02000000) | ||
12 | #define ACK (0x01000000) | ||
13 | |||
14 | /* status bits */ | ||
15 | #define STS (0x20000000) | ||
16 | #define BER (0x10000000) | ||
17 | #define LRB (0x08000000) | ||
18 | #define AAS (0x04000000) | ||
19 | #define LAB (0x02000000) | ||
20 | #define BB (0x01000000) | ||
21 | |||
22 | #define SEND_I2C_START (PIN | ESO | STA) | ||
23 | #define SEND_I2C_STOP (PIN | ESO | STO) | ||
24 | #define CLEAR_I2C_BUS (PIN | ESO | ACK) | ||
25 | #define NEGATIVE_ACK ((ESO) & ~ACK) | ||
26 | |||
27 | #define SELECT(a) (a) | ||
28 | #define S0 (PIN | ESO | ES1) | ||
29 | #define S0_OWN (PIN) | ||
30 | #define S2 (PIN | ES1) | ||
31 | #define S3 (PIN | ES2) | ||
32 | |||
33 | #define ENABLE_SERIAL (PIN | ESO) | ||
34 | #define DISABLE_SERIAL (PIN) | ||
35 | #define RESET (PIN) | ||
36 | |||
37 | #define XMIT_LAST_BYTE (1) | ||
38 | #define VFC_I2C_ACK_CHECK (1) | ||
39 | #define VFC_I2C_NO_ACK_CHECK (0) | ||
40 | |||
41 | #endif /* _LINUX_VFC_I2C_H_ */ | ||
42 | |||
43 | |||
44 | |||