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