]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/media/video/cx18/cx18-i2c.c
[SCSI] fcoe: fix configuration problems
[linux-2.6-omap-h63xx.git] / drivers / media / video / cx18 / cx18-i2c.c
1 /*
2  *  cx18 I2C functions
3  *
4  *  Derived from ivtv-i2c.c
5  *
6  *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21  *  02111-1307  USA
22  */
23
24 #include "cx18-driver.h"
25 #include "cx18-io.h"
26 #include "cx18-cards.h"
27 #include "cx18-gpio.h"
28 #include "cx18-av-core.h"
29 #include "cx18-i2c.h"
30
31 #define CX18_REG_I2C_1_WR   0xf15000
32 #define CX18_REG_I2C_1_RD   0xf15008
33 #define CX18_REG_I2C_2_WR   0xf25100
34 #define CX18_REG_I2C_2_RD   0xf25108
35
36 #define SETSCL_BIT      0x0001
37 #define SETSDL_BIT      0x0002
38 #define GETSCL_BIT      0x0004
39 #define GETSDL_BIT      0x0008
40
41 #define CX18_CS5345_I2C_ADDR            0x4c
42
43 /* This array should match the CX18_HW_ defines */
44 static const u8 hw_driverids[] = {
45         I2C_DRIVERID_TUNER,
46         I2C_DRIVERID_TVEEPROM,
47         I2C_DRIVERID_CS5345,
48         0,              /* CX18_HW_GPIO dummy driver ID */
49         0               /* CX18_HW_CX23418 dummy driver ID */
50 };
51
52 /* This array should match the CX18_HW_ defines */
53 static const u8 hw_addrs[] = {
54         0,
55         0,
56         CX18_CS5345_I2C_ADDR,
57         0,              /* CX18_HW_GPIO dummy driver ID */
58         0,              /* CX18_HW_CX23418 dummy driver ID */
59 };
60
61 /* This array should match the CX18_HW_ defines */
62 /* This might well become a card-specific array */
63 static const u8 hw_bus[] = {
64         0,
65         0,
66         0,
67         0,              /* CX18_HW_GPIO dummy driver ID */
68         0,              /* CX18_HW_CX23418 dummy driver ID */
69 };
70
71 /* This array should match the CX18_HW_ defines */
72 static const char * const hw_devicenames[] = {
73         "tuner",
74         "tveeprom",
75         "cs5345",
76         "gpio",
77         "cx23418",
78 };
79
80 int cx18_i2c_register(struct cx18 *cx, unsigned idx)
81 {
82         struct i2c_board_info info;
83         struct i2c_client *c;
84         u8 id, bus;
85         int i;
86
87         CX18_DEBUG_I2C("i2c client register\n");
88         if (idx >= ARRAY_SIZE(hw_driverids) || hw_driverids[idx] == 0)
89                 return -1;
90         id = hw_driverids[idx];
91         bus = hw_bus[idx];
92         memset(&info, 0, sizeof(info));
93         strlcpy(info.type, hw_devicenames[idx], sizeof(info.type));
94         info.addr = hw_addrs[idx];
95         for (i = 0; i < I2C_CLIENTS_MAX; i++)
96                 if (cx->i2c_clients[i] == NULL)
97                         break;
98
99         if (i == I2C_CLIENTS_MAX) {
100                 CX18_ERR("insufficient room for new I2C client!\n");
101                 return -ENOMEM;
102         }
103
104         if (id != I2C_DRIVERID_TUNER) {
105                 c = i2c_new_device(&cx->i2c_adap[bus], &info);
106                 if (c->driver == NULL)
107                         i2c_unregister_device(c);
108                 else
109                         cx->i2c_clients[i] = c;
110                 return cx->i2c_clients[i] ? 0 : -ENODEV;
111         }
112
113         /* special tuner handling */
114         c = i2c_new_probed_device(&cx->i2c_adap[1], &info, cx->card_i2c->radio);
115         if (c && c->driver == NULL)
116                 i2c_unregister_device(c);
117         else if (c)
118                 cx->i2c_clients[i++] = c;
119         c = i2c_new_probed_device(&cx->i2c_adap[1], &info, cx->card_i2c->demod);
120         if (c && c->driver == NULL)
121                 i2c_unregister_device(c);
122         else if (c)
123                 cx->i2c_clients[i++] = c;
124         c = i2c_new_probed_device(&cx->i2c_adap[1], &info, cx->card_i2c->tv);
125         if (c && c->driver == NULL)
126                 i2c_unregister_device(c);
127         else if (c)
128                 cx->i2c_clients[i++] = c;
129         return 0;
130 }
131
132 static int attach_inform(struct i2c_client *client)
133 {
134         return 0;
135 }
136
137 static int detach_inform(struct i2c_client *client)
138 {
139         int i;
140         struct cx18 *cx = (struct cx18 *)i2c_get_adapdata(client->adapter);
141
142         CX18_DEBUG_I2C("i2c client detach\n");
143         for (i = 0; i < I2C_CLIENTS_MAX; i++) {
144                 if (cx->i2c_clients[i] == client) {
145                         cx->i2c_clients[i] = NULL;
146                         break;
147                 }
148         }
149         CX18_DEBUG_I2C("i2c detach [client=%s,%s]\n",
150                    client->name, (i < I2C_CLIENTS_MAX) ? "ok" : "failed");
151
152         return 0;
153 }
154
155 static void cx18_setscl(void *data, int state)
156 {
157         struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
158         int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
159         u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR;
160         u32 r = cx18_read_reg(cx, addr);
161
162         if (state)
163                 cx18_write_reg_sync(cx, r | SETSCL_BIT, addr);
164         else
165                 cx18_write_reg_sync(cx, r & ~SETSCL_BIT, addr);
166 }
167
168 static void cx18_setsda(void *data, int state)
169 {
170         struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
171         int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
172         u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR;
173         u32 r = cx18_read_reg(cx, addr);
174
175         if (state)
176                 cx18_write_reg_sync(cx, r | SETSDL_BIT, addr);
177         else
178                 cx18_write_reg_sync(cx, r & ~SETSDL_BIT, addr);
179 }
180
181 static int cx18_getscl(void *data)
182 {
183         struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
184         int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
185         u32 addr = bus_index ? CX18_REG_I2C_2_RD : CX18_REG_I2C_1_RD;
186
187         return cx18_read_reg(cx, addr) & GETSCL_BIT;
188 }
189
190 static int cx18_getsda(void *data)
191 {
192         struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
193         int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
194         u32 addr = bus_index ? CX18_REG_I2C_2_RD : CX18_REG_I2C_1_RD;
195
196         return cx18_read_reg(cx, addr) & GETSDL_BIT;
197 }
198
199 /* template for i2c-bit-algo */
200 static struct i2c_adapter cx18_i2c_adap_template = {
201         .name = "cx18 i2c driver",
202         .id = I2C_HW_B_CX2341X,
203         .algo = NULL,                   /* set by i2c-algo-bit */
204         .algo_data = NULL,              /* filled from template */
205         .client_register = attach_inform,
206         .client_unregister = detach_inform,
207         .owner = THIS_MODULE,
208 };
209
210 #define CX18_SCL_PERIOD (10) /* usecs. 10 usec is period for a 100 KHz clock */
211 #define CX18_ALGO_BIT_TIMEOUT (2) /* seconds */
212
213 static struct i2c_algo_bit_data cx18_i2c_algo_template = {
214         .setsda         = cx18_setsda,
215         .setscl         = cx18_setscl,
216         .getsda         = cx18_getsda,
217         .getscl         = cx18_getscl,
218         .udelay         = CX18_SCL_PERIOD/2,       /* 1/2 clock period in usec*/
219         .timeout        = CX18_ALGO_BIT_TIMEOUT*HZ /* jiffies */
220 };
221
222 static struct i2c_client cx18_i2c_client_template = {
223         .name = "cx18 internal",
224 };
225
226 int cx18_call_i2c_client(struct cx18 *cx, int addr, unsigned cmd, void *arg)
227 {
228         struct i2c_client *client;
229         int retval;
230         int i;
231
232         CX18_DEBUG_I2C("call_i2c_client addr=%02x\n", addr);
233         for (i = 0; i < I2C_CLIENTS_MAX; i++) {
234                 client = cx->i2c_clients[i];
235                 if (client == NULL || client->driver == NULL ||
236                                 client->driver->command == NULL)
237                         continue;
238                 if (addr == client->addr) {
239                         retval = client->driver->command(client, cmd, arg);
240                         return retval;
241                 }
242         }
243         if (cmd != VIDIOC_G_CHIP_IDENT)
244                 CX18_ERR("i2c addr 0x%02x not found for cmd 0x%x!\n",
245                                addr, cmd);
246         return -ENODEV;
247 }
248
249 /* Find the i2c device based on the driver ID and return
250    its i2c address or -ENODEV if no matching device was found. */
251 static int cx18_i2c_id_addr(struct cx18 *cx, u32 id)
252 {
253         struct i2c_client *client;
254         int retval = -ENODEV;
255         int i;
256
257         for (i = 0; i < I2C_CLIENTS_MAX; i++) {
258                 client = cx->i2c_clients[i];
259                 if (client == NULL || client->driver == NULL)
260                         continue;
261                 if (id == client->driver->id) {
262                         retval = client->addr;
263                         break;
264                 }
265         }
266         return retval;
267 }
268
269 /* Find the i2c device name matching the DRIVERID */
270 static const char *cx18_i2c_id_name(u32 id)
271 {
272         int i;
273
274         for (i = 0; i < ARRAY_SIZE(hw_driverids); i++)
275                 if (hw_driverids[i] == id)
276                         return hw_devicenames[i];
277         return "unknown device";
278 }
279
280 /* Find the i2c device name matching the CX18_HW_ flag */
281 static const char *cx18_i2c_hw_name(u32 hw)
282 {
283         int i;
284
285         for (i = 0; i < ARRAY_SIZE(hw_driverids); i++)
286                 if (1 << i == hw)
287                         return hw_devicenames[i];
288         return "unknown device";
289 }
290
291 /* Find the i2c device matching the CX18_HW_ flag and return
292    its i2c address or -ENODEV if no matching device was found. */
293 int cx18_i2c_hw_addr(struct cx18 *cx, u32 hw)
294 {
295         int i;
296
297         for (i = 0; i < ARRAY_SIZE(hw_driverids); i++)
298                 if (1 << i == hw)
299                         return cx18_i2c_id_addr(cx, hw_driverids[i]);
300         return -ENODEV;
301 }
302
303 /* Calls i2c device based on CX18_HW_ flag. If hw == 0, then do nothing.
304    If hw == CX18_HW_GPIO then call the gpio handler. */
305 int cx18_i2c_hw(struct cx18 *cx, u32 hw, unsigned int cmd, void *arg)
306 {
307         int addr;
308
309         if (hw == 0)
310                 return 0;
311
312         if (hw == CX18_HW_GPIO)
313                 return cx18_gpio(cx, cmd, arg);
314
315         if (hw == CX18_HW_CX23418)
316                 return cx18_av_cmd(cx, cmd, arg);
317
318         addr = cx18_i2c_hw_addr(cx, hw);
319         if (addr < 0) {
320                 CX18_ERR("i2c hardware 0x%08x (%s) not found for cmd 0x%x!\n",
321                                hw, cx18_i2c_hw_name(hw), cmd);
322                 return addr;
323         }
324         return cx18_call_i2c_client(cx, addr, cmd, arg);
325 }
326
327 /* Calls i2c device based on I2C driver ID. */
328 int cx18_i2c_id(struct cx18 *cx, u32 id, unsigned int cmd, void *arg)
329 {
330         int addr;
331
332         addr = cx18_i2c_id_addr(cx, id);
333         if (addr < 0) {
334                 if (cmd != VIDIOC_G_CHIP_IDENT)
335                         CX18_ERR("i2c ID 0x%08x (%s) not found for cmd 0x%x!\n",
336                                 id, cx18_i2c_id_name(id), cmd);
337                 return addr;
338         }
339         return cx18_call_i2c_client(cx, addr, cmd, arg);
340 }
341
342 /* broadcast cmd for all I2C clients and for the gpio subsystem */
343 void cx18_call_i2c_clients(struct cx18 *cx, unsigned int cmd, void *arg)
344 {
345         if (cx->i2c_adap[0].algo == NULL || cx->i2c_adap[1].algo == NULL) {
346                 CX18_ERR("adapter is not set\n");
347                 return;
348         }
349         cx18_av_cmd(cx, cmd, arg);
350         i2c_clients_command(&cx->i2c_adap[0], cmd, arg);
351         i2c_clients_command(&cx->i2c_adap[1], cmd, arg);
352         if (cx->hw_flags & CX18_HW_GPIO)
353                 cx18_gpio(cx, cmd, arg);
354 }
355
356 /* init + register i2c algo-bit adapter */
357 int init_cx18_i2c(struct cx18 *cx)
358 {
359         int i;
360         CX18_DEBUG_I2C("i2c init\n");
361
362         /* Sanity checks for the I2C hardware arrays. They must be the
363          * same size and GPIO/CX23418 must be the last entries.
364          */
365         if (ARRAY_SIZE(hw_driverids) != ARRAY_SIZE(hw_addrs) ||
366             ARRAY_SIZE(hw_devicenames) != ARRAY_SIZE(hw_addrs) ||
367             CX18_HW_GPIO != (1 << (ARRAY_SIZE(hw_addrs) - 2)) ||
368             CX18_HW_CX23418 != (1 << (ARRAY_SIZE(hw_addrs) - 1)) ||
369             hw_driverids[ARRAY_SIZE(hw_addrs) - 1]) {
370                 CX18_ERR("Mismatched I2C hardware arrays\n");
371                 return -ENODEV;
372         }
373
374         for (i = 0; i < 2; i++) {
375                 memcpy(&cx->i2c_adap[i], &cx18_i2c_adap_template,
376                         sizeof(struct i2c_adapter));
377                 memcpy(&cx->i2c_algo[i], &cx18_i2c_algo_template,
378                         sizeof(struct i2c_algo_bit_data));
379                 cx->i2c_algo_cb_data[i].cx = cx;
380                 cx->i2c_algo_cb_data[i].bus_index = i;
381                 cx->i2c_algo[i].data = &cx->i2c_algo_cb_data[i];
382                 cx->i2c_adap[i].algo_data = &cx->i2c_algo[i];
383
384                 sprintf(cx->i2c_adap[i].name + strlen(cx->i2c_adap[i].name),
385                                 " #%d-%d", cx->num, i);
386                 i2c_set_adapdata(&cx->i2c_adap[i], cx);
387
388                 memcpy(&cx->i2c_client[i], &cx18_i2c_client_template,
389                         sizeof(struct i2c_client));
390                 sprintf(cx->i2c_client[i].name +
391                                 strlen(cx->i2c_client[i].name), "%d", i);
392                 cx->i2c_client[i].adapter = &cx->i2c_adap[i];
393                 cx->i2c_adap[i].dev.parent = &cx->dev->dev;
394         }
395
396         if (cx18_read_reg(cx, CX18_REG_I2C_2_WR) != 0x0003c02f) {
397                 /* Reset/Unreset I2C hardware block */
398                 /* Clock select 220MHz */
399                 cx18_write_reg(cx, 0x10000000, 0xc71004);
400                 /* Clock Enable */
401                 cx18_write_reg_sync(cx, 0x10001000, 0xc71024);
402         }
403         /* courtesy of Steven Toth <stoth@hauppauge.com> */
404         cx18_write_reg_sync(cx, 0x00c00000, 0xc7001c);
405         mdelay(10);
406         cx18_write_reg_sync(cx, 0x00c000c0, 0xc7001c);
407         mdelay(10);
408         cx18_write_reg_sync(cx, 0x00c00000, 0xc7001c);
409         mdelay(10);
410
411         /* Set to edge-triggered intrs. */
412         cx18_write_reg_sync(cx, 0x00c00000, 0xc730c8);
413         /* Clear any stale intrs */
414         cx18_write_reg_sync(cx, 0x00c00000, 0xc730c4);
415
416         /* Hw I2C1 Clock Freq ~100kHz */
417         cx18_write_reg_sync(cx, 0x00021c0f & ~4, CX18_REG_I2C_1_WR);
418         cx18_setscl(&cx->i2c_algo_cb_data[0], 1);
419         cx18_setsda(&cx->i2c_algo_cb_data[0], 1);
420
421         /* Hw I2C2 Clock Freq ~100kHz */
422         cx18_write_reg_sync(cx, 0x00021c0f & ~4, CX18_REG_I2C_2_WR);
423         cx18_setscl(&cx->i2c_algo_cb_data[1], 1);
424         cx18_setsda(&cx->i2c_algo_cb_data[1], 1);
425
426         cx18_reset_i2c_slaves_gpio(cx);
427
428         return i2c_bit_add_bus(&cx->i2c_adap[0]) ||
429                 i2c_bit_add_bus(&cx->i2c_adap[1]);
430 }
431
432 void exit_cx18_i2c(struct cx18 *cx)
433 {
434         int i;
435         CX18_DEBUG_I2C("i2c exit\n");
436         cx18_write_reg(cx, cx18_read_reg(cx, CX18_REG_I2C_1_WR) | 4,
437                                                         CX18_REG_I2C_1_WR);
438         cx18_write_reg(cx, cx18_read_reg(cx, CX18_REG_I2C_2_WR) | 4,
439                                                         CX18_REG_I2C_2_WR);
440
441         for (i = 0; i < 2; i++) {
442                 i2c_del_adapter(&cx->i2c_adap[i]);
443         }
444 }
445
446 /*
447    Hauppauge HVR1600 should have:
448    32 cx24227
449    98 unknown
450    a0 eeprom
451    c2 tuner
452    e? zilog ir
453    */