Merge remote branch 'alsa/devel' into topic/misc
[pandora-kernel.git] / drivers / media / dvb / mantis / mantis_i2c.c
1 /*
2         Mantis PCI bridge driver
3
4         Copyright (C) Manu Abraham (abraham.manu@gmail.com)
5
6         This program is free software; you can redistribute it and/or modify
7         it under the terms of the GNU General Public License as published by
8         the Free Software Foundation; either version 2 of the License, or
9         (at your option) any later version.
10
11         This program is distributed in the hope that it will be useful,
12         but WITHOUT ANY WARRANTY; without even the implied warranty of
13         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14         GNU General Public License for more details.
15
16         You should have received a copy of the GNU General Public License
17         along with this program; if not, write to the Free Software
18         Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include <asm/io.h>
22 #include <linux/ioport.h>
23 #include <linux/pci.h>
24 #include <linux/i2c.h>
25
26 #include "dmxdev.h"
27 #include "dvbdev.h"
28 #include "dvb_demux.h"
29 #include "dvb_frontend.h"
30 #include "dvb_net.h"
31
32 #include "mantis_common.h"
33 #include "mantis_reg.h"
34 #include "mantis_i2c.h"
35
36 #define TRIALS                  10000
37
38 static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg)
39 {
40         u32 rxd, i, stat, trials;
41
42         dprintk(MANTIS_INFO, 0, "        %s:  Address=[0x%02x] <R>[ ",
43                 __func__, msg->addr);
44
45         for (i = 0; i < msg->len; i++) {
46                 rxd = (msg->addr << 25) | (1 << 24)
47                                         | MANTIS_I2C_RATE_3
48                                         | MANTIS_I2C_STOP
49                                         | MANTIS_I2C_PGMODE;
50
51                 if (i == (msg->len - 1))
52                         rxd &= ~MANTIS_I2C_STOP;
53
54                 mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT);
55                 mmwrite(rxd, MANTIS_I2CDATA_CTL);
56
57                 /* wait for xfer completion */
58                 for (trials = 0; trials < TRIALS; trials++) {
59                         stat = mmread(MANTIS_INT_STAT);
60                         if (stat & MANTIS_INT_I2CDONE)
61                                 break;
62                 }
63
64                 dprintk(MANTIS_TMG, 0, "I2CDONE: trials=%d\n", trials);
65
66                 /* wait for xfer completion */
67                 for (trials = 0; trials < TRIALS; trials++) {
68                         stat = mmread(MANTIS_INT_STAT);
69                         if (stat & MANTIS_INT_I2CRACK)
70                                 break;
71                 }
72
73                 dprintk(MANTIS_TMG, 0, "I2CRACK: trials=%d\n", trials);
74
75                 rxd = mmread(MANTIS_I2CDATA_CTL);
76                 msg->buf[i] = (u8)((rxd >> 8) & 0xFF);
77                 dprintk(MANTIS_INFO, 0, "%02x ", msg->buf[i]);
78         }
79         dprintk(MANTIS_INFO, 0, "]\n");
80
81         return 0;
82 }
83
84 static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg)
85 {
86         int i;
87         u32 txd = 0, stat, trials;
88
89         dprintk(MANTIS_INFO, 0, "        %s: Address=[0x%02x] <W>[ ",
90                 __func__, msg->addr);
91
92         for (i = 0; i < msg->len; i++) {
93                 dprintk(MANTIS_INFO, 0, "%02x ", msg->buf[i]);
94                 txd = (msg->addr << 25) | (msg->buf[i] << 8)
95                                         | MANTIS_I2C_RATE_3
96                                         | MANTIS_I2C_STOP
97                                         | MANTIS_I2C_PGMODE;
98
99                 if (i == (msg->len - 1))
100                         txd &= ~MANTIS_I2C_STOP;
101
102                 mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT);
103                 mmwrite(txd, MANTIS_I2CDATA_CTL);
104
105                 /* wait for xfer completion */
106                 for (trials = 0; trials < TRIALS; trials++) {
107                         stat = mmread(MANTIS_INT_STAT);
108                         if (stat & MANTIS_INT_I2CDONE)
109                                 break;
110                 }
111
112                 dprintk(MANTIS_TMG, 0, "I2CDONE: trials=%d\n", trials);
113
114                 /* wait for xfer completion */
115                 for (trials = 0; trials < TRIALS; trials++) {
116                         stat = mmread(MANTIS_INT_STAT);
117                         if (stat & MANTIS_INT_I2CRACK)
118                                 break;
119                 }
120
121                 dprintk(MANTIS_TMG, 0, "I2CRACK: trials=%d\n", trials);
122         }
123         dprintk(MANTIS_INFO, 0, "]\n");
124
125         return 0;
126 }
127
128 static int mantis_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
129 {
130         int ret = 0, i = 0, trials;
131         u32 stat, data, txd;
132         struct mantis_pci *mantis;
133         struct mantis_hwconfig *config;
134
135         mantis = i2c_get_adapdata(adapter);
136         BUG_ON(!mantis);
137         config = mantis->hwconfig;
138         BUG_ON(!config);
139
140         dprintk(MANTIS_DEBUG, 1, "Messages:%d", num);
141         mutex_lock(&mantis->i2c_lock);
142
143         while (i < num) {
144                 /* Byte MODE */
145                 if ((config->i2c_mode & MANTIS_BYTE_MODE) &&
146                     ((i + 1) < num)                     &&
147                     (msgs[i].len < 2)                   &&
148                     (msgs[i + 1].len < 2)               &&
149                     (msgs[i + 1].flags & I2C_M_RD)) {
150
151                         dprintk(MANTIS_DEBUG, 0, "        Byte MODE:\n");
152
153                         /* Read operation */
154                         txd = msgs[i].addr << 25 | (0x1 << 24)
155                                                  | (msgs[i].buf[0] << 16)
156                                                  | MANTIS_I2C_RATE_3;
157
158                         mmwrite(txd, MANTIS_I2CDATA_CTL);
159                         /* wait for xfer completion */
160                         for (trials = 0; trials < TRIALS; trials++) {
161                                 stat = mmread(MANTIS_INT_STAT);
162                                 if (stat & MANTIS_INT_I2CDONE)
163                                         break;
164                         }
165
166                         /* check for xfer completion */
167                         if (stat & MANTIS_INT_I2CDONE) {
168                                 /* check xfer was acknowledged */
169                                 if (stat & MANTIS_INT_I2CRACK) {
170                                         data = mmread(MANTIS_I2CDATA_CTL);
171                                         msgs[i + 1].buf[0] = (data >> 8) & 0xff;
172                                         dprintk(MANTIS_DEBUG, 0, "        Byte <%d> RXD=0x%02x  [%02x]\n", 0x0, data, msgs[i + 1].buf[0]);
173                                 } else {
174                                         /* I/O error */
175                                         dprintk(MANTIS_ERROR, 1, "        I/O error, LINE:%d", __LINE__);
176                                         ret = -EIO;
177                                         break;
178                                 }
179                         } else {
180                                 /* I/O error */
181                                 dprintk(MANTIS_ERROR, 1, "        I/O error, LINE:%d", __LINE__);
182                                 ret = -EIO;
183                                 break;
184                         }
185                         i += 2; /* Write/Read operation in one go */
186                 }
187
188                 if (i < num) {
189                         if (msgs[i].flags & I2C_M_RD)
190                                 ret = mantis_i2c_read(mantis, &msgs[i]);
191                         else
192                                 ret = mantis_i2c_write(mantis, &msgs[i]);
193
194                         i++;
195                         if (ret < 0)
196                                 goto bail_out;
197                 }
198
199         }
200
201         mutex_unlock(&mantis->i2c_lock);
202
203         return num;
204
205 bail_out:
206         mutex_unlock(&mantis->i2c_lock);
207         return ret;
208 }
209
210 static u32 mantis_i2c_func(struct i2c_adapter *adapter)
211 {
212         return I2C_FUNC_SMBUS_EMUL;
213 }
214
215 static struct i2c_algorithm mantis_algo = {
216         .master_xfer            = mantis_i2c_xfer,
217         .functionality          = mantis_i2c_func,
218 };
219
220 int __devinit mantis_i2c_init(struct mantis_pci *mantis)
221 {
222         u32 intstat, intmask;
223         struct i2c_adapter *i2c_adapter = &mantis->adapter;
224         struct pci_dev *pdev            = mantis->pdev;
225
226         init_waitqueue_head(&mantis->i2c_wq);
227         mutex_init(&mantis->i2c_lock);
228         strncpy(i2c_adapter->name, "Mantis I2C", sizeof(i2c_adapter->name));
229         i2c_set_adapdata(i2c_adapter, mantis);
230
231         i2c_adapter->owner      = THIS_MODULE;
232         i2c_adapter->class      = I2C_CLASS_TV_DIGITAL;
233         i2c_adapter->algo       = &mantis_algo;
234         i2c_adapter->algo_data  = NULL;
235         i2c_adapter->timeout    = 500;
236         i2c_adapter->retries    = 3;
237         i2c_adapter->dev.parent = &pdev->dev;
238
239         mantis->i2c_rc          = i2c_add_adapter(i2c_adapter);
240         if (mantis->i2c_rc < 0)
241                 return mantis->i2c_rc;
242
243         dprintk(MANTIS_DEBUG, 1, "Initializing I2C ..");
244
245         intstat = mmread(MANTIS_INT_STAT);
246         intmask = mmread(MANTIS_INT_MASK);
247         mmwrite(intstat, MANTIS_INT_STAT);
248         dprintk(MANTIS_DEBUG, 1, "Disabling I2C interrupt");
249         intmask = mmread(MANTIS_INT_MASK);
250         mmwrite((intmask & ~MANTIS_INT_I2CDONE), MANTIS_INT_MASK);
251
252         return 0;
253 }
254 EXPORT_SYMBOL_GPL(mantis_i2c_init);
255
256 int mantis_i2c_exit(struct mantis_pci *mantis)
257 {
258         u32 intmask;
259
260         dprintk(MANTIS_DEBUG, 1, "Disabling I2C interrupt");
261         intmask = mmread(MANTIS_INT_MASK);
262         mmwrite((intmask & ~MANTIS_INT_I2CDONE), MANTIS_INT_MASK);
263
264         dprintk(MANTIS_DEBUG, 1, "Removing I2C adapter");
265         return i2c_del_adapter(&mantis->adapter);
266 }
267 EXPORT_SYMBOL_GPL(mantis_i2c_exit);