输出的芯片驱动跟采集芯片的驱动类似,TI也提供了输出芯片驱动的接口,它提供了和采集芯片类似的头文件,要编写主要是根据include/media/davinci/vid_encoder_if.h 这个头文件进行编写。
主要是定义了视频编码设备的结构体,结构体如下:
/**
* struct vid_encoder_device
* @name: Name of the encoder device
* @channel_id: Id of the channel to which encoder is connected
* @capabilities: encoder capabilities. This is only for VBI capabilities
* @initialize: Pointer to initialize function to initialize encoder
* @mode_ops: Set of functions pointers for standard related functions
* @ctrl_ops: Set of functions pointers for control related functions
* @output_ops: Set of functions pointers for output related functions
* @fmt_ops: Set of functions pointers for format related functions
* @params_ops: Set of functions pointers for params related functions
* @misc_ops: Set of functions pointers for miscellaneous functions functions
* @deinitialize: functions pointer to de-initialize functio
* @start_display: function to start display.
* @stop_display: function to stop display.
* @write_vbi_data: function to write sliced vbi data.
* @enable_vbi: Function to enable support for RAW VBI.
* @enable_hbi: Function to enable support for RAW HBI.
* @set_vbi_services: function to enable sliced vbi services
*
* Description:
* output ops structure
* Channel_id is used when encoder support multiple channels. In this case
* encoder module will use the channel id to select the channel for
* which the operation applies.
* initialize() called by encoder manager to initialize the encoder. Usually
* called before invoking any operations on the encoder.flag may be used by
* the encoder module to do different level of initialization. Encoder
* module must set a default output and mode in this code.
* deinitialize() called to deinitialize the current encoder that is active
* before initializing the new encoder.
*/
struct vid_encoder_device {
u8 name[VID_ENC_NAME_MAX_CHARS];
int channel_id;
u32 capabilities;
int (*initialize) (struct vid_encoder_device * enc, int flag);
struct vid_enc_mode_ops *mode_ops;
struct vid_enc_control_ops *ctrl_ops;
struct vid_enc_output_ops *output_ops;
struct vid_enc_param_ops *params_ops;
struct vid_enc_misc_ops *misc_ops;
int (*write_vbi_data) (struct vid_enc_sliced_vbi_data * data,
struct vid_encoder_device * enc);
int (*enable_vbi) (int flag, struct vid_encoder_device * enc);
int (*enable_hbi) (int flag, struct vid_encoder_device * enc);
int (*set_vbi_services) (struct vid_enc_sliced_vbi_service * services,
struct vid_encoder_device * enc);
int (*get_sliced_cap) (struct vid_enc_sliced_vbi_service *,
struct vid_encoder_device * enc);
int (*deinitialize) (struct vid_encoder_device * enc);
int (*start_display) (struct vid_encoder_device * enc);
int (*stop_display) (struct vid_encoder_device * enc);
};
同时也包含了在drivers/media/video/davinci/davinci_enc_mngr.c定义的注册和反注册的两个接口,供其他模块使用。
261 /**
262 * vid_enc_register_encoder
263 * @encoder: pointer to the encoder device structure
264 * Returns: Zero if successful, or non-zero otherwise
265 *
266 * Description:
267 * Register the encoder module with the encoder manager
268 * This is implemented by the encoder Manager
269 */
270 int vid_enc_register_encoder(struct vid_encoder_device
271 *encoder);
272
273 /**
274 * vid_enc_unregister_encoder
275 * @encoder: pointer to the encoder device structure
276 * Returns: Zero if successful, or non-zero otherwise
277 *
278 * Description:
279 * Unregister the encoder module with the encoder manager
280 * This is implemented by the encoder Manager
281 */
282 int vid_enc_unregister_encoder(struct vid_encoder_device
283 *encoder);
视频输出设备结构体在9034中定义如下:
538 static struct vid_encoder_device sii9034_dev[SII9034_NUM_CHANNELS] = {
539 {
540 .name = "SII9034",
541 .channel_id = 0,
542 .capabilities = 0,
543 .initialize = sii9034_initialize,
544 .mode_ops = &standards_ops,
545 .ctrl_ops = &controls_ops,
546 .output_ops = &outputs_ops,
547 .params_ops = ¶ms_ops,
548 .deinitialize = sii9034_deinitialize,
549 .misc_ops = NULL,
550 .write_vbi_data = NULL,
551 .enable_vbi = NULL,
552 .enable_hbi = NULL,
553 .set_vbi_services = NULL,
554 .get_sliced_cap = NULL,
555 .start_display = sii9034_start_display,
556 .stop_display = sii9034_stop_display}
557 };
编写9034的驱动主要完成以上的一些操作,
515 /* Global structures variables */用户空间和内核空间的操作
516 static struct vid_enc_param_ops params_ops = {
517 .setparams = sii9034_set_params,
518 .getparams = sii9034_get_params
519 };
520 //一些控制信息
521 static struct vid_enc_control_ops controls_ops = {
522 .setcontrol = sii9034_setcontrol,
523 .getcontrol = sii9034_getcontrol
524 };
525 //输出的一些操作
526 static struct vid_enc_output_ops outputs_ops = {
527 .count = SII9034_MAX_NO_OUTPUTS,
528 .enumoutput = sii9034_enumoutput,
529 .setoutput = sii9034_setoutput, //通过index设置输出的索引
530 .getoutput = sii9034_getoutput
531 };
532
533 static struct vid_enc_mode_ops standards_ops = {
534 .setmode = sii9034_setstd,
535 .getmode = sii9034_getstd,
536 };
537
9034的初始化函数 sii9034_i2c_init,9034模块的初始化主要是初始化I2C设备和注册vid_encoder_device,具体函数如下所示:
1910 /* This function used to initialize the i2c driver */
1911 static int sii9034_i2c_init(void)
1912 {
1913 int err = 0;
1914 int i = 0, j;
1915 /* Take instance of driver */
1916 struct i2c_driver *driver;
1917
1918 static char strings[SII9034_NUM_CHANNELS][80] = {
1919 "SII9034"
1920 };
1921
1922 for (i = 0; i < SII9034_NUM_CHANNELS; i++) {
1923 driver = &sii9034_channel_info[i].i2c_dev.driver;
1924 driver->driver.name = strings[i];
1925 driver->id = I2C_DRIVERID_MISC;
1926 // driver->flags = I2C_DF_NOTIFY;
1927 if (0 == i) {
1928 driver->attach_adapter = sii9034_i2c_probe_adapter;
1929 }
1930
1931 driver->detach_client = sii9034_i2c_detach_client;
1932 err |= vid_enc_register_encoder(&sii9034_dev[i]);
1933 if (err < 0) {
1934 for (j = i - 1; j > 0; j--) {
1935 vid_enc_unregister_encoder(&sii9034_dev[j]);
1936 }
1937 return err;
1938 }
1939 }
1940 return err;
1941 }
9034设备的初始化sii9034_initialize,主要是用i2c_add_driver注册I2C 驱动,以及相关寄存器的设置。
533 static struct vid_enc_mode_ops standards_ops = {
534 .setmode = sii9034_setstd,
535 .getmode = sii9034_getstd,
536 };
sii9034_setstd 通过比较来获取输出的格式,然后根据该格式设置相关的寄存器,最后将得到的输出格式保存到sii9034_channel_info[ch_id].mode_info中。
sii9034_getstd 从sii9034_channel_info[ch_id].mode_info取出格式信息。
521 static struct vid_enc_control_ops controls_ops = {
522 .setcontrol = sii9034_setcontrol,
523 .getcontrol = sii9034_getcontrol
524 };
设置和获取一些相关的控制信息,比如亮度等
515 /* Global structures variables */
516 static struct vid_enc_param_ops params_ops = {
517 .setparams = sii9034_set_params,
518 .getparams = sii9034_get_params
519 };
params_ops 提供了用户空间和内核空间的接口,如下:
1778 /* This function is used to set parameters depending on the type */
1779 static int sii9034_set_params(void *p, struct vid_encoder_device *enc)
1780 {
1781 int err = 0;
1782 int ch_id;
1783 sii9034_params params;
1784
1785 if (NULL == enc) {
1786 printk(KERN_ERR "NULL Pointer.\n");
1787 return -EINVAL;
1788 }
1789 return 0;
1790
1791
1792 ch_id = enc->channel_id;
1793 dev_dbg(sii9034_i2c_dev[ch_id], "<sii9034_set_params>\n");
1794 /* Check for null value */
1795 if (!(sii9034_params *) p) {
1796 dev_err(sii9034_i2c_dev[ch_id],
1797 "sii9034_set_hdparams:NULL pointer\n");
1798 return -EINVAL;
1799 }
1800
1801 if (copy_from_user(¶ms, (sii9034_params *) p, sizeof(params))) {
1802 return -EFAULT;
1803 }
1804
1805 if (SII9034_SDPARAMS == params.type) {
1806 /* If parameter type is SD parameters, call
1807 * sii9034_set_sdparams function to set SD parameters */
1808 //err = sii9034_set_sdparams(&(params.params.sd), enc);
1809 } else if (SII9034_HDPARAMS == params.type) {
1810 /* If parameter type is HD parameters, call
1811 * sii9034_set_hdparams function to set HD parameters */
1812 //err = sii9034_set_hdparams(&(params.params.hd), enc);
1813 } else {
1814 dev_err(sii9034_i2c_dev[ch_id],
1815 "sii9034_set_params:invalid type of parameter\n");
1816 return -EINVAL;
1817 }
1818 sii9034_channel_info[ch_id].params = params;
1819 dev_dbg(sii9034_i2c_dev[ch_id], "</sii9034_set_params>\n");
1820 return err;
1821 }
1823 /* This function is used to get parameters depending on the type */
1824 static int sii9034_get_params(void *p, struct vid_encoder_device *enc)
1825 {
1826 int err = 0;
1827 int ch_id;
1828 sii9034_params *params = (sii9034_params *) p;
1829 if (NULL == enc) {
1830 printk(KERN_ERR "NULL Pointer.\n");
1831 return -EINVAL;
1832 }
1833
1834 ch_id = enc->channel_id;
1835 dev_dbg(sii9034_i2c_dev[ch_id], "<sii9034_get_params>\n");
1836 /* Check for null value */
1837 if (!params) {
1838 dev_err(sii9034_i2c_dev[ch_id],
1839 "sii9034_get_params:NULL pointer\n");
1840 return -EINVAL;
1841 }
1842
1843 if (copy_to_user(params, &(sii9034_channel_info[ch_id].params),
1844 sizeof(*params))) {
1845 return -EFAULT;
1846 }
1847 dev_dbg(sii9034_i2c_dev[ch_id], "</sii9034_get_params>\n");
1848 return err;
1849 }
1850