主要做一些笔记,不对的地方请批评指正。
对芯片驱动的编写主要是根据vid_decoder_if.h提供的接口进行编程。
主要是对结构体decoder_device的实现,decoder_device 结构体封装了具体的实现方法。
/* decoder device structure */
struct decoder_device {
/* Name of the decoder device */
u8 name[DECODER_MAX_NAME];
/* Decoder interface type i.e. BT656 */
vid_capture_interface_type if_type;
/* Id of the channel to which decoder is connected */
int channel_id;
/* decoder capabilities */
u32 capabilities;
/* Pointer to initialize function to initialize decoder */
int (*initialize) (void *dec, int flag);
/* Set of functions pointers for standard related functions */
struct standard_ops *std_ops;
/* Set of functions pointers for control related functions */
struct control_ops *ctrl_ops;
/* Set of functions pointers for input related functions */
struct input_ops *input_ops;
/* Set of functions pointers for format related functions */
struct format_ops *fmt_ops;
/* Set of functions pointers for device specific configs */
struct param_ops *params_ops;
/* Pointer to deinitialize function */
int (*deinitialize) (void *dec);
/* This function will be called whenever the sliced vbi data has to be get from the decoder */
int (*read_vbi_data) (struct v4l2_sliced_vbi_data *data, void *dec);
/* This function will be called whenver all the sliced vbi services needs to be get from the decoder */
int (*get_sliced_vbi_cap) (struct v4l2_sliced_vbi_cap *cap, void *dec);
int (*get_video_sync_status)(void *dec);
};
最后还提供接口向V4L2注册以及反注册
/* Function to register decoder to the VPIF-V4L2 layer */
int vpif_register_decoder(struct decoder_device *decoder);
/* Function to un-register decoder to the VPIF-V4L2 layer */
int vpif_unregister_decoder(struct decoder_device *decoder);
例如在sii9013中decoder_device的实例为:
468 static struct decoder_device sii9013_dev[SII9013_NUM_CHANNELS] = {
469 {
470 .name = "SII9013",
471 .if_type = INTERFACE_TYPE_BT1120,
472 .channel_id = 0,
473 .capabilities = 0,
474 .initialize = sii9013_initialize,
475 .std_ops = &standards_ops,
476 .ctrl_ops = &controls_ops,
477 .input_ops = &inputs_ops,
478 .fmt_ops = NULL,
479 .params_ops = ¶ms_ops,
480 .deinitialize = sii9013_deinitialize,
481 .get_video_sync_status = sii9013_video_sync_status}
482 };
在9013中实现了一下几个操作方式:
445 static struct param_ops params_ops = {
446 .setparams = sii9013_setparams,
447 .getparams = sii9013_getparams
448 };
sii9013_setparams 主要是从用户空间获取用户传递过来的参数进行设置,
同时也调用sii9013_setinput和sii9013_setstd,
在sii9013_setinput中主要是设置视频格式参数的索引。
sii9013_setstd根据v4l2_std_id来获取相应的结构standard,
最后sii9013_setstd根据standard调用sii9013_set_vid_reg来设置相关的寄存器。
sii9013_getparams主要是想用户空间传递相关的参数。
449 static struct control_ops controls_ops = {
450 .count = SII9013_MAX_NO_CONTROLS,
451 .queryctrl = sii9013_querycontrol,
452 .setcontrol = sii9013_setcontrol,
453 .getcontrol = sii9013_getcontrol
454 };
control_ops 这个结构体在9013中只打印一些信息,没有什么作用,相当于空。
455 static struct input_ops inputs_ops = {
456 .count = SII9013_MAX_NO_INPUTS,
457 .enuminput = sii9013_enuminput,
458 .setinput = sii9013_setinput,
459 .getinput = sii9013_getinput
460 };
sii9013_enuminput 将获取输入信息,将信息copy 到v4l2_input。
sii9013_setinput中主要是设置视频格式参数的索引。
sii9013_getinput是获取视频格式参数的索引。
461 static struct standard_ops standards_ops = {
462 .count = SII9013_MAX_NO_STANDARDS,
463 .enumstd = sii9013_enumstd,
464 .setstd = sii9013_setstd,
465 .getstd = sii9013_getstd,
466 .querystd = sii9013_querystd,
467 };
sii9013_enumstd 获取输入的格式信息,并将信息复制到v4l2_standard;
sii9013_setstd根据v4l2_std_id来获取相应的结构standard,
最后sii9013_setstd根据standard调用sii9013_set_vid_reg来设置相关的寄存器。
sii9013_getstd 设置v4l2_std_id。
sii9013_querystd 读取sii9013 10个输入寄存器,然后 sii9013_analysestd通过读取得到的寄存器的值进行判断是哪一种格式。
最后在初始化9013的时候调用davincihd_capture.c 提供的vpif_register_decoder接口注册采集驱动设备。
1901 static int sii9013_i2c_init(void)
1902 {
1903 int err = 0;
1904 int i = 0, j = 0;
1905
1906 /* Take instance of driver */
1907 struct i2c_driver *driver;
1908
1909 i2c_add_driver(&i2c_driver_sii9013_second);
1910
1911 for (i = 0; i < SII9013_NUM_CHANNELS; i++) {
1912 driver = &sii9013_channel_info[i].i2c_dev.driver;
1913
1914 driver->driver.name = "sii9013";
1915 driver->id = I2C_DRIVERID_MISC;
1916
1917 driver->attach_adapter = sii9013_i2c_probe_adapter;
1918 driver->detach_client = sii9013_i2c_detach_client;
1919
1920 err = vpif_register_decoder(&sii9013_dev[i]);
1921 if (err < 0) {
1922 for (j = i - 1; j > 0; j--) {
1923 vpif_unregister_decoder(&sii9013_dev[j]);
1924 }
1925 return err;
1926 }
1927 }
1928 return err;
1929 }