- 驱动初始化
在drivers/media/video/sp0a19.c中
device_initcall_sync(sp0a_mod_init);
static struct i2c_driver sp0a_i2c_driver = {
.driver = {
.name = SP0A_NAME_STRING(),
},
.probe = sp0a_probe,
.remove = sp0a_remove,
.id_table = sp0a_id,
};
static int __init sp0a_mod_init(void)
{
return i2c_add_driver(&sp0a_i2c_driver);
}
在probe函数中
static int sp0a_probe(struct i2c_client *client, const struct i2c_device_id *did)
{
struct sp0a *sp0a;
struct soc_camera_device *icd = client->dev.platform_data;
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
struct soc_camera_link *icl;
icl = to_soc_camera_link(icd);
sp0a = kzalloc(sizeof(struct sp0a), GFP_KERNEL);
v4l2_i2c_subdev_init(&sp0a->subdev, client, &sp0a_subdev_ops);
icd->ops = &sp0a_ops;
sp0a->info_priv.fmt = sp0a_colour_fmts[0];
sp0a_video_probe(icd, client);
return ret;
}
函数指针的注册过程
v4l2_i2c_subdev_init(&sp0a->subdev, client, &sp0a_subdev_ops);
static struct v4l2_subdev_core_ops sp0a_subdev_core_ops = {
.init = sp0a_init,
.g_ctrl = sp0a_g_control,
.s_ctrl = sp0a_s_control,
.g_ext_ctrls = sp0a_g_ext_controls,
.s_ext_ctrls = sp0a_s_ext_controls,
.g_chip_ident = sp0a_g_chip_ident,
.ioctl = sp0a_ioctl,
};
static struct v4l2_subdev_video_ops sp0a_subdev_video_ops = {
.s_mbus_fmt = sp0a_s_fmt,
.g_mbus_fmt = sp0a_g_fmt,
.try_mbus_fmt = sp0a_try_fmt,
.enum_mbus_fmt = sp0a_enum_fmt,
};
static struct v4l2_subdev_ops sp0a_subdev_ops = {
.core = &sp0a_subdev_core_ops,
.video = &sp0a_subdev_video_ops,
};
icd->ops = &sp0a_ops;
static struct soc_camera_ops sp0a_ops =
{
.suspend = sp0a_suspend,
.resume = sp0a_resume,
.set_bus_param = sp0a_set_bus_param,
.query_bus_param = sp0a_query_bus_param,
.controls = sp0a_controls,
.menus = sp0a_menus,
.num_controls = ARRAY_SIZE(sp0a_controls),
.num_menus = ARRAY_SIZE(sp0a_menus),
};
static int sp0a_video_probe(struct soc_camera_device *icd, struct i2c_client *client)
{
char pid = 0;
int ret;
struct sp0a *sp0a = to_sp0a(client);
if ( g_bIsAtvStart )
{
return 0;
}
//.add power.sheng 2012.09.04
/* We must have a parent by now. And it cannot be a wrong one.
* So this entire test is completely redundant. */
if (!icd->dev.parent ||
to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
return -ENODEV;
if (sp0a_ioctrl(icd, Sensor_PowerDown, 0) < 0) {
ret = -ENODEV;
goto sp0a_video_probe_err;
}
/* soft reset */
/* ret = sp0a_write(client, 0x12, 0x80);
if (ret != 0)
{
SP0A_TR(“soft reset %s failed\n”,SP0A_NAME_STRING());
return -ENODEV;
}
mdelay(50); *///delay 5 microseconds
/* check if it is an sp0a sp0a */
ret = sp0a_read(client, 0x02, &pid);
if (ret != 0) {
SP0A_TR("%s read chip id high byte failed\n",SP0A_NAME_STRING());
ret = -ENODEV;
goto sp0a_video_probe_err;
}
SP0A_DG("\n %s pid = 0x%x\n", SP0A_NAME_STRING(), pid);
if (pid == SP0A_ID) {
sp0a->model = SP0A_V4L2_IDENT;
} else {
SP0A_TR("error: %s mismatched pid = 0x%x\n", SP0A_NAME_STRING(), pid);
ret = -ENODEV;
goto sp0a_video_probe_err;
}
return 0;
sp0a_video_probe_err:
return ret;
}