Need Help with I2C Linux Device Drivers

Hi,

        I have a custom board built with ADV7403 from analog devices.
ADV7403 is connected as client to a Beagleboard-xM Rev.C on which linux
Angstrom is ported with the kernel version 2.6.32.

Im trying to write a device driver for ADV7403 for RGB input signal. In
order to configure ADV7403, i2c communication is used.

So far in the linux device drivers i have been able to include support for
module_init and module_exit. and when i insert my module(i.e., .ko file)
module_init is triggered. (this is done by using ' insmod adv7403.ko '
command)

According to my knowledge, after module_init next function called is
Probe(). but i dont see the probe() function being called and executed in
the run time.. reason for this may be adv7403 hardware is not getting
detected on the i2c line which triggers the probe() function.

one of the straight reason for this could be the adv7403's i2c slave
address. the slave address of adv7403 is 0x21. but i dont know how to and
where to give the i2c slave address in the linux device driver structure.
Any suggestions or hint in this matter would be helpful.

Im new to writing linux device drivers and i might have missed out some
important and simple things due to my insufficient knowledge on linux
device drivers. If anything of this sort is found, please point it out.

I have pasted the code that is written so far below..

#include <linux/module.h>

#include <linux/init.h>

#include <linux/errno.h>

#include <linux/kernel.h>

#include <linux/interrupt.h>

#include <linux/i2c.h>

#include <linux/i2c-id.h>

#include <linux/videodev2.h>

#include <linux/mutex.h>

#include <linux/slab.h>

#include <linux/log2.h>

#include <media/v4l2-ioctl.h>

#include <media/v4l2-device.h>

#include <media/v4l2-chip-ident.h>

#include <media/v4l2-subdev.h>

#include <media/soc_camera.h>

#include "adv7403_regs.h"

#define DRIVER_NAME "adv7403"

struct adv7403_state {

          struct v4l2_subdev subdev;

};

static __devinit int adv7403_probe(struct i2c_client *client,

                              const struct i2c_device_id *id)

{

          struct adv7403_state *state;

          int ret;

          /* Check if the adapter supports the needed features */

          if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_BYTE_DATA))

                    return -EIO;

          v4l_info(client, "chip found @ 0x%02x (%s)\n",

                              client->addr << 1, client->adapter->name);

          state = kzalloc(sizeof(struct adv7403_state), GFP_KERNEL);

          if (state == NULL) {

                    ret = -ENOMEM;

                    goto err;

          }

        else{

                    printk(KERN_ERR DRIVER_NAME ": Detected %d\n");

          }

err:

          printk(KERN_ERR DRIVER_NAME ": Failed to probe: %d\n", ret);

          return ret;

}

static __devexit int adv7403_remove(struct i2c_client *client)

{

          struct v4l2_subdev *sd = i2c_get_clientdata(client);

          v4l2_device_unregister_subdev(sd);

          return 0;

}

static const struct i2c_device_id adv7403_id[] = {

          {DRIVER_NAME, 0},

          {},

};

MODULE_DEVICE_TABLE(i2c, adv7403_id);

static struct i2c_driver adv7403_driver = {

          .driver = {

                    .owner = THIS_MODULE,

                    .name = DRIVER_NAME,

          },

        .probe = adv7403_probe,

        .remove = adv7403_remove,

          .id_table = adv7403_id

};

static int __init adv7403_mod_init(void)

{

          printk(" ADV7403 Video Decoder Device Driver inserted to kernel
\n");

          return i2c_add_driver(&adv7403_driver);

}

static void __exit adv7403_mod_exit(void)

{

        printk(" ADV7403 Video Decoder Device Driver removed from kernel
\n");

          i2c_del_driver(&adv7403_driver);

}

module_init(adv7403_mod_init);

module_exit(adv7403_mod_exit);

MODULE_DESCRIPTION("Analog Devices ADV7403 video driver");

thanking you,

Shravan Kulkarni

P.S :

My system configuration:

Processor: intel core 2 duo 2.4 GHz

Ram : 2GB

O.S : Ubuntu 10.04 (kernel: 2.6.32-39)

BeagleBoard-xM Rev.C configuration( which host to ADV7403)

Processor : DM3730 1GHz

Ram: 512MB

O.S : Linux Angstrom ( kernel 2.6.32 )

   - 0 Views
   - Tags: none (add <http://ez.analog.com/thread/14389#>)

   - **

Here’s a good article that shows an example of an i2c slave device driver.

http://www.embedded-bits.co.uk/2009/i2c-in-the-2632-linux-kernel/

They suggest just instantiating the device in the board description with a name and your I2C slave address. This is very simple but might not suit your needs. Fortunately, that same article references this article regarding different ways of having the kernel detect the I2C device:

http://lxr.linux.no/#linux+v2.6.31/Documentation/i2c/instantiating-devices

Good luck!

Hi Dave,
Thank you for your reply. But apologies to bother you again. I went through the link which you gave. from the 2nd link i.e., http://lxr.linux.no/linux+v2.6.31/Documentation/i2c/instantiating-devices im adding i2c_board_info structure to my drivers to detect the adv7403.

but when i include this into my driver and compile im getting the following errors.

code included:-

static struct i2c_board_info __initdata board_i2c_board_info[] = {
{
I2C_BOARD_INFO(DRIVER_NAME, 0x21),
},
};

(…)
int i2c_register_board_info(2,
board_i2c_board_info, ARRAY_SIZE(board_i2c_board_info));
(…)

error generated:-

drivers/media/video/adv7403.c:75: error: expected identifier or ‘(’ before ‘…’ token
drivers/media/video/adv7403.c:77: error: expected identifier or ‘(’ before ‘)’ token
drivers/media/video/adv7403.c:78: error: expected identifier or ‘(’ before ‘…’ token
drivers/media/video/adv7403.c:99: error: ‘adv7403_id’ undeclared here (not in a function)
make[4]: *** [drivers/media/video/adv7403.o] Error 1
make[3]: *** [drivers/media/video] Error 2
make[3]: *** Waiting for unfinished jobs…
make[2]: *** [drivers/media] Error 2
make[2]: *** Waiting for unfinished jobs…
make[1]: *** [drivers] Error 2
make[1]: *** Waiting for unfinished jobs…

now if i look at the errors it says it requires ’ … ’ before and after i2c_register_board_info()
i have included the ’ … ’ before and after i2c_register_board_info. but still this error is getting generated…
and one more strange thing is that there was no error related to adv7403_id before but now it says there is some error with respect to adv7403_id also…
Im not able to figure out what might be the reason for this behavior.

regards,
Shravan Kulkarni

Hi,

I'm controling I2C with python, so i may not be able to advice about
your question.
I'm sorry....;-(

But, I'm so interested in your project.
When can i buy your product ADV7403 RGB capture cape?

I just finished reading datasheet of ADV7403, it is cool chip.
Could you tell me how to use it?
Connect RGB and HV to ADV7403, supply power, command via I2C,
then, it will output pixeldata???

regards,
Koutarou Furukawa

I’m not sure that you are putting this code in the right place. The way I read that documentation is that this code needs to go in a board definition file. I have done something similar on another project. You either need to modify an existing board definition or add a new board folder and update the Kconfig/Makefile system. (The second one is the more proper way and is a good skill to learn if you are going write drivers.

Here’s the source code for the sfe4001 example the documentation references:

http://lxr.free-electrons.com/source/drivers/net/sfc/sfe4001.c?v=2.6.28

And here is a platform definition file that defines some i2c devices using i2c_register_board_info().

http://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/arch/arm/mach-omap2/board-h4.c#L365

Notice that this is not a driver file! This is in the arch/arm tree where different platforms are defined.

Also, it looks like you are developing your driver with the source code right in the kernel tree. You might look around for a web page that describes how to develop “out of tree.”

Dave …

If you look at that one, there is no i2c_register_board info.
Keep banging on it.

Dave …

Hi Dave,
             Thank you for your reply. But apologies to bother you again.
I went through the link which you gave. from the 2nd link i.e.,
LXR linux/Documentation/i2c/instantiating-devices im
adding i2c_board_info structure to my drivers to detect the adv7403.

but when i include this into my driver and compile im getting the
following errors.

code included:-
static struct i2c_board_info __initdata board_i2c_board_info = {
           {
I2C_BOARD_INFO(DRIVER_NAME, 0x21),
           },
};

(...)
int i2c_register_board_info(2,
board_i2c_board_info, ARRAY_SIZE(board_i2c_board_info));
(...)

error generated:-
drivers/media/video/adv7403.c:75: error: expected identifier or '('
before '...' token
drivers/media/video/adv7403.c:77: error: expected identifier or '('
before ')' token
drivers/media/video/adv7403.c:78: error: expected identifier or '('
before '...' token
drivers/media/video/adv7403.c:99: error: 'adv7403_id' undeclared here
(not in a function)
make[4]: *** [drivers/media/video/adv7403.o] Error 1
make[3]: *** [drivers/media/video] Error 2
make[3]: *** Waiting for unfinished jobs....
make[2]: *** [drivers/media] Error 2
make[2]: *** Waiting for unfinished jobs....
make[1]: *** [drivers] Error 2
make[1]: *** Waiting for unfinished jobs....

now if i look at the errors it says it requires ' ... ' before and after
i2c_register_board_info()
i have included the ' ... ' before and after i2c_register_board_info. but
still this error is getting generated...
and one more strange thing is that there was no error related to
adv7403_id before but now it says there is some error with respect to
adv7403_id also....
Im not able to figure out what might be the reason for this behavior.
Shravan,

I'm not sure that you are putting this code in the right place. The way
I read that documentation is that this code needs to go in a board
definition file. I have done something similar on another project. You
either need to modify an existing board definition or add a new board
folder and update the Kconfig/Makefile system. (The second one is the more
proper way and is a good skill to learn if you are going write drivers.

Here's the source code for the sfe4001 example the documentation
references:

http://lxr.free-electrons.com/source/drivers/net/sfc/sfe4001.c?v=2.6.28

If you look at that one, there is no i2c_register_board info.

And here is a platform definition file that defines some i2c devices using

Hi Dave,
Thank you for the link and tips… Il go through the link and try to implement that for my scenario. Il post an update on the outcome.

regards,
Shravan Kulkarni

Hi Dave,
Thank you for the link and tips… Il go through the link and try to implement that for my scenario. Il post an update on the outcome.

regards,
Shravan Kulkarni

Sounds good. Looks like I am going to be doing something very similar with an SPI-based LCD.

Hi Dave,
Sorry for the delay and i was working on the suggestion you gave… like you mentioned i looked into the /arch/arm/mach-omap2/board-omap3beagle.c and board-omap3beagle-camera.c and the lines which you gave viz…

static struct i2c_board_info __initdata adv7403_info[] = {
{
I2C_BOARD_INFO(“adv7403”, 0x21),
},
};

these lines were added in board-omap3beagle.c

following lines were added in the same file around 780 line no. in the function

file:- board-omap3beagle.c

function:-
static int __init omap3_beagle_i2c_init(void) // around 780 line.no in the file

lines added to above function:

} else if (!strcmp(cameraboard_name, “adv7403”)){
printk(KERN_INFO “Beagle cameraboard:”
" regisetering i2c2 bus for adv7403\n");
omap_register_i2c_bus(2,400, adv7403_info,
ARRAY_SIZE(adv7403_info));

there is a nested if-else tree and the above lines were integrated to that… still probe function was not triggered…

But there was a new finding for me… its in arch/arm/configs/ in this path there are few files related to beagleboard…
They are
omap3_beagle_angstrom_defconfig,
omap3_beagle_cam_defconfig and
omap3_beagle_defconfig…

In these files modules were listed and some of them were enabled and some of them were commented so that they can be enabled if needed… But the info given at the top of the file is as follows…