Embeded linux之soc camera

嵌入式技术

1367人已加入

描述

soc camera 子系统为分为soc camera device 和 soc camera host,并且定义了标准的接口或者回调函数.

流程:

1.获取传来信息,填充soc_camera_link

2.初始化soc_camera_device(iface、device、设备号、总线类型)、加入链表

3.

一、/linux-3.0.35/drivers/media/video/soc_camera.c主要是用来管理接口或者回调函数.

module_init(soc_camera_init);

static int __init soc_camera_init(void)
{
int ret = bus_register(&soc_camera_bus_type);//注册单没有关联
...
ret = driver_register(&ic_drv);

...

ret = platform_driver_probe(&soc_camera_pdrv, soc_camera_pdrv_probe);

...
}

static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev)
{

//通过传入的参数pdev获取platform_data,即struct soc_camera_link
struct soc_camera_link *icl = pdev->dev.platform_data;

struct soc_camera_device *icd;

/*

* 分配设备结构及初始化

*/

icd = kzalloc(sizeof(*icd), GFP_KERNEL);

icd->iface = icl->bus_id;//iface被初始化为bus_id
icd->pdev = &pdev->dev;
platform_set_drvdata(pdev, icd);

ret = soc_camera_device_register(icd);//soc_camera_device加到全局camera device链表@devices上,并且为它分配设备号,做一些必要的初始化

soc_camera_device_init(&icd->dev, icl);//设置soc_came_device对应device的bus为soc_camera_bus_type,这样当我们注册设备时,就会调用soc_camera_probe

icd->user_width  = DEFAULT_WIDTH;
icd->user_height = DEFAULT_HEIGHT;
}

struct soc_camera_link {
int bus_id;//匹配soc camera host的序号
unsigned long flags;
int i2c_adapter_id;//I2C 适配器号
struct i2c_board_info *board_info;
const char *module_name;
void *priv;
struct regulator_bulk_data *regulators;//用于电源的管理
int num_regulators;

/*

*针对那些非I2C的平台的函数,用于管理sensor设备的添加或者删除

*/
int (*add_device)(struct soc_camera_link *, struct device *);
void (*del_device)(struct soc_camera_link *);
int (*power)(struct device *, int);
int (*reset)(struct device *);
int (*set_bus_param)(struct soc_camera_link *, unsigned long flags);
unsigned long (*query_bus_param)(struct soc_camera_link *);
void (*free_bus)(struct soc_camera_link *);
};

struct soc_camera_device {
struct list_head list;
struct device dev;
struct device *pdev;  
s32 user_width;           //图像的宽度,以像素为单位
s32 user_height;//图像的高度,以像素为单位
u32 bytesperline;  
u32 sizeimage;            //一画图像的大小,也是存储图像缓冲区的大小
enum v4l2_colorspace colorspace;//色域,指描述色彩时所使用的坐标系
unsigned char iface;  //于camera link中的bus_id相对应
unsigned char devnum;  
struct soc_camera_sense *sense; 
struct soc_camera_ops *ops;
struct video_device *vdev;
const struct soc_camera_format_xlate *current_fmt;//驱动中当前使用的视频格式
struct soc_camera_format_xlate *user_formats;     //全部支持的视频格式
int num_user_formats;
enum v4l2_field field;  //决定图像源数据交错的方式
void *host_priv;  
int use_count;
struct mutex video_lock; 
struct file *streamer;  

/*

* 管理帧缓冲区

*/
union {
struct videobuf_queue vb_vidq;
struct vb2_queue vb2_vidq;
};
};

static int soc_camera_device_register(struct soc_camera_device *icd)
{
struct soc_camera_device *ix;
int num = -1, i;

for (i = 0; i < 256 && num < 0; i++) {//判断挂接的设备是否256个设备号都占用
num = i;
list_for_each_entry(ix, &devices, list) {
if (ix->iface == icd->iface && ix->devnum == i) {
num = -1;
break;
}
}
   }

icd->devnum  = num;//找到空闲的设备号
icd->use_count  = 0;
icd->host_priv  = NULL;
mutex_init(&icd->video_lock);

list_add_tail(&icd->list, &devices);//将空闲的设备结构放入链表

}

static void soc_camera_device_init(struct device *dev, void *pdata)
{
dev->platform_data = pdata;
dev->bus  = &soc_camera_bus_type;//设置总线类型
dev->release  = dummy_release;
}

struct bus_type soc_camera_bus_type = {
 .name  = "soc-camera",
 .probe  = soc_camera_probe,
 .remove  = soc_camera_remove,
 .suspend = soc_camera_suspend,
 .resume  = soc_camera_resume,
};

static int soc_camera_probe(struct device *dev)
{

...
 ret = video_dev_create(icd);

...

}

static int video_dev_create(struct soc_camera_device *icd)
{
 struct video_device *vdev = video_device_alloc();

strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name));

vdev->parent  = &icd->dev;
 vdev->current_norm = V4L2_STD_UNKNOWN;
 vdev->fops  = &soc_camera_fops;
 vdev->ioctl_ops  = &soc_camera_ioctl_ops;
 vdev->release  = video_device_release;
 vdev->tvnorms  = V4L2_STD_UNKNOWN;

icd->vdev = vdev;

return 0;
}

static struct v4l2_file_operations soc_camera_fops = {
 .owner  = THIS_MODULE,
 .open  = soc_camera_open,
 .release = soc_camera_close,
 .unlocked_ioctl = video_ioctl2,
 .read  = soc_camera_read,
 .mmap  = soc_camera_mmap,
 .poll  = soc_camera_poll,
};

static int soc_camera_open(struct file *file)
{
 struct video_device *vdev = video_devdata(file);//获取video_driver信息

...

/linux-3.0.35/drivers/media/video/v4l2-ioctl.c

long video_ioctl2(struct file *file,
        unsigned int cmd, unsigned long arg)
{
return video_usercopy(file, cmd, arg, __video_do_ioctl);
}

static long __video_do_ioctl(struct file *file,
  unsigned int cmd, void *arg)
{
struct video_device *vfd = video_devdata(file);
const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
void *fh = file->private_data;

...

case VIDIOC_S_CROP:
{
struct v4l2_crop *p = arg;

ret = ops->vidioc_s_crop(file, fh, p);
break;
}

...

}



 

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分