[media] DiBx000: add addition i2c-interface names
[pandora-kernel.git] / drivers / media / dvb / frontends / dibx000_common.c
1 #include <linux/i2c.h>
2
3 #include "dibx000_common.h"
4
5 static int debug;
6 module_param(debug, int, 0644);
7 MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
8
9 #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiBX000: "); printk(args); printk("\n"); } } while (0)
10
11 static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val)
12 {
13         u8 b[4] = {
14                 (reg >> 8) & 0xff, reg & 0xff,
15                 (val >> 8) & 0xff, val & 0xff,
16         };
17         struct i2c_msg msg = {
18                 .addr = mst->i2c_addr,.flags = 0,.buf = b,.len = 4
19         };
20
21         return i2c_transfer(mst->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
22 }
23
24 static u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg)
25 {
26         u8 wb[2] = { reg >> 8, reg & 0xff };
27         u8 rb[2];
28         struct i2c_msg msg[2] = {
29                 {.addr = mst->i2c_addr,.flags = 0,.buf = wb,.len = 2},
30                 {.addr = mst->i2c_addr,.flags = I2C_M_RD,.buf = rb,.len = 2},
31         };
32
33         if (i2c_transfer(mst->i2c_adap, msg, 2) != 2)
34                 dprintk("i2c read error on %d", reg);
35
36         return (rb[0] << 8) | rb[1];
37 }
38
39 static int dibx000_is_i2c_done(struct dibx000_i2c_master *mst)
40 {
41         int i = 100; // max_i2c_polls;
42         u16 status;
43
44         while (((status = dibx000_read_word(mst, mst->base_reg + 2)) & 0x0100) == 0 && --i > 0);
45
46         /* i2c timed out */
47         if (i == 0)
48                 return -EREMOTEIO;
49
50         /* no acknowledge */
51         if ((status & 0x0080) == 0)
52                 return -EREMOTEIO;
53
54         return 0;
55 }
56
57 static int dibx000_master_i2c_write(struct dibx000_i2c_master *mst, struct i2c_msg *msg, u8 stop)
58 {
59         u16 data;
60         u16 da;
61         u16 i;
62         u16 txlen = msg->len, len;
63         const u8 *b = msg->buf;
64
65         while (txlen) {
66                 dibx000_read_word(mst, mst->base_reg + 2);   // reset fifo ptr
67
68                 len = txlen > 8 ? 8 : txlen;
69                 for (i = 0; i < len; i += 2) {
70                         data = *b++ << 8;
71                         if (i+1 < len)
72                                 data |= *b++;
73                         dibx000_write_word(mst, mst->base_reg, data);
74                 }
75                 da = (((u8) (msg->addr))  << 9) | // addr
76                         (1           << 8) | // master
77                         (1           << 7) | // rq
78                         (0           << 6) | // stop
79                         (0           << 5) | // start
80                         ((len & 0x7) << 2) | // nb 8 bytes == 0 here
81                         (0           << 1) | // rw
82                         (0           << 0);  // irqen
83
84                 if (txlen == msg->len)
85                         da |= 1 << 5; /* start */
86
87                 if (txlen-len == 0 && stop)
88                         da |= 1 << 6; /* stop */
89
90                 dibx000_write_word(mst, mst->base_reg+1, da);
91
92                 if (dibx000_is_i2c_done(mst) != 0)
93                         return -EREMOTEIO;
94                 txlen -= len;
95         }
96
97         return 0;
98 }
99
100 static int dibx000_master_i2c_read(struct dibx000_i2c_master *mst, struct i2c_msg *msg)
101 {
102         u16 da;
103         u8 *b = msg->buf;
104         u16 rxlen = msg->len, len;
105
106         while (rxlen) {
107                 len = rxlen > 8 ? 8 : rxlen;
108                 da = (((u8) (msg->addr)) << 9) | // addr
109                         (1           << 8) | // master
110                         (1           << 7) | // rq
111                         (0           << 6) | // stop
112                         (0           << 5) | // start
113                         ((len & 0x7) << 2) | // nb
114                         (1           << 1) | // rw
115                         (0           << 0);  // irqen
116
117                 if (rxlen == msg->len)
118                         da |= 1 << 5; /* start */
119
120                 if (rxlen-len == 0)
121                         da |= 1 << 6; /* stop */
122                 dibx000_write_word(mst, mst->base_reg+1, da);
123
124                 if (dibx000_is_i2c_done(mst) != 0)
125                         return -EREMOTEIO;
126
127                 rxlen -= len;
128
129                 while (len) {
130                         da = dibx000_read_word(mst, mst->base_reg);
131                         *b++ = (da >> 8) & 0xff;
132                         len--;
133                         if (len >= 1) {
134                                 *b++ =  da   & 0xff;
135                                 len--;
136                         }
137                 }
138         }
139
140         return 0;
141 }
142
143 int dibx000_i2c_set_speed(struct i2c_adapter *i2c_adap, u16 speed)
144 {
145         struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
146
147         if (mst->device_rev < DIB7000MC && speed < 235)
148                 speed = 235;
149         return dibx000_write_word(mst, mst->base_reg + 3, (u16)(60000 / speed));
150
151 }
152 EXPORT_SYMBOL(dibx000_i2c_set_speed);
153
154 static u32 dibx000_i2c_func(struct i2c_adapter *adapter)
155 {
156         return I2C_FUNC_I2C;
157 }
158
159 static int dibx000_i2c_select_interface(struct dibx000_i2c_master *mst,
160                                         enum dibx000_i2c_interface intf)
161 {
162         if (mst->device_rev > DIB3000MC && mst->selected_interface != intf) {
163                 dprintk("selecting interface: %d", intf);
164                 mst->selected_interface = intf;
165                 return dibx000_write_word(mst, mst->base_reg + 4, intf);
166         }
167         return 0;
168 }
169
170 static int dibx000_i2c_master_xfer_gpio12(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
171 {
172         struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
173         int msg_index;
174         int ret = 0;
175
176         dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_1_2);
177         for (msg_index = 0; msg_index<num; msg_index++) {
178                 if (msg[msg_index].flags & I2C_M_RD)
179                 {
180                         ret = dibx000_master_i2c_read(mst, &msg[msg_index]);
181                         if (ret != 0)
182                                 return 0;
183                 }
184                 else
185                 {
186                         ret = dibx000_master_i2c_write(mst, &msg[msg_index], 1);
187                         if (ret != 0)
188                                 return 0;
189                 }
190         }
191
192         return num;
193 }
194
195 static int dibx000_i2c_master_xfer_gpio34(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
196 {
197         struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
198         int msg_index;
199         int ret = 0;
200
201         dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_3_4);
202         for (msg_index = 0; msg_index<num; msg_index++) {
203                 if (msg[msg_index].flags & I2C_M_RD)
204                 {
205                         ret = dibx000_master_i2c_read(mst, &msg[msg_index]);
206                         if (ret != 0)
207                                 return 0;
208                 }
209                 else
210                 {
211                         ret = dibx000_master_i2c_write(mst, &msg[msg_index], 1);
212                         if (ret != 0)
213                                 return 0;
214                 }
215         }
216
217         return num;
218 }
219
220 static struct i2c_algorithm dibx000_i2c_master_gpio12_xfer_algo = {
221         .master_xfer = dibx000_i2c_master_xfer_gpio12,
222         .functionality = dibx000_i2c_func,
223 };
224
225 static struct i2c_algorithm dibx000_i2c_master_gpio34_xfer_algo = {
226         .master_xfer = dibx000_i2c_master_xfer_gpio34,
227         .functionality = dibx000_i2c_func,
228 };
229
230 static int dibx000_i2c_gate_ctrl(struct dibx000_i2c_master *mst, u8 tx[4],
231                                  u8 addr, int onoff)
232 {
233         u16 val;
234
235
236         if (onoff)
237                 val = addr << 8;        // bit 7 = use master or not, if 0, the gate is open
238         else
239                 val = 1 << 7;
240
241         if (mst->device_rev > DIB7000)
242                 val <<= 1;
243
244         tx[0] = (((mst->base_reg + 1) >> 8) & 0xff);
245         tx[1] = ((mst->base_reg + 1) & 0xff);
246         tx[2] = val >> 8;
247         tx[3] = val & 0xff;
248
249         return 0;
250 }
251
252 static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap,
253                                         struct i2c_msg msg[], int num)
254 {
255         struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
256         struct i2c_msg m[2 + num];
257         u8 tx_open[4], tx_close[4];
258
259         memset(m, 0, sizeof(struct i2c_msg) * (2 + num));
260
261         dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_6_7);
262
263         dibx000_i2c_gate_ctrl(mst, tx_open, msg[0].addr, 1);
264         m[0].addr = mst->i2c_addr;
265         m[0].buf = tx_open;
266         m[0].len = 4;
267
268         memcpy(&m[1], msg, sizeof(struct i2c_msg) * num);
269
270         dibx000_i2c_gate_ctrl(mst, tx_close, 0, 0);
271         m[num + 1].addr = mst->i2c_addr;
272         m[num + 1].buf = tx_close;
273         m[num + 1].len = 4;
274
275         return i2c_transfer(mst->i2c_adap, m, 2 + num) == 2 + num ? num : -EIO;
276 }
277
278 static struct i2c_algorithm dibx000_i2c_gated_gpio67_algo = {
279         .master_xfer = dibx000_i2c_gated_gpio67_xfer,
280         .functionality = dibx000_i2c_func,
281 };
282
283 static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap,
284                                         struct i2c_msg msg[], int num)
285 {
286         struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
287         struct i2c_msg m[2 + num];
288         u8 tx_open[4], tx_close[4];
289
290         memset(m, 0, sizeof(struct i2c_msg) * (2 + num));
291
292         dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER);
293
294         dibx000_i2c_gate_ctrl(mst, tx_open, msg[0].addr, 1);
295         m[0].addr = mst->i2c_addr;
296         m[0].buf = tx_open;
297         m[0].len = 4;
298
299         memcpy(&m[1], msg, sizeof(struct i2c_msg) * num);
300
301         dibx000_i2c_gate_ctrl(mst, tx_close, 0, 0);
302         m[num + 1].addr = mst->i2c_addr;
303         m[num + 1].buf = tx_close;
304         m[num + 1].len = 4;
305
306         return i2c_transfer(mst->i2c_adap, m, 2 + num) == 2 + num ? num : -EIO;
307 }
308
309 static struct i2c_algorithm dibx000_i2c_gated_tuner_algo = {
310         .master_xfer = dibx000_i2c_gated_tuner_xfer,
311         .functionality = dibx000_i2c_func,
312 };
313
314 struct i2c_adapter *dibx000_get_i2c_adapter(struct dibx000_i2c_master *mst,
315                                                 enum dibx000_i2c_interface intf,
316                                                 int gating)
317 {
318         struct i2c_adapter *i2c = NULL;
319
320         switch (intf) {
321         case DIBX000_I2C_INTERFACE_TUNER:
322                 if (gating)
323                         i2c = &mst->gated_tuner_i2c_adap;
324                 break;
325         case DIBX000_I2C_INTERFACE_GPIO_1_2:
326                 if (!gating)
327                         i2c = &mst->master_i2c_adap_gpio12;
328                 break;
329         case DIBX000_I2C_INTERFACE_GPIO_3_4:
330                 if (!gating)
331                         i2c = &mst->master_i2c_adap_gpio34;
332                 break;
333         case DIBX000_I2C_INTERFACE_GPIO_6_7:
334                 if (gating)
335                         i2c = &mst->master_i2c_adap_gpio67;
336                 break;
337         default:
338                 printk(KERN_ERR "DiBX000: incorrect I2C interface selected\n");
339                 break;
340         }
341
342         return i2c;
343 }
344
345 EXPORT_SYMBOL(dibx000_get_i2c_adapter);
346
347 void dibx000_reset_i2c_master(struct dibx000_i2c_master *mst)
348 {
349         /* initialize the i2c-master by closing the gate */
350         u8 tx[4];
351         struct i2c_msg m = {.addr = mst->i2c_addr,.buf = tx,.len = 4 };
352
353         dibx000_i2c_gate_ctrl(mst, tx, 0, 0);
354         i2c_transfer(mst->i2c_adap, &m, 1);
355         mst->selected_interface = 0xff; // the first time force a select of the I2C
356         dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER);
357 }
358
359 EXPORT_SYMBOL(dibx000_reset_i2c_master);
360
361 static int i2c_adapter_init(struct i2c_adapter *i2c_adap,
362                                 struct i2c_algorithm *algo, const char *name,
363                                 struct dibx000_i2c_master *mst)
364 {
365         strncpy(i2c_adap->name, name, sizeof(i2c_adap->name));
366         i2c_adap->algo = algo;
367         i2c_adap->algo_data = NULL;
368         i2c_set_adapdata(i2c_adap, mst);
369         if (i2c_add_adapter(i2c_adap) < 0)
370                 return -ENODEV;
371         return 0;
372 }
373
374 int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev,
375                                 struct i2c_adapter *i2c_adap, u8 i2c_addr)
376 {
377         u8 tx[4];
378         struct i2c_msg m = {.addr = i2c_addr >> 1,.buf = tx,.len = 4 };
379
380         mst->device_rev = device_rev;
381         mst->i2c_adap = i2c_adap;
382         mst->i2c_addr = i2c_addr >> 1;
383
384         if (device_rev == DIB7000P || device_rev == DIB8000)
385                 mst->base_reg = 1024;
386         else
387                 mst->base_reg = 768;
388
389         mst->gated_tuner_i2c_adap.dev.parent = mst->i2c_adap->dev.parent;
390         if (i2c_adapter_init
391                         (&mst->gated_tuner_i2c_adap, &dibx000_i2c_gated_tuner_algo,
392                          "DiBX000 tuner I2C bus", mst) != 0)
393                 printk(KERN_ERR
394                                 "DiBX000: could not initialize the tuner i2c_adapter\n");
395
396         mst->master_i2c_adap_gpio12.dev.parent = mst->i2c_adap->dev.parent;
397         if (i2c_adapter_init
398                         (&mst->master_i2c_adap_gpio12, &dibx000_i2c_master_gpio12_xfer_algo,
399                          "DiBX000 master GPIO12 I2C bus", mst) != 0)
400                 printk(KERN_ERR
401                                 "DiBX000: could not initialize the master i2c_adapter\n");
402
403         mst->master_i2c_adap_gpio34.dev.parent = mst->i2c_adap->dev.parent;
404         if (i2c_adapter_init
405                         (&mst->master_i2c_adap_gpio34, &dibx000_i2c_master_gpio34_xfer_algo,
406                          "DiBX000 master GPIO34 I2C bus", mst) != 0)
407                 printk(KERN_ERR
408                                 "DiBX000: could not initialize the master i2c_adapter\n");
409
410         mst->master_i2c_adap_gpio67.dev.parent = mst->i2c_adap->dev.parent;
411         if (i2c_adapter_init
412                         (&mst->master_i2c_adap_gpio67, &dibx000_i2c_gated_gpio67_algo,
413                          "DiBX000 master GPIO67 I2C bus", mst) != 0)
414                 printk(KERN_ERR
415                                 "DiBX000: could not initialize the master i2c_adapter\n");
416
417         /* initialize the i2c-master by closing the gate */
418         dibx000_i2c_gate_ctrl(mst, tx, 0, 0);
419
420         return i2c_transfer(i2c_adap, &m, 1) == 1;
421 }
422
423 EXPORT_SYMBOL(dibx000_init_i2c_master);
424
425 void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst)
426 {
427         i2c_del_adapter(&mst->gated_tuner_i2c_adap);
428         i2c_del_adapter(&mst->master_i2c_adap_gpio12);
429         i2c_del_adapter(&mst->master_i2c_adap_gpio34);
430         i2c_del_adapter(&mst->master_i2c_adap_gpio67);
431 }
432 EXPORT_SYMBOL(dibx000_exit_i2c_master);
433
434
435 u32 systime(void)
436 {
437         struct timespec t;
438
439         t = current_kernel_time();
440         return (t.tv_sec * 10000) + (t.tv_nsec / 100000);
441 }
442 EXPORT_SYMBOL(systime);
443
444 MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
445 MODULE_DESCRIPTION("Common function the DiBcom demodulator family");
446 MODULE_LICENSE("GPL");