This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

i2c problem for v4l2-subdev

Other Parts Discussed in Thread: TEST2

Hello,

I am working with a gumstix overo board connected with a e-con-systems camera module using a ov3640 camera sensor.

Along with the board I got a camera driver which can be used with linux kernel 2.6.34, but I want to use the camera along with the linux kernel 3.5.

So I tried to implement the driver into the kernel sources by referring to an existing driver (/driver/media/video/ov9640.c).

But the i2c_transfer fails. The older driver configured before the use of i2c some pins and set clock and so on, but I thought when I use the "v4l2-subdev-api" these things should be done automatically. Am I right?

Can some help me out?

Here is my codesnippet:

static int ov3640_reg_read(struct i2c_client *client, u16 reg, u8 *val)

{
    int ret;
    u8 data[2] = {0};

    struct i2c_msg msg = {

        .addr    = client->addr,
        .flags    = 0,
        .len    = 2,
        .buf    = data,
    };

    data[0] = (u8)(reg >> 8);
    data[1] = (u8)(reg & 0xff);

    ret = i2c_transfer(client->adapter, &msg, 1);

    if (ret < 0)
        goto err;

    msg.flags = I2C_M_RD;
    msg.len = 1;

    ret = i2c_transfer(client->adapter, &msg, 1);

    if (ret < 0)
        goto err;

    *val = data[0];

    return 0;
err:

    dev_err(&client->dev, "Failed reading register 0x%02x!\n", reg);

    return ret;

}

struct ov3640 {
    struct v4l2_subdev subdev;
    struct v4l2_subdev_sensor_interface_parms *plat_parms;
    struct v4l2_fract timeperframe;
    int i_size;
    int i_fmt;
    int ver;
    int fps;
};

static struct ov3640 *to_ov3640(const struct i2c_client *client)
{
    return container_of(i2c_get_clientdata(client), struct ov3640, subdev);
}

static int ov3640_detect(struct i2c_client *client)
{
    u8 pidh, pidl;

    if (!client)
        return -ENODEV;

    if (ov3640_reg_read(client, 0x300A, &pidh))
        return -ENODEV;

    if (ov3640_reg_read(client, 0x300B, &pidl))
        return -ENODEV;

    if ((pidh == 0x36) && ((pidl == 0x41) || (pidl == 0x4C)))
    {
        dev_info(&client->dev, "Detect success (%02X,%02X)\n", pidh, pidl);

        return pidl;
    }

    return -ENODEV;
}

static int ov3640_video_probe(struct soc_camera_device *icd, struct i2c_client *client)
{
    struct ov3640 *ov3640 = to_ov3640(client);

    int ver;

    ver = ov3640_detect(client);

    if (ver < 0)
    {
        dev_err(&client->dev, "Unable to detect sensor, err %d\n", ver);

        return ver;
    }

    ov3640->ver = ver;

    dev_dbg(&client->dev, "Chip version 0x%02x detected\n", ov3640->ver);

    return 0;
}

/* ----------------------------------------------------------------------- */

static const struct v4l2_queryctrl ov3640_controls[] = {};

static struct v4l2_subdev_core_ops ov3640_subdev_core_ops = {
    .g_chip_ident    = test2,
    .g_ctrl        = test2,
    .s_ctrl        = test2,
};

static struct v4l2_subdev_video_ops ov3640_subdev_video_ops = {
    .s_stream    = test2,
    .try_mbus_fmt    = test2,
    .s_mbus_fmt    = test2,
    .g_mbus_fmt    = test2,
    .enum_mbus_fmt    = test2,
    .enum_framesizes = test2,
    .enum_frameintervals = test2,
    .g_parm = test2,
    .s_parm = test2,
};

static struct v4l2_subdev_sensor_ops ov3640_subdev_sensor_ops = {
    .g_skip_frames    = test2,
};

static struct v4l2_subdev_ops ov3640_subdev_ops = {
    .core    = &ov3640_subdev_core_ops,
    .video    = &ov3640_subdev_video_ops,
    .sensor    = &ov3640_subdev_sensor_ops,
};

/* ----------------------------------------------------------------------- */



/************************************************************************************************************
 *  
 *  MODULE TYPE    :    FUNCTION                MODULE ID    :    
 *  Name    :    ov3640_probe
 *  Parameter1    :    struct i2c_client *client
 *  Parameter2    :    const struct i2c_device_id *id
 *  Returns    :    LINT32    - On sucess returns 0
 *                  - On Failure a negative number be returned
 *
 *  Description    :     Configure the gpio levels for ov3640 driver
 *  Comments    :      
 ************************************************************************************************************/
static INT32 ov3640_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
    cam_interface_pin_config *pin = NULL;
    struct ov3640 *ov3640;
    if(!client->dev.platform_data)
        printk("TOM OV3640 PROBE PLATFORM NULL ##########\n");
    struct soc_camera_device *icd = client->dev.platform_data;

    struct soc_camera_link *icl;

    int ret;

    if (!icd) {

        dev_err(&client->dev, "OV3640: missing soc-camera data!\n");

        return -EINVAL;
    }

    icl = soc_camera_i2c_to_link(client);

    if (!icl) {

        dev_err(&client->dev, "OV3640 driver needs platform data\n");

        return -EINVAL;
    }

    if (!icl->priv) {

        dev_err(&client->dev, "OV3640 driver needs i/f platform data\n");

        return -EINVAL;
    }

    ov3640 = kzalloc(sizeof(struct ov3640), GFP_KERNEL);

    if (!ov3640)
        return -ENOMEM;

    v4l2_i2c_subdev_init(&ov3640->subdev, client, &ov3640_subdev_ops);

    ov3640->i_fmt = 0; /* First format in the list */

    ov3640->timeperframe.numerator = 1;

    ov3640->timeperframe.denominator = 15;

    ov3640->plat_parms = icl->priv;

    if ((pin = kmalloc(sizeof(cam_interface_pin_config), GFP_KERNEL)) == NULL)
    {
        printk(KERN_ERR "Failed to allocate memory for pins\n");
    }
    
    all_clk_enable();

    init_omap_hwr(pin);

    ret = ov3640_video_probe(icd, client);

    if (ret) {

        kfree(ov3640);
    }

    return 0;
}

static const struct i2c_device_id ov3640_id[] = {
    { "ov3640", 0 },
    { }
};
MODULE_DEVICE_TABLE(i2c, ov3640_id);

static const unsigned short normal_i2c[] = {
    0x3C, 0xfffeU };

static struct i2c_driver ov3640_driver = {
    .class        = I2C_CLASS_HWMON,
    .driver = {
        .owner    = THIS_MODULE,
        .name    = "ov3640",
    },
    .probe        = ov3640_probe,
    .remove        = __exit_p(ov3640_remove),
    .id_table    = ov3640_id,
};

module_i2c_driver(ov3640_driver);

MODULE_DESCRIPTION("SoC Camera driver for Omni Vision 3640 sensor");
MODULE_AUTHOR("Test");
MODULE_LICENSE("GPL v2");

Regards, Tom