1 /*
2 bttv-if.c -- interfaces to other kernel modules
3 all the i2c code is here
4 also the gpio interface exported by bttv (used by lirc)
5
6 bttv - Bt848 frame grabber driver
7
8 Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de)
9 & Marcus Metzler (mocm@thp.uni-koeln.de)
10 (c) 1999,2000 Gerd Knorr <kraxel@goldbach.in-berlin.de>
11
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25
26 */
27
28 #define __NO_VERSION__ 1
29
30 #include <linux/version.h>
31 #include <linux/module.h>
32 #include <linux/init.h>
33
34 #include <asm/io.h>
35
36 #include "bttvp.h"
37 #include "tuner.h"
38
39
40 EXPORT_SYMBOL(bttv_get_cardinfo);
41 EXPORT_SYMBOL(bttv_get_id);
42 EXPORT_SYMBOL(bttv_gpio_enable);
43 EXPORT_SYMBOL(bttv_read_gpio);
44 EXPORT_SYMBOL(bttv_write_gpio);
45 EXPORT_SYMBOL(bttv_get_gpio_queue);
46
47 /* ----------------------------------------------------------------------- */
48 /* Exported functions - for other modules which want to access the */
49 /* gpio ports (IR for example) */
50 /* see bttv.h for comments */
51
52 int bttv_get_cardinfo(unsigned int card, int *type, int *cardid)
53 {
54 if (card >= bttv_num) {
55 return -1;
56 }
57 *type = bttvs[card].type;
58 *cardid = bttvs[card].cardid;
59 return 0;
60 }
61
62 int bttv_get_id(unsigned int card)
63 {
64 printk("bttv_get_id is obsolete, use bttv_get_cardinfo instead\n");
65 if (card >= bttv_num) {
66 return -1;
67 }
68 return bttvs[card].type;
69 }
70
71 int bttv_gpio_enable(unsigned int card, unsigned long mask, unsigned long data)
72 {
73 struct bttv *btv;
74
75 if (card >= bttv_num) {
76 return -EINVAL;
77 }
78
79 btv = &bttvs[card];
80 btaor(data, ~mask, BT848_GPIO_OUT_EN);
81 if (bttv_gpio)
82 bttv_gpio_tracking(btv,"extern enable");
83 return 0;
84 }
85
86 int bttv_read_gpio(unsigned int card, unsigned long *data)
87 {
88 struct bttv *btv;
89
90 if (card >= bttv_num) {
91 return -EINVAL;
92 }
93
94 btv = &bttvs[card];
95
96 if(btv->shutdown) {
97 return -ENODEV;
98 }
99
100 /* prior setting BT848_GPIO_REG_INP is (probably) not needed
101 because we set direct input on init */
102 *data = btread(BT848_GPIO_DATA);
103 return 0;
104 }
105
106 int bttv_write_gpio(unsigned int card, unsigned long mask, unsigned long data)
107 {
108 struct bttv *btv;
109
110 if (card >= bttv_num) {
111 return -EINVAL;
112 }
113
114 btv = &bttvs[card];
115
116 /* prior setting BT848_GPIO_REG_INP is (probably) not needed
117 because direct input is set on init */
118 btaor(data & mask, ~mask, BT848_GPIO_DATA);
119 if (bttv_gpio)
120 bttv_gpio_tracking(btv,"extern write");
121 return 0;
122 }
123
124 wait_queue_head_t* bttv_get_gpio_queue(unsigned int card)
125 {
126 struct bttv *btv;
127
128 if (card >= bttv_num) {
129 return NULL;
130 }
131
132 btv = &bttvs[card];
133 if (bttvs[card].shutdown) {
134 return NULL;
135 }
136 return &btv->gpioq;
137 }
138
139
140 /* ----------------------------------------------------------------------- */
141 /* I2C functions */
142
143 void bttv_bit_setscl(void *data, int state)
144 {
145 struct bttv *btv = (struct bttv*)data;
146
147 if (state)
148 btv->i2c_state |= 0x02;
149 else
150 btv->i2c_state &= ~0x02;
151 btwrite(btv->i2c_state, BT848_I2C);
152 btread(BT848_I2C);
153 }
154
155 void bttv_bit_setsda(void *data, int state)
156 {
157 struct bttv *btv = (struct bttv*)data;
158
159 if (state)
160 btv->i2c_state |= 0x01;
161 else
162 btv->i2c_state &= ~0x01;
163 btwrite(btv->i2c_state, BT848_I2C);
164 btread(BT848_I2C);
165 }
166
167 static int bttv_bit_getscl(void *data)
168 {
169 struct bttv *btv = (struct bttv*)data;
170 int state;
171
172 state = btread(BT848_I2C) & 0x02 ? 1 : 0;
173 return state;
174 }
175
176 static int bttv_bit_getsda(void *data)
177 {
178 struct bttv *btv = (struct bttv*)data;
179 int state;
180
181 state = btread(BT848_I2C) & 0x01;
182 return state;
183 }
184
185 static void bttv_inc_use(struct i2c_adapter *adap)
186 {
187 MOD_INC_USE_COUNT;
188 }
189
190 static void bttv_dec_use(struct i2c_adapter *adap)
191 {
192 MOD_DEC_USE_COUNT;
193 }
194
195 static int attach_inform(struct i2c_client *client)
196 {
197 struct bttv *btv = (struct bttv*)client->adapter->data;
198 int i;
199
200 for (i = 0; i < I2C_CLIENTS_MAX; i++) {
201 if (btv->i2c_clients[i] == NULL) {
202 btv->i2c_clients[i] = client;
203 break;
204 }
205 }
206 if (btv->tuner_type != -1)
207 bttv_call_i2c_clients(btv,TUNER_SET_TYPE,&btv->tuner_type);
208 if (bttv_verbose)
209 printk("bttv%d: i2c attach [%s]\n",btv->nr,client->name);
210 return 0;
211 }
212
213 static int detach_inform(struct i2c_client *client)
214 {
215 struct bttv *btv = (struct bttv*)client->adapter->data;
216 int i;
217
218 if (bttv_verbose)
219 printk("bttv%d: i2c detach [%s]\n",btv->nr,client->name);
220 for (i = 0; i < I2C_CLIENTS_MAX; i++) {
221 if (btv->i2c_clients[i] == client) {
222 btv->i2c_clients[i] = NULL;
223 break;
224 }
225 }
226 return 0;
227 }
228
229 void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg)
230 {
231 int i;
232
233 for (i = 0; i < I2C_CLIENTS_MAX; i++) {
234 if (NULL == btv->i2c_clients[i])
235 continue;
236 if (NULL == btv->i2c_clients[i]->driver->command)
237 continue;
238 btv->i2c_clients[i]->driver->command(
239 btv->i2c_clients[i],cmd,arg);
240 }
241 }
242
243 struct i2c_algo_bit_data bttv_i2c_algo_template = {
244 setsda: bttv_bit_setsda,
245 setscl: bttv_bit_setscl,
246 getsda: bttv_bit_getsda,
247 getscl: bttv_bit_getscl,
248 udelay: 40,
249 mdelay: 10,
250 timeout: 200,
251 };
252
253 struct i2c_adapter bttv_i2c_adap_template = {
254 name: "bt848",
255 id: I2C_HW_B_BT848,
256 inc_use: bttv_inc_use,
257 dec_use: bttv_dec_use,
258 client_register: attach_inform,
259 client_unregister: detach_inform,
260 };
261
262 struct i2c_client bttv_i2c_client_template = {
263 name: "bttv internal use only",
264 id: -1,
265 };
266
267
268 /* read I2C */
269 int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for)
270 {
271 unsigned char buffer = 0;
272
273 if (0 != btv->i2c_rc)
274 return -1;
275 if (bttv_verbose && NULL != probe_for)
276 printk(KERN_INFO "bttv%d: i2c: checking for %s @ 0x%02x... ",
277 btv->nr,probe_for,addr);
278 btv->i2c_client.addr = addr >> 1;
279 if (1 != i2c_master_recv(&btv->i2c_client, &buffer, 1)) {
280 if (NULL != probe_for) {
281 if (bttv_verbose)
282 printk("not found\n");
283 } else
284 printk(KERN_WARNING "bttv%d: i2c read 0x%x: error\n",
285 btv->nr,addr);
286 return -1;
287 }
288 if (bttv_verbose && NULL != probe_for)
289 printk("found\n");
290 return buffer;
291 }
292
293 /* write I2C */
294 int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1,
295 unsigned char b2, int both)
296 {
297 unsigned char buffer[2];
298 int bytes = both ? 2 : 1;
299
300 if (0 != btv->i2c_rc)
301 return -1;
302 btv->i2c_client.addr = addr >> 1;
303 buffer[0] = b1;
304 buffer[1] = b2;
305 if (bytes != i2c_master_send(&btv->i2c_client, buffer, bytes))
306 return -1;
307 return 0;
308 }
309
310 /* read EEPROM content */
311 void __devinit bttv_readee(struct bttv *btv, unsigned char *eedata, int addr)
312 {
313 int i;
314
315 if (bttv_I2CWrite(btv, addr, 0, -1, 0)<0) {
316 printk(KERN_WARNING "bttv: readee error\n");
317 return;
318 }
319 btv->i2c_client.addr = addr >> 1;
320 for (i=0; i<256; i+=16) {
321 if (16 != i2c_master_recv(&btv->i2c_client,eedata+i,16)) {
322 printk(KERN_WARNING "bttv: readee error\n");
323 break;
324 }
325 }
326 }
327
328 /*
329 * Local variables:
330 * c-basic-offset: 8
331 * End:
332 */
333
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.