soc camera 子系统为分为soc camera device 和 soc camera host,并且定义了标准的接口或者回调函数.
流程:
1.获取传来信息,填充soc_camera_link
2.初始化soc_camera_device(iface、device、设备号、总线类型)、加入链表
3.
一、/ linux -3.0.35/drive rs /media/video/soc_camera.c主要是用来管理接口或者回调函数.
module_init(soc_camera_init);
sta ti c int __init soc_camera_init(void)
{
int ret = bus_regis te r(&soc_camera_bus_type);//注册单没有关联
...
ret = driver_register(&ic_drv);
...
ret = platform_driver_probe(&soc_camera_pdrv, soc_camera_pdrv_probe);
...
}
sta TI c 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_w idt h = 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_pa ram )(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 v 4l 2_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;
};
};
sta TI c 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_t ai l(&icd->list, &devices);//将空闲的设备结构放入链表
}
sta TI c 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,
};
sta TI c 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;
}
...
}