1 I2C Conversion Guide for I2C-old to the current I2C API
3 For Linux Kernel v2.5.x
4 Frank Davis <fdavis@si.rr.com>
5 -------------------------------------------------------
7 There exists several kernel drivers that are using an old version of the I2C
8 API. These drivers need to be converted to the current (kernel 2.5.x) version.
9 The following document provides a guideline to make the appropriate changes to
10 the affected drivers. There maybe slight modifications to this guide that are
11 specific to the driver you are working on. If you see {driver_name}, replace
12 that with the respective name of the driver, such as saa7110.c , {driver_name}
15 -------------------------------------------------------
17 Step 1: Include the right header file
19 Perform the following change within the driver
21 #include <linux/i2c-old.h> --> #include <linux/i2c.h>
23 Step 2: Add and set the i2c modes
25 Add the following code near the top of the driver
27 static unsigned short normal_i2c[] = {34>>1, I2C_CLIENT_END };
28 static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
29 static unsigned short probe[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
30 static unsigned short probe_range[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
31 static unsigned short ignore[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
32 static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
33 static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
35 static struct i2c_client_address_data addr_data = {
36 normal_i2c , normal_i2c_range,
38 ignore , ignore_range,
42 static struct i2c_client client_template;
44 Step 3: Modify the driver info struct
46 Within the struct for the driver , such as struct {driver_name} , make the
48 struct i2c_bus *bus --> struct i2c_client *client
50 Make changes where this change affects references within the file.
52 Add a semaphore to the driver struct (as above)
56 Step 5: Remove specific read and write functions
58 Remove the driver specific write and read functions, usually in the form:
59 {driver_name}_write , {driver_name}_read , {driver_name}_write_block , etc.
61 Step 6: Update the write and read functions for the current I2C API
63 Replace all references of {driver_name}_write with i2c_smbus_write_byte_data
64 Replace all references of {driver_name}_read with i2c_smbus_read_byte_data or
65 i2c_smbus_read_byte , depending on args passed in.
67 ** Ensure that these functions pass in the i2c_client *client , NOT the
68 decoder/encoder that was passed in the driver specific write and read
71 Step 7: Modify the driver's attach function
73 Change the driver attach function prototype :
74 {driver_name}_attach(struct i2c_device *device) --> {driver_name}_attach(struct
75 i2c_adapter *adap, int addr , unsigned short flags, int kind)
77 Create a i2c_client client...
78 Add the following (where "decoder" is a reference to a struct for the driver
81 struct i2c_client *client;
82 client = kmalloc(sizeof(*client), GFP_KERNEL);
85 client_template.adapter = adap;
86 client_template.addr = addr;
87 memcpy(client, &client_template, sizeof(*client));
88 strcpy(client->name , "{driver_name}");
89 decoder->client = client;
90 client->data = decoder;
93 Towards the end of the function, add:
95 init_MUTEX(&decoder->lock);
96 i2c_attach_client(client);
99 Step 8: Modify the driver's detach function
101 Change the driver detach function prototype :
102 {driver_name}_detach(struct i2c_device *device) --> {driver_name}_detach(struct
105 In the beginning of the detach function, add:
106 i2c_detach_client(client);
108 Towards the end of the detach function, add:
112 Step 9: Modify the driver's command function
114 Change the driver command function prototype :
116 Step 10: Add the probe function after the driver's attach function.
118 Add the following code:
120 static int {driver_name}_probe(struct i2c_adapter *adap)
122 return i2c_probe(adap, &addr_data, {driver_name}_attach);
126 Step 11: Modify the driver's i2c_driver
128 Find the i2c_driver , such as
129 static struct i2c_driver i2c_driver_saa7110
130 It is usually located towards the end of the driver
131 Replace the values from I2C_DRIVERID_{something} to {driver_name}_attach, and
133 I2C_DRIVERID_{driver_name} , // verify by looking in include/linux/i2c-id.h
138 Step 12: Adding the i2c_client
140 Add the i2c_client to the driver. Add the following code:
142 static struct i2c_client client_template = {
143 "{driver_name}_client",
148 {i2c_driver reference}
151 Step 13: Registering and Unregistering
153 Replace i2c_register_driver with i2c_add_driver
154 Replace i2c_unregister_driver with i2c_del_driver
156 -------------------------------------------------------
160 The following patch provides the i2c coversion patch for the saa7110 driver
161 based on the above guide (for clarity).
164 --- drivers/media/video/saa7110.c.old Fri Jun 28 10:22:52 2002
165 +++ drivers/media/video/saa7110.c Thu Jul 4 16:51:08 2002
168 #include <asm/uaccess.h>
170 -#include <linux/i2c-old.h>
171 +#include <linux/i2c.h>
172 #include <linux/videodev.h>
173 #include "linux/video_decoder.h"
177 #define I2C_SAA7110 0x9C /* or 0x9E */
179 +#define IF_NAME "saa7110"
180 #define I2C_DELAY 10 /* 10 us or 100khz */
182 +static unsigned short normal_i2c[] = {34>>1, I2C_CLIENT_END };
183 +static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
184 +static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
185 +static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
186 +static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
187 +static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
188 +static unsigned short force[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
190 +static struct i2c_client_address_data addr_data = {
191 + normal_i2c, normal_i2c_range,
192 + probe, probe_range,
193 + ignore, ignore_range,
197 +static struct i2c_client client_template;
200 - struct i2c_bus *bus;
201 + struct i2c_client *client;
203 unsigned char reg[36];
205 + struct semaphore lock;
212 /* ----------------------------------------------------------------------- */
213 -/* I2C support functions */
214 -/* ----------------------------------------------------------------------- */
216 -int saa7110_write(struct saa7110 *decoder, unsigned char subaddr, unsigned char data)
220 - LOCK_I2C_BUS(decoder->bus);
221 - i2c_start(decoder->bus);
222 - i2c_sendbyte(decoder->bus, decoder->addr, I2C_DELAY);
223 - i2c_sendbyte(decoder->bus, subaddr, I2C_DELAY);
224 - ack = i2c_sendbyte(decoder->bus, data, I2C_DELAY);
225 - i2c_stop(decoder->bus);
226 - decoder->reg[subaddr] = data;
227 - UNLOCK_I2C_BUS(decoder->bus);
232 -int saa7110_write_block(struct saa7110* decoder, unsigned const char *data, unsigned int len)
234 - unsigned subaddr = *data;
236 - LOCK_I2C_BUS(decoder->bus);
237 - i2c_start(decoder->bus);
238 - i2c_sendbyte(decoder->bus,decoder->addr,I2C_DELAY);
239 - while (len-- > 0) {
240 - if (i2c_sendbyte(decoder->bus,*data,0)) {
241 - i2c_stop(decoder->bus);
242 - UNLOCK_I2C_BUS(decoder->bus);
245 - decoder->reg[subaddr++] = *data++;
247 - i2c_stop(decoder->bus);
248 - UNLOCK_I2C_BUS(decoder->bus);
254 -int saa7110_read(struct saa7110* decoder)
258 - LOCK_I2C_BUS(decoder->bus);
259 - i2c_start(decoder->bus);
260 - i2c_sendbyte(decoder->bus, decoder->addr, I2C_DELAY);
261 - i2c_start(decoder->bus);
262 - i2c_sendbyte(decoder->bus, decoder->addr | 1, I2C_DELAY);
263 - data = i2c_readbyte(decoder->bus, 1);
264 - i2c_stop(decoder->bus);
265 - UNLOCK_I2C_BUS(decoder->bus);
269 -/* ----------------------------------------------------------------------- */
270 /* SAA7110 functions */
271 /* ----------------------------------------------------------------------- */
273 -int saa7110_selmux(struct i2c_device *device, int chan)
274 +int saa7110_selmux(struct i2c_client *client, int chan)
276 static const unsigned char modes[9][8] = {
277 /* mode 0 */ { 0x00, 0xD9, 0x17, 0x40, 0x03, 0x44, 0x75, 0x16 },
279 /* mode 6 */ { 0x80, 0x59, 0x17, 0x42, 0xA3, 0x44, 0x75, 0x12 },
280 /* mode 7 */ { 0x80, 0x9A, 0x17, 0xB1, 0x13, 0x60, 0xB5, 0x14 },
281 /* mode 8 */ { 0x80, 0x3C, 0x27, 0xC1, 0x23, 0x44, 0x75, 0x21 } };
282 - struct saa7110* decoder = device->data;
283 const unsigned char* ptr = modes[chan];
285 - saa7110_write(decoder,0x06,ptr[0]); /* Luminance control */
286 - saa7110_write(decoder,0x20,ptr[1]); /* Analog Control #1 */
287 - saa7110_write(decoder,0x21,ptr[2]); /* Analog Control #2 */
288 - saa7110_write(decoder,0x22,ptr[3]); /* Mixer Control #1 */
289 - saa7110_write(decoder,0x2C,ptr[4]); /* Mixer Control #2 */
290 - saa7110_write(decoder,0x30,ptr[5]); /* ADCs gain control */
291 - saa7110_write(decoder,0x31,ptr[6]); /* Mixer Control #3 */
292 - saa7110_write(decoder,0x21,ptr[7]); /* Analog Control #2 */
293 + i2c_smbus_write_byte_data(client,0x06,ptr[0]); /* Luminance control */
294 + i2c_smbus_write_byte_data(client,0x20,ptr[1]); /* Analog Control #1 */
295 + i2c_smbus_write_byte_data(client,0x21,ptr[2]); /* Analog Control #2 */
296 + i2c_smbus_write_byte_data(client,0x22,ptr[3]); /* Mixer Control #1 */
297 + i2c_smbus_write_byte_data(client,0x2C,ptr[4]); /* Mixer Control #2 */
298 + i2c_smbus_write_byte_data(client,0x30,ptr[5]); /* ADCs gain control */
299 + i2c_smbus_write_byte_data(client,0x31,ptr[6]); /* Mixer Control #3 */
300 + i2c_smbus_write_byte_data(client,0x21,ptr[7]); /* Analog Control #2 */
306 -int determine_norm(struct i2c_device* dev)
307 +int determine_norm(struct i2c_client* client)
309 - struct saa7110* decoder = dev->data;
312 /* mode changed, start automatic detection */
313 - status = saa7110_read(decoder);
314 + status = i2c_smbus_read_byte(client);
315 if ((status & 3) == 0) {
316 - saa7110_write(decoder,0x06,0x80);
317 + i2c_smbus_write_byte_data(client,0x06,0x80);
319 - DEBUG(printk(KERN_INFO "%s: norm=bw60\n",dev->name));
320 - saa7110_write(decoder,0x2E,0x81);
321 + DEBUG(printk(KERN_INFO "%s: norm=bw60\n",adp->name));
322 + i2c_smbus_write_byte_data(client,0x2E,0x81);
323 return VIDEO_MODE_NTSC;
325 - DEBUG(printk(KERN_INFO "%s: norm=bw50\n",dev->name));
326 - saa7110_write(decoder,0x2E,0x9A);
327 + DEBUG(printk(KERN_INFO "%s: norm=bw50\n",adp->name));
328 + i2c_smbus_write_byte_data(client,0x2E,0x9A);
329 return VIDEO_MODE_PAL;
332 - saa7110_write(decoder,0x06,0x00);
333 + i2c_smbus_write_byte_data(client,0x06,0x00);
334 if (status & 0x20) { /* 60Hz */
335 - DEBUG(printk(KERN_INFO "%s: norm=ntsc\n",dev->name));
336 - saa7110_write(decoder,0x0D,0x06);
337 - saa7110_write(decoder,0x11,0x2C);
338 - saa7110_write(decoder,0x2E,0x81);
339 + DEBUG(printk(KERN_INFO "%s: norm=ntsc\n",adp->name));
340 + i2c_smbus_write_byte_data(client,0x0D,0x06);
341 + i2c_smbus_write_byte_data(client,0x11,0x2C);
342 + i2c_smbus_write_byte_data(client,0x2E,0x81);
343 return VIDEO_MODE_NTSC;
346 /* 50Hz -> PAL/SECAM */
347 - saa7110_write(decoder,0x0D,0x06);
348 - saa7110_write(decoder,0x11,0x59);
349 - saa7110_write(decoder,0x2E,0x9A);
350 + i2c_smbus_write_byte_data(client,0x0D,0x06);
351 + i2c_smbus_write_byte_data(client,0x11,0x59);
352 + i2c_smbus_write_byte_data(client,0x2E,0x9A);
354 mdelay(150); /* pause 150 ms */
356 - status = saa7110_read(decoder);
357 + status = i2c_smbus_read_byte(client);
358 if ((status & 0x03) == 0x01) {
359 DEBUG(printk(KERN_INFO "%s: norm=secam\n",dev->name));
360 - saa7110_write(decoder,0x0D,0x07);
361 + i2c_smbus_write_byte_data(client,0x0D,0x07);
362 return VIDEO_MODE_SECAM;
364 DEBUG(printk(KERN_INFO "%s: norm=pal\n",dev->name));
369 -int saa7110_attach(struct i2c_device *device)
370 +int saa7110_attach(struct i2c_adapter *adap, int addr, unsigned short flags, int kind)
372 static const unsigned char initseq[] = {
373 0, 0x4C, 0x3C, 0x0D, 0xEF, 0xBD, 0xF0, 0x00, 0x00,
374 @@ -198,20 +157,28 @@
375 0xD9, 0x17, 0x40, 0x41, 0x80, 0x41, 0x80, 0x4F,
376 0xFE, 0x01, 0xCF, 0x0F, 0x03, 0x01, 0x81, 0x03,
377 0x40, 0x75, 0x01, 0x8C, 0x03};
378 - struct saa7110* decoder;
379 + struct saa7110 *decoder;
380 + struct i2c_client *client;
383 - device->data = decoder = kmalloc(sizeof(struct saa7110), GFP_KERNEL);
384 - if (device->data == 0)
385 + client=kmalloc(sizeof(*client), GFP_KERNEL);
389 + client_template.adapter = adap;
390 + client_template.addr = addr;
391 + memcpy(client, &client_template, sizeof(*client));
393 + decoder = kmalloc(sizeof(*decoder), GFP_KERNEL);
394 + if (decoder == NULL) {
399 /* clear our private data */
400 - memset(decoder, 0, sizeof(struct saa7110));
401 - strcpy(device->name, "saa7110");
402 - decoder->bus = device->bus;
403 - decoder->addr = device->addr;
404 + memset(decoder, 0, sizeof(*decoder));
405 + strcpy(client->name, IF_NAME);
406 + decoder->client = client;
407 + client->data = decoder;
408 + decoder->addr = addr;
409 decoder->norm = VIDEO_MODE_PAL;
412 @@ -220,40 +187,52 @@
413 decoder->hue = 32768;
414 decoder->sat = 32768;
416 - rv = saa7110_write_block(decoder, initseq, sizeof(initseq));
417 + rv = i2c_master_send(client, initseq, sizeof(initseq));
419 - printk(KERN_ERR "%s_attach: init status %d\n", device->name, rv);
420 + printk(KERN_ERR "%s_attach: init status %d\n", client->name, rv);
422 - saa7110_write(decoder,0x21,0x16);
423 - saa7110_write(decoder,0x0D,0x04);
424 - DEBUG(printk(KERN_INFO "%s_attach: chip version %x\n", device->name, saa7110_read(decoder)));
425 - saa7110_write(decoder,0x0D,0x06);
426 + i2c_smbus_write_byte_data(client,0x21,0x16);
427 + i2c_smbus_write_byte_data(client,0x0D,0x04);
428 + DEBUG(printk(KERN_INFO "%s_attach: chip version %x\n", client->name, i2c_smbus_read_byte(client)));
429 + i2c_smbus_write_byte_data(client,0x0D,0x06);
432 + init_MUTEX(&decoder->lock);
433 + i2c_attach_client(client);
434 /* setup and implicit mode 0 select has been performed */
439 +int saa7110_probe(struct i2c_adapter *adap)
441 + return i2c_probe(adap, &addr_data, saa7110_attach);
445 -int saa7110_detach(struct i2c_device *device)
446 +int saa7110_detach(struct i2c_client *client)
448 - struct saa7110* decoder = device->data;
449 + struct saa7110* decoder = client->data;
451 - DEBUG(printk(KERN_INFO "%s_detach\n",device->name));
452 + i2c_detach_client(client);
454 + DEBUG(printk(KERN_INFO "%s_detach\n",client->name));
456 /* stop further output */
457 - saa7110_write(decoder,0x0E,0x00);
458 + i2c_smbus_write_byte_data(client,0x0E,0x00);
460 - kfree(device->data);
468 -int saa7110_command(struct i2c_device *device, unsigned int cmd, void *arg)
469 +int saa7110_command(struct i2c_client *client, unsigned int cmd, void *arg)
471 - struct saa7110* decoder = device->data;
472 + struct saa7110* decoder = client->data;
476 @@ -272,11 +251,11 @@
478 case DECODER_GET_STATUS:
480 - struct saa7110* decoder = device->data;
481 + struct saa7110* decoder = client->data;
485 - status = i2c_read(device->bus,device->addr|1);
486 + status = i2c_smbus_read_byte(client);
488 res |= DECODER_STATUS_GOOD;
490 @@ -301,26 +280,26 @@
492 if (decoder->norm != v) {
494 - saa7110_write(decoder, 0x06, 0x00);
495 + i2c_smbus_write_byte_data(client, 0x06, 0x00);
497 case VIDEO_MODE_NTSC:
498 - saa7110_write(decoder, 0x0D, 0x06);
499 - saa7110_write(decoder, 0x11, 0x2C);
500 - saa7110_write(decoder, 0x30, 0x81);
501 - saa7110_write(decoder, 0x2A, 0xDF);
502 + i2c_smbus_write_byte_data(client, 0x0D, 0x06);
503 + i2c_smbus_write_byte_data(client, 0x11, 0x2C);
504 + i2c_smbus_write_byte_data(client, 0x30, 0x81);
505 + i2c_smbus_write_byte_data(client, 0x2A, 0xDF);
508 - saa7110_write(decoder, 0x0D, 0x06);
509 - saa7110_write(decoder, 0x11, 0x59);
510 - saa7110_write(decoder, 0x2E, 0x9A);
511 + i2c_smbus_write_byte_data(client, 0x0D, 0x06);
512 + i2c_smbus_write_byte_data(client, 0x11, 0x59);
513 + i2c_smbus_write_byte_data(client, 0x2E, 0x9A);
515 case VIDEO_MODE_SECAM:
516 - saa7110_write(decoder, 0x0D, 0x07);
517 - saa7110_write(decoder, 0x11, 0x59);
518 - saa7110_write(decoder, 0x2E, 0x9A);
519 + i2c_smbus_write_byte_data(client, 0x0D, 0x07);
520 + i2c_smbus_write_byte_data(client, 0x11, 0x59);
521 + i2c_smbus_write_byte_data(client, 0x2E, 0x9A);
523 case VIDEO_MODE_AUTO:
524 - *(int*)arg = determine_norm(device);
525 + *(int*)arg = determine_norm(client);
531 if (decoder->input != v) {
533 - saa7110_selmux(device, v);
534 + saa7110_selmux(client, v);
540 if (decoder->enable != v) {
542 - saa7110_write(decoder,0x0E, v ? 0x18 : 0x00);
543 + i2c_smbus_write_byte_data(client,0x0E, v ? 0x18 : 0x00);
547 @@ -360,22 +339,22 @@
548 if (decoder->bright != pic->brightness) {
549 /* We want 0 to 255 we get 0-65535 */
550 decoder->bright = pic->brightness;
551 - saa7110_write(decoder, 0x19, decoder->bright >> 8);
552 + i2c_smbus_write_byte_data(client, 0x19, decoder->bright >> 8);
554 if (decoder->contrast != pic->contrast) {
555 /* We want 0 to 127 we get 0-65535 */
556 decoder->contrast = pic->contrast;
557 - saa7110_write(decoder, 0x13, decoder->contrast >> 9);
558 + i2c_smbus_write_byte_data(client, 0x13, decoder->contrast >> 9);
560 if (decoder->sat != pic->colour) {
561 /* We want 0 to 127 we get 0-65535 */
562 decoder->sat = pic->colour;
563 - saa7110_write(decoder, 0x12, decoder->sat >> 9);
564 + i2c_smbus_write_byte_data(client, 0x12, decoder->sat >> 9);
566 if (decoder->hue != pic->hue) {
567 /* We want -128 to 127 we get 0-65535 */
568 decoder->hue = pic->hue;
569 - saa7110_write(decoder, 0x07, (decoder->hue>>8)-128);
570 + i2c_smbus_write_byte_data(client, 0x07, (decoder->hue>>8)-128);
576 for (v=0; v<34; v+=16) {
578 - DEBUG(printk(KERN_INFO "%s: %03x\n",device->name,v));
579 + DEBUG(printk(KERN_INFO "%s: %03x\n",client->name,v));
580 for (j=0; j<16; j++) {
581 DEBUG(printk(KERN_INFO " %02x",decoder->reg[v+j]));
583 @@ -402,24 +381,30 @@
585 static struct i2c_driver i2c_driver_saa7110 =
587 - "saa7110", /* name */
589 - I2C_DRIVERID_VIDEODECODER, /* in i2c.h */
590 - I2C_SAA7110, I2C_SAA7110+1, /* Addr range */
595 + .owner = THIS_MODULE,
597 + .id = I2C_DRIVERID_SAA7110,
598 + .flags = I2C_DF_NOTIFY,
599 + .attach_adapter = saa7110_probe,
600 + .detach_adapter = saa7110_detach,
601 + .command = saa7110_command,
603 +static struct i2c_client client_template = {
609 + &i2c_driver_saa7110
612 static int saa7110_init(void)
614 - return i2c_register_driver(&i2c_driver_saa7110);
615 + return i2c_add_driver(&i2c_driver_saa7110);
618 static void saa7110_exit(void)
620 - i2c_unregister_driver(&i2c_driver_saa7110);
621 + i2c_del_driver(&i2c_driver_saa7110);