File: /usr/src/linux/drivers/media/video/i2c-parport.c

1     /*
2      * I2C driver for parallel port
3      *
4      * Author: Phil Blundell <philb@gnu.org>
5      *
6      * This program is free software; you can redistribute it and/or
7      * modify it under the terms of the GNU General Public License
8      * as published by the Free Software Foundation; either version
9      * 2 of the License, or (at your option) any later version.
10      *
11      * This driver implements a simple I2C protocol by bit-twiddling some
12      * signals on the parallel port.  Since the outputs on the parallel port
13      * aren't open collector, three lines rather than two are used:
14      *
15      *	D0	clock out
16      *	D1	data out
17      *	BUSY	data in	
18      */
19     
20     #include <linux/parport.h>
21     #include <linux/module.h>
22     #include <linux/delay.h>
23     #include <linux/i2c-old.h>
24     #include <linux/init.h>
25     #include <linux/spinlock.h>
26     
27     #define I2C_DELAY   10
28     
29     static int debug = 0;
30     
31     struct parport_i2c_bus
32     {
33       struct i2c_bus i2c;
34       struct parport_i2c_bus *next;
35     };
36     
37     static struct parport_i2c_bus *bus_list;
38     
39     static spinlock_t bus_list_lock = SPIN_LOCK_UNLOCKED;
40     
41     /* software I2C functions */
42     
43     static void i2c_setlines(struct i2c_bus *bus, int clk, int data)
44     {
45       struct parport *p = bus->data;
46       parport_write_data(p, (clk?1:0) | (data?2:0)); 
47       udelay(I2C_DELAY);
48     }
49     
50     static int i2c_getdataline(struct i2c_bus *bus)
51     {
52       struct parport *p = bus->data;
53       return (parport_read_status(p) & PARPORT_STATUS_BUSY) ? 0 : 1;
54     }
55     
56     static struct i2c_bus parport_i2c_bus_template = 
57     {
58       "...",
59       I2C_BUSID_PARPORT,
60       NULL,
61       
62       SPIN_LOCK_UNLOCKED,
63       
64       NULL,
65       NULL,
66     	
67       i2c_setlines,
68       i2c_getdataline,
69       NULL,
70       NULL,
71     };
72     
73     static void i2c_parport_attach(struct parport *port)
74     {
75       struct parport_i2c_bus *b = kmalloc(sizeof(struct parport_i2c_bus), 
76     				      GFP_KERNEL);
77       if (!b) {
78     	  printk(KERN_ERR "i2c_parport: Memory allocation failed. Not attaching.\n");
79     	  return;
80       }
81       b->i2c = parport_i2c_bus_template;
82       b->i2c.data = parport_get_port (port);
83       strncpy(b->i2c.name, port->name, 32);
84       spin_lock(&bus_list_lock);
85       b->next = bus_list;
86       bus_list = b;
87       spin_unlock(&bus_list_lock);
88       i2c_register_bus(&b->i2c);
89       if (debug)
90         printk(KERN_DEBUG "i2c: attached to %s\n", port->name);
91     }
92     
93     static void i2c_parport_detach(struct parport *port)
94     {
95       struct parport_i2c_bus *b, *old_b = NULL;
96       spin_lock(&bus_list_lock);
97       b = bus_list;
98       while (b)
99       {
100         if (b->i2c.data == port)
101         {
102           if (old_b)
103     	old_b->next = b->next;
104           else
105     	bus_list = b->next;
106           i2c_unregister_bus(&b->i2c);
107           kfree(b);
108           break;
109         }
110         old_b = b;
111         b = b->next;
112       }
113       spin_unlock(&bus_list_lock);
114       if (debug)
115         printk(KERN_DEBUG "i2c: detached from %s\n", port->name);
116     }
117     
118     static struct parport_driver parport_i2c_driver = 
119     {
120       "i2c",
121       i2c_parport_attach,
122       i2c_parport_detach
123     };
124     
125     #ifdef MODULE
126     int init_module(void)
127     #else
128     int __init i2c_parport_init(void)
129     #endif
130     {
131       printk("I2C: driver for parallel port v0.1 philb@gnu.org\n");
132       parport_register_driver(&parport_i2c_driver);
133       return 0;
134     }
135     
136     #ifdef MODULE
137     MODULE_PARM(debug, "i");
138     
139     void cleanup_module(void)
140     {
141       struct parport_i2c_bus *b = bus_list;
142       while (b)
143       {
144         struct parport_i2c_bus *next = b->next;
145         i2c_unregister_bus(&b->i2c);
146         kfree(b);
147         b = next;
148       }
149       parport_unregister_driver(&parport_i2c_driver);
150     }
151     #endif
152