一個基於v4l2框架的輸出驅動分析

地址:linux-2.6.19/drivers/media/video/mxc/output/Mx27_v4l2_output.c

三個結構分析,mxc_v4l2out_fops 向上層註冊其操作,但其上層不是操作系統而是v4l2
static struct file_operations mxc_v4l2out_fops = {
.owner = THIS_MODULE,
.open = mxc_v4l2out_open,
.release = mxc_v4l2out_close,
.ioctl = mxc_v4l2out_ioctl,
.mmap = mxc_v4l2out_mmap,
.poll = mxc_v4l2out_poll,
};

設備結構有兩個, 因爲即使平臺設備,又是v4l2設備,,,分別想兩個地方註冊。

static struct video_device mxc_v4l2out_template = {//v4l2設備
.owner = THIS_MODULE,
.name = "MXC Video Output",
.type = 0,
.type2 = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING,
.hardware = 39,
.fops = &mxc_v4l2out_fops,
.release = video_device_release,
};

static struct platform_device mxc_v4l2out_device = {//平臺設備
.name = "MXC Video Output",
.dev = {
.release = camera_platform_release,
},
.id = 0,
};
平臺驅動:

static struct platform_driver mxc_v4l2out_driver = {
.driver = {
.name = "MXC Video Output",
.owner = THIS_MODULE,
.bus = &platform_bus_type,
},
.probe = mxc_v4l2out_probe,
.remove = NULL,
};

mxc_v4l2out_init-》platform_driver_register(&mxc_v4l2out_driver);註冊平臺設備,註冊成功有主要就是調用驅動的prode...這裏就是mxc_v4l2out_probe
結構體:

/*!
* common v4l2 driver structure.
*/
typedef struct _vout_data {
struct video_device *video_dev;
/*!
* semaphore guard against SMP multithreading
*/
struct semaphore busy_lock;

/*!
* number of process that have device open
*/
int open_count;

v4l_tear_protect tear_protection;

/*!
* params lock for this camera
*/
struct semaphore param_lock;

struct timer_list output_timer;
unsigned long start_jiffies;
u32 frame_count;

v4l_queue ready_q;
v4l_queue done_q;

s8 next_rdy_ipu_buf;
s8 next_done_ipu_buf;
s8 ipu_buf[2];
volatile v4lout_state state;

int cur_disp_output;
int output_fb_num[MXC_V4L2_OUT_NUM_OUTPUTS];
int output_enabled[MXC_V4L2_OUT_NUM_OUTPUTS];
struct v4l2_framebuffer v4l2_fb;
ipu_channel_t display_ch;
ipu_channel_t post_proc_ch;

/*!
* FRAME_NUM-buffering, so we need a array
*/
int buffer_cnt;
dma_addr_t queue_buf_paddr[MAX_FRAME_NUM];
void *queue_buf_vaddr[MAX_FRAME_NUM];
u32 queue_buf_size;
struct v4l2_buffer v4l2_bufs[MAX_FRAME_NUM];
u32 sdc_fg_buf_size;
dma_addr_t display_bufs[2];
void *display_bufs_vaddr[2];
dma_addr_t rot_pp_bufs[2];
void *rot_pp_bufs_vaddr[2];
u32 rot_pp_buf_size;

/*!
* Poll wait queue
*/
wait_queue_head_t v4l_bufq;

/*!
* v4l2 format
*/
struct v4l2_format v2f;
struct v4l2_mxc_offset offset;
ipu_rotate_mode_t rotate;

/* crop */
struct v4l2_rect crop_bounds[MXC_V4L2_OUT_NUM_OUTPUTS];
struct v4l2_rect crop_current;
}

vout_data;mxc_v4l2out_probe中有*(vout->video_dev) = mxc_v4l2out_template把v4l2設備付給 * common v4l2 driver structure.中的video_dev成員

video_register_device向v4l2註冊設備。。。分析其代碼:

內核中註釋:

video_register_device - register video4linux devices
* @vfd: video device structure we want to register
* @type: type of device to register
* @nr: which device number (0 == /dev/video0, 1 == /dev/video1, ...
* -1 == first free)
*

v4l2設備分四種不通的類型:video ,vtx,vbi,radio分別有佔不同的
static struct video_device *video_device[VIDEO_NUM_DEVICES];全局的vide_device結構,靜態在本文件有效

其中分配一個指針,,指向註冊的設備,這樣設備就註冊成功了(videodev.c)

回到prode中video_set_drvdata(vout->video_dev, vout);繼續吧驅動放到dev->priv中。


接下來分析驅動是如何被調用的:

在videodev.c中,videodev_init-》register_chrdev(VIDEO_MAJOR, VIDEO_NAME, &video_fops)向操作系統註冊了fops..所以,只要是#define VIDEO_MAJOR 81,,都要由這個ops來調用,,其中子設備就是通過video_register_device來向該高層註冊的
分析ops中的video_open:

file->f_op = fops_get(vfl->fops);

if(file->f_op->open)
err = file->f_op->open(inode,file);

把子設備相應的fops付給file->f_op,這樣在read,write時候就會調用子設備的read,wrtie了。接下來就是調用子設備的open

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章