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