1. 最上层的数据结构 v4l2_i2c_data,V4L2设备mt9e013的i2c数据表示:
a. struct v4l2_subdev
b. struct media_pad
struct media_entity
c. struct v4l2_mbus_framfmt
d. struct camera_sensor_platform_data
4. v4l2_i2c_subdev_init(),这里执行了2个动作,一个是设置V4L2子设备数据,一个是设置I2C client数据
5. mt9e013_ops
a. mt9e013_core_ops :
V4L2 IOCTL 传下来的具体执行函数
b. mt9e013_video_ops : v4l2 接口传下来的视频相关的操作
c. mt9e013_pad_ops :
media 帧设置方面的操作
6. mt9e013_entity_ops
media_entity_operations 原型定义:
7. media_entity_init
struct media_link
8. mt9e013_remove
1. static struct v4l2_i2c_driver_data v4l2_i2c_data = {
2. .name = MT9E013_NAME,
3. .probe = mt9e013_probe,
4. .remove = mt9e013_remove,
5. .id_table = mt9e013_id,
6. };
v4l2_i2c_driver_data 原型定义: 1. struct v4l2_i2c_driver_data {
2. const char * const name;
3. int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);
4. int (*probe)(struct i2c_client *client, const struct i2c_device_id *id);
5. int (*remove)(struct i2c_client *client);
6. int (*suspend)(struct i2c_client *client, pm_message_t state);
7. int (*resume)(struct i2c_client *client);
8. const struct i2c_device_id *id_table;
9. };
2. mt9e013_probe()
1. static int mt9e013_probe(struct i2c_client *client,
2. const struct i2c_device_id *id)
3. {
4. struct mt9e013_device *dev; //mt9e013_device 是最上层的模型,里面包含了很多数据结构,后面介绍
5. int ret;
6. _dev_info(&client->dev, "mt9e013 probe\n");
7.
8. /* allocate sensor device & init sub device */
9. dev = kzalloc(sizeof(*dev), GFP_KERNEL); //分配dev内存,并置0
10. if (!dev) {
11. v4l2_err(client, "%s: out of memory\n", __func__);
12. return -ENOMEM;
13. }
14.
15. dev->fmt_idx = 0;
16. v4l2_i2c_subdev_init(&(dev->sd), client, &mt9e013_ops); //i2c v4l2子设备初始化 添加mt9e013_ops。
17.
18. dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; //this subdev needs a device node.
19. dev->pad.flags = MEDIA_PAD_FLAG_OUTPUT;
20. dev->sd.entity.ops = &mt9e013_entity_ops; //entity operation
21. dev->format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
22.
23. /* REVISIT: Do we need media controller? */
24. ret = media_entity_init(&dev->sd.entity, 1, &dev->pad, 0); //media entity init
25. if (ret) {
26. mt9e013_remove(client);
27. return ret;
28. }
29.
30. return 0;
31. }
3. mt9e013_device 相关数据结构:
a. struct v4l2_subdev
- /* Each instance of a subdev driver should create this struct, either
- stand-alone or embedded in a larger struct.
- */
- struct v4l2_subdev {
- #if defined(CONFIG_MEDIA_CONTROLLER)
- struct media_entity entity;
- #endif
- struct list_head list;
- struct module*owner;
- u32 flags;
- struct v4l2_device *v4l2_dev;
- const struct v4l2_subdev_ops*ops;
- /* The control handler of this subdev. May be NULL. */
- struct v4l2_ctrl_handler *ctrl_handler;
- /* name must be unique */
- char name[V4L2_SUBDEV_NAME_SIZE];
- /* can be used to group similar subdevs, value is driver-specific */
- u32 grp_id;
- /* pointer to private data */
- void *dev_priv;
- void *host_priv;
- /* subdev device node */
- struct video_device devnode;
- unsigned int initialized;
- /* number of events to be allocated on open */
- unsigned int nevents;
- };
- struct media_pad{
- struct media_entity *entity; /* Entity this pad belongs to */
- u16 index; /* Pad index in the entity pads array */
- unsigned long flags; /* Pad flags (MEDIA_PAD_FLAG_*) */
- };
- struct media_entity{
- struct list_head list;
- struct media_device *parent; /* Media device this entity belongs to*/
- u32 id; /* Entity ID, unique in the parent media
- * device context */
- const char*name; /* Entity name */
- u32 type; /* Entity type (MEDIA_ENTITY_TYPE_*) */
- u32 revision; /* Entity revision, driver specific */
- unsigned long flags; /* Entity flags (MEDIA_ENTITY_FLAG_*) */
- u32 group_id; /* Entity group ID */
- u16 num_pads; /* Number of input and output pads */
- u16 num_links; /* Number of existing links, both
- * enabled and disabled */
- u16 num_backlinks; /* Number of backlinks */
- u16 max_links; /* Maximum number of links */
- struct media_pad *pads; /* Pads array (num_pads elements) */
- struct media_link *links; /* Links array (max_links elements)*/
- const struct media_entity_operations *ops; /* Entity operations */ //这个比较重要
- int stream_count; /* Stream count for the entity. */
- int use_count; /* Use count for the entity. */
- struct media_pipeline *pipe; /* Pipeline this entity belongs to. */
- union {
- /* Node specifications */
- struct {
- u32 major;
- u32 minor;
- } v4l;
- struct {
- u32 major;
- u32 minor;
- } fb;
- struct {
- u32 card;
- u32 device;
- u32 subdevice;
- } alsa;
- int dvb;
- /* Sub-device specifications */
- /* Nothing needed yet */
- };
- };
- /**
- * struct v4l2_mbus_framefmt - frame format on the media bus
- * @width: frame width
- * @height: frame height
- * @code: data format code (from enum v4l2_mbus_pixelcode)
- * @field: used interlacing type (from enum v4l2_field)
- * @colorspace: colorspace of the data (from enum v4l2_colorspace)
- */
- struct v4l2_mbus_framefmt {
- __u32 width;
- __u32 height;
- __u32 code;
- __u32 field;
- __u32 colorspace;
- };
- struct camera_sensor_platform_data{
- int (*gpio_ctrl)(struct v4l2_subdev*subdev, int flag);
- int (*flisclk_ctrl)(struct v4l2_subdev*subdev, int flag);
- int (*power_ctrl)(struct v4l2_subdev*subdev, int flag);
- int (*csi_cfg)(struct v4l2_subdev*subdev, int flag);
- };
4. v4l2_i2c_subdev_init(),这里执行了2个动作,一个是设置V4L2子设备数据,一个是设置I2C client数据
- /* I2C Helper functions */
- void v4l2_i2c_subdev_init(struct v4l2_subdev*sd, struct i2c_client *client,
- const struct v4l2_subdev_ops *ops)
- {
- v4l2_subdev_init(sd, ops);
- sd->flags|= V4L2_SUBDEV_FL_IS_I2C;
- /* the owner is the same as the i2c_client's driver owner */
- sd->owner= client->driver->driver.owner;
- /* i2c_client and v4l2_subdev point to one another */
- v4l2_set_subdevdata(sd, client); //设置V4L2 子设备数据
- i2c_set_clientdata(client, sd); //设置I2C client 数据
- /* initialize name */
- snprintf(sd->name,sizeof(sd->name),"%s %d-%04x",
- client->driver->driver.name, i2c_adapter_id(client->adapter),
- client->addr);
- }
- EXPORT_SYMBOL_GPL(v4l2_i2c_subdev_init);
- static const struct v4l2_subdev_ops mt9e013_ops= { //v4l2_subdev operation, 表示vl42 子设备所具有的能力。
- .core =&mt9e013_core_ops,
- .video =&mt9e013_video_ops,
- .pad =&mt9e013_pad_ops,
- };
- static const struct v4l2_subdev_core_ops mt9e013_core_ops= {
- .g_chip_ident = mt9e013_g_chip_ident, //获得Id
- .s_config = mt9e013_s_config, //配置
- .queryctrl = mt9e013_queryctrl, //query control能力
- .g_ctrl = mt9e013_g_ctrl, //get control
- .s_ctrl = mt9e013_s_ctrl, //set control
- .s_power = mt9e013_s_power, //set power
- .ioctl = mt9e013_ioctl, //ioctl
- .init = mt9e013_init,
- };
- static const struct v4l2_subdev_video_ops mt9e013_video_ops= {
- .s_stream = mt9e013_s_stream, //set stream
- .enum_framesizes = mt9e013_enum_framesizes, //enum framesizes
- .enum_frameintervals = mt9e013_enum_frameintervals,
- .enum_mbus_fmt = mt9e013_enum_mbus_fmt,
- .try_mbus_fmt = mt9e013_try_mbus_fmt, // try format
- .g_mbus_fmt = mt9e013_g_mbus_fmt, // get format
- .s_mbus_fmt = mt9e013_s_mbus_fmt, //set format
- };
- /* REVISIT: Do we need pad operations? */
- static conststruct v4l2_subdev_pad_ops mt9e013_pad_ops = {
- .enum_mbus_code = mt9e013_enum_mbus_code,
- .enum_frame_size = mt9e013_enum_frame_size, // frame size
- .get_fmt = mt9e013_get_pad_format, // get format
- .set_fmt = mt9e013_set_pad_format, // set format
- };
6. mt9e013_entity_ops
- static const struct media_entity_operations mt9e013_entity_ops= {
- .set_power = v4l2_subdev_set_power, //设置v4l2子设备电源
- };
- struct media_entity_operations{
- int (*link_setup)(struct media_entity*entity,
- const struct media_pad *local,
- const struct media_pad *remote, u32 flags);
- int (*set_power)(struct media_entity*entity, int power);
- };
- /**
- * media_entity_init - Initialize a media entity
- *
- * @num_pads: Total number of input and output pads.
- * @extra_links: Initial estimate of the number of extra links.
- * @pads: Array of 'num_pads' pads.
- *
- * The total number of pads is an intrinsic property of entities known by the
- * entity driver, while the total number of links depends on hardware design
- * and is an extrinsic property unknown to the entity driver. However, in most
- * use cases the entity driver can guess the number of links which can safely
- * be assumed to be equal to or larger than the number of pads.
- *
- * For those reasons the links array can be preallocated based on the entity
- * driver guess and will be reallocated later if extra links need to be
- * created.
- *
- * This function allocates a links array with enough space to hold at least
- * 'num_pads' + 'extra_links' elements. The media_entity::max_links field will
- * be set to the number of allocated elements.
- *
- * The pads array is managed by the entity driver and passed to
- * media_entity_init() where its pointer will be stored in the entity structure.
- */
- int
- media_entity_init(struct media_entity*entity, u16 num_pads,
- struct media_pad *pads, u16 extra_links)
- {
- struct media_link *links;
- unsigned int max_links = num_pads + extra_links;
- unsigned int i;
- links = kzalloc(max_links* sizeof(links[0]), GFP_KERNEL);
- if (links== NULL)
- return -ENOMEM;
- entity->group_id= 0;
- entity->max_links= max_links;
- entity->num_links= 0;
- entity->num_backlinks= 0;
- entity->num_pads= num_pads;
- entity->pads= pads;
- entity->links= links;
- for (i= 0; i < num_pads; i++){
- pads[i].entity= entity;
- pads[i].index= i;
- }
- return 0;
- }
- EXPORT_SYMBOL_GPL(media_entity_init);
- struct media_link{
- struct media_pad *source; /* Source pad */
- struct media_pad *sink; /* Sink pad */
- struct media_link *reverse; /* Link in the reverse direction */
- unsigned long flags; /* Link flags (MEDIA_LINK_FLAG_*) */
- };
- static int mt9e013_remove(struct i2c_client*client)
- {
- struct v4l2_subdev *sd = i2c_get_clientdata(client); //先根据i2c client, 来获得v4l2 子设备。
- struct mt9e013_device *dev = to_mt9e013_sensor(sd); //通过container_of(v4l2_subdev),来获得包含它的 最上层mt9e013设备。
- dev->platform_data->csi_cfg(sd, 0);
- v4l2_device_unregister_subdev(sd); //注销v4l2子设备。
- kfree(dev);
- return 0;
- }
struct mt9e013_device
1. /* mt9e013 device structure */
2. struct mt9e013_device {
3. struct v4l2_subdev sd; //表示V4L2 子设备属性
4. struct media_pad pad;
5. struct v4l2_mbus_framefmt format;
6.
7. struct camera_sensor_platform_data *platform_data;
8. int fmt_idx;
9. int status;
10. u8 res;
11. u8 type;
12. u16 sensor_id;
13. u8 sensor_revision;
14.
15. unsigned int intg_factor;
16. };