对于V4L2
子设备,其核心就是去实现struct v4l2_subdev_ops
子设备操作接口,下面就介绍V4L2
操作函数接口用到的一些关键成员是什么意思。
子设备,负责实现具体的功能。可将其抽象为具体的某一摄像头传感器,如OV7740
、OV7251
、OV5640
和OV13850
等。
每一个子设备驱动都必须有一个 v4l2_subdev
结构体,这个结构体可以作为独立的简单子设备存在,也可以嵌入到更大的结构体(自定义的子设备结构体)里面。通常会有一个由内核设置的低层次结构体(i2c_client
,也就是上面说的 i2c
设备),它包含了一些设备数据,要调用 v4l2_set_subdevdata
来设置子设备私有数据指针指向它,这样的话就可以很方便的从 subdev
找到相关的 I2C
设备数据(这个要编程实现的时候才能够了解它的用意)。另外也需要设置低级别结构的私有数据指针指向 v4l2_subdev
结构体,方便从低级别的结构体访问 v4l2_subdev
结构体,达到双向访问的目的,对于 i2c_client
来说,可以用 i2c_set_clientdata
函数来设置,其它的需使用与之相应的函数来完成设置。
struct v4l2_subdev
源码分析:include\media\v4l2-subdev.h
#define V4L2_SUBDEV_NAME_SIZE 32
/* Set this flag if this subdev is a i2c device. */
/* 设置从设备是I2C设备 */
#define V4L2_SUBDEV_FL_IS_I2C (1U << 0)
/* Set this flag if this subdev is a spi device. */
/* 设置从设备是SPI设备 */
#define V4L2_SUBDEV_FL_IS_SPI (1U << 1)
/* Set this flag if this subdev needs a device node. */
/* 从设备需要设备树节点 */
#define V4L2_SUBDEV_FL_HAS_DEVNODE (1U << 2)
/* Set this flag if this subdev generates events. */
/* 从设备会产生事件 */
#define V4L2_SUBDEV_FL_HAS_EVENTS (1U << 3)
/* Each instance of a subdev driver should create this struct, either
stand-alone or embedded in a larger struct.
*/
struct v4l2_subdev {
#if defined(CONFIG_MEDIA_CONTROLLER)
struct media_entity entity;
#endif
/* 子设备串联链表 */
struct list_head list;
/* 属于那个模块,一般指向i2c_client驱动模块 */
struct module *owner;
bool owner_v4l2_dev;
/* 此标志位是设备属于哪一种设备,由上面的V4L2_SUBDEV_FL_XXX宏确定 */
u32 flags;
/* 指向父设备 */
struct v4l2_device *v4l2_dev;
/* v4l2子设备的操作函数集合 */
const struct v4l2_subdev_ops *ops;
/* Never call these internal ops from within a driver! */
/* 提供给v4l2框架的操作函数,只有v4l2框架会调用,驱动不使用 */
const struct v4l2_subdev_internal_ops *internal_ops;
/* The control handler of this subdev. May be NULL. */
/* subdev控制接口 */
struct v4l2_ctrl_handler *ctrl_handler;
/* name must be unique */
/* 从设备的名称,必须独一无二 */
char name[V4L2_SUBDEV_NAME_SIZE];
/* can be used to group similar subdevs, value is driver-specific */
/* 从设备组的ID,由驱动定义,相似的从设备可以编为一组 */
u32 grp_id;
/* pointer to private data */
/* 从设备私有数据指针,一般指向i2c_client的设备结构体dev */
void *dev_priv;
/* 主设备私有数据指针,一般指向v4l2_device嵌入的结构体 */
void *host_priv;
/* subdev device node */
/* 指向video设备结构体 */
struct video_device *devnode;
/* pointer to the physical device, if any */
/* 指向物理设备 */
struct device *dev;
struct fwnode_handle *fwnode;
/* Links this subdev to a global subdev_list or @notifier->done list. */
/* 将所有从设备连接到全局subdev_list链表或notifier->done链表 */
struct list_head async_list;
/* Pointer to respective struct v4l2_async_subdev. */
/* 指向struct v4l2_async_subdev,用于异步事件 */
struct v4l2_async_subdev *asd;
/* Pointer to the managing notifier. */
/* 指向管理的notifier,用于主设备和从设备的异步关联 */
struct v4l2_async_notifier *notifier;
/* common part of subdevice platform data */
struct v4l2_async_notifier *subdev_notifier;
/* A sub-device notifier implicitly registered for the sub-device
using v4l2_device_register_sensor_subdev(). */
struct v4l2_subdev_platform_data *pdata;
};
上一章节讲解了V4L2
的注册,在注册过程中需要调用v4l2_i2c_subdev_init
对struct v4l2_subdev_ops
结构体进行初始化,它会为子设备提供操作函数,其中struct v4l2_subdev_ops
结构体包含了哪些,具体如下:
include\media\v4l2-subdev.h
struct v4l2_subdev_ops {
/* 视频设备通用的操作:初始化、加载FW、上电和RESET等 */
const struct v4l2_subdev_core_ops *core;
/* 调谐器操作合集 */
const struct v4l2_subdev_tuner_ops *tuner;
/* 音频操作合集 */
const struct v4l2_subdev_audio_ops *audio;
/* 视频设备的特有操作:设置帧率、裁剪图像、开关视频流等 */
/* 视频操作合集 */
const struct v4l2_subdev_video_ops *video;
const struct v4l2_subdev_vbi_ops *vbi;
const struct v4l2_subdev_ir_ops *ir;
const struct v4l2_subdev_sensor_ops *sensor;
const struct v4l2_subdev_pad_ops *pad;
};
struct v4l2_subdev_ops
结构体中的每一个成员都是一个操作函数集合,具体意义如下:struct v4l2_subdev_core_ops
结构体主要是配置子设备的初始化、电源、固件加载等include\media\v4l2-subdev.h
/**
* struct v4l2_subdev_core_ops - Define core ops callbacks for subdevs
*
* @log_status: callback for VIDIOC_LOG_STATUS ioctl handler code.
*
* @s_io_pin_config: configure one or more chip I/O pins for chips that
* multiplex different internal signal pads out to IO pins. This function
* takes a pointer to an array of 'n' pin configuration entries, one for
* each pin being configured. This function could be called at times
* other than just subdevice initialization.
*
* @init: initialize the sensor registers to some sort of reasonable default
* values. Do not use for new drivers and should be removed in existing
* drivers.
*
* @load_fw: load firmware.
*
* @reset: generic reset command. The argument selects which subsystems to
* reset. Passing 0 will always reset the whole chip. Do not use for new
* drivers without discussing this first on the linux-media mailinglist.
* There should be no reason normally to reset a device.
*
* @s_gpio: set GPIO pins. Very simple right now, might need to be extended with
* a direction argument if needed.
*
* @queryctrl: callback for VIDIOC_QUERYCTL ioctl handler code.
*
* @g_ctrl: callback for VIDIOC_G_CTRL ioctl handler code.
*
* @s_ctrl: callback for VIDIOC_S_CTRL ioctl handler code.
*
* @g_ext_ctrls: callback for VIDIOC_G_EXT_CTRLS ioctl handler code.
*
* @s_ext_ctrls: callback for VIDIOC_S_EXT_CTRLS ioctl handler code.
*
* @try_ext_ctrls: callback for VIDIOC_TRY_EXT_CTRLS ioctl handler code.
*
* @querymenu: callback for VIDIOC_QUERYMENU ioctl handler code.
*
* @ioctl: called at the end of ioctl() syscall handler at the V4L2 core.
* used to provide support for private ioctls used on the driver.
*
* @compat_ioctl32: called when a 32 bits application uses a 64 bits Kernel,
* in order to fix data passed from/to userspace.
*
* @g_register: callback for VIDIOC_G_REGISTER ioctl handler code.
*
* @s_register: callback for VIDIOC_G_REGISTER ioctl handler code.
*
* @s_power: puts subdevice in power saving mode (on == 0) or normal operation
* mode (on == 1).
*
* @interrupt_service_routine: Called by the bridge chip's interrupt service
* handler, when an interrupt status has be raised due to this subdev,
* so that this subdev can handle the details. It may schedule work to be
* performed later. It must not sleep. *Called from an IRQ context*.
*
* @subscribe_event: used by the drivers to request the control framework that
* for it to be warned when the value of a control changes.
*
* @unsubscribe_event: remove event subscription from the control framework.
*/
struct v4l2_subdev_core_ops {
/* 状态消息 */
int (*log_status)(struct v4l2_subdev *sd);
int (*s_io_pin_config)(struct v4l2_subdev *sd, size_t n,
struct v4l2_subdev_io_pin_config *pincfg);
/* 初始化设备 */
int (*init)(struct v4l2_subdev *sd, u32 val);
/* 加载firmware */
int (*load_fw)(struct v4l2_subdev *sd);
/* 重置设备 */
int (*reset)(struct v4l2_subdev *sd, u32 val);
/* 设置gpio */
int (*s_gpio)(struct v4l2_subdev *sd, u32 val);
/* 处理特殊命令 */
int (*queryctrl)(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc);
int (*g_ctrl)(struct v4l2_subdev *sd, struct v4l2_control *ctrl);
int (*s_ctrl)(struct v4l2_subdev *sd, struct v4l2_control *ctrl);
int (*g_ext_ctrls)(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls);
int (*s_ext_ctrls)(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls);
int (*try_ext_ctrls)(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls);
int (*querymenu)(struct v4l2_subdev *sd, struct v4l2_querymenu *qm);
long (*ioctl)(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
#ifdef CONFIG_COMPAT
long (*compat_ioctl32)(struct v4l2_subdev *sd, unsigned int cmd,
unsigned long arg);
#endif
#ifdef CONFIG_VIDEO_ADV_DEBUG
/* 获取寄存器值 */
int (*g_register)(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg);
/* 设置寄存器值 */
int (*s_register)(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg);
#endif
/* 控制电源上电下电 */
int (*s_power)(struct v4l2_subdev *sd, int on);
/* 中断服务函数 */
int (*interrupt_service_routine)(struct v4l2_subdev *sd,
u32 status, bool *handled);
/* 处理请求事件 */
int (*subscribe_event)(struct v4l2_subdev *sd, struct v4l2_fh *fh,
struct v4l2_event_subscription *sub);
/* 删除订阅的事件 */
int (*unsubscribe_event)(struct v4l2_subdev *sd, struct v4l2_fh *fh,
struct v4l2_event_subscription *sub);
};
struct v4l2_subdev_tuner_ops
结构体主要是用在一些调谐器和调幅器等一些无线模块时调用include\media\v4l2-subdev.h
/**
* struct s_radio - Callbacks used when v4l device was opened in radio mode.
*
* @s_radio: callback for VIDIOC_S_RADIO ioctl handler code.
*
* @s_frequency: callback for VIDIOC_S_FREQUENCY ioctl handler code.
*
* @g_frequency: callback for VIDIOC_G_FREQUENCY ioctl handler code.
* freq->type must be filled in. Normally done by video_ioctl2
* or the bridge driver.
*
* @enum_freq_bands: callback for VIDIOC_ENUM_FREQ_BANDS ioctl handler code.
*
* @g_tuner: callback for VIDIOC_G_TUNER ioctl handler code.
*
* @s_tuner: callback for VIDIOC_S_TUNER ioctl handler code. vt->type must be
* filled in. Normally done by video_ioctl2 or the
* bridge driver.
*
* @g_modulator: callback for VIDIOC_G_MODULATOR ioctl handler code.
*
* @s_modulator: callback for VIDIOC_S_MODULATOR ioctl handler code.
*
* @s_type_addr: sets tuner type and its I2C addr.
*
* @s_config: sets tda9887 specific stuff, like port1, port2 and qss
*/
struct v4l2_subdev_tuner_ops {
/* 设置无线设备信息 */
int (*s_radio)(struct v4l2_subdev *sd);
/* 设置频率 */
int (*s_frequency)(struct v4l2_subdev *sd, const struct v4l2_frequency *freq);
/* 获取频率 */
int (*g_frequency)(struct v4l2_subdev *sd, struct v4l2_frequency *freq);
int (*enum_freq_bands)(struct v4l2_subdev *sd, struct v4l2_frequency_band *band);
/* 获取调谐器信息 */
int (*g_tuner)(struct v4l2_subdev *sd, struct v4l2_tuner *vt);
/* 设置调谐器信息 */
int (*s_tuner)(struct v4l2_subdev *sd, const struct v4l2_tuner *vt);
/* 获取调幅器信息 */
int (*g_modulator)(struct v4l2_subdev *sd, struct v4l2_modulator *vm);
/* 设置调幅器信息 */
int (*s_modulator)(struct v4l2_subdev *sd, const struct v4l2_modulator *vm);
/* 安装调谐器 */
int (*s_type_addr)(struct v4l2_subdev *sd, struct tuner_setup *type);
/* 设置配置信息 */
int (*s_config)(struct v4l2_subdev *sd, const struct v4l2_priv_tun_config *config);
};
struct v4l2_subdev_audio_ops
结构体主要是用在一些音频模块输入输出的时候调用include\media\v4l2-subdev.h
/**
* struct v4l2_subdev_audio_ops - Callbacks used for audio-related settings
*
* @s_clock_freq: set the frequency (in Hz) of the audio clock output.
* Used to slave an audio processor to the video decoder, ensuring that
* audio and video remain synchronized. Usual values for the frequency
* are 48000, 44100 or 32000 Hz. If the frequency is not supported, then
* -EINVAL is returned.
*
* @s_i2s_clock_freq: sets I2S speed in bps. This is used to provide a standard
* way to select I2S clock used by driving digital audio streams at some
* board designs. Usual values for the frequency are 1024000 and 2048000.
* If the frequency is not supported, then -EINVAL is returned.
*
* @s_routing: used to define the input and/or output pins of an audio chip,
* and any additional configuration data.
* Never attempt to use user-level input IDs (e.g. Composite, S-Video,
* Tuner) at this level. An i2c device shouldn't know about whether an
* input pin is connected to a Composite connector, become on another
* board or platform it might be connected to something else entirely.
* The calling driver is responsible for mapping a user-level input to
* the right pins on the i2c device.
*
* @s_stream: used to notify the audio code that stream will start or has
* stopped.
*/
struct v4l2_subdev_audio_ops {
/* 设置音频设备频率 */
int (*s_clock_freq)(struct v4l2_subdev *sd, u32 freq);
/* 设置i2s总线频率 */
int (*s_i2s_clock_freq)(struct v4l2_subdev *sd, u32 freq);
/* 设置音频路由 */
int (*s_routing)(struct v4l2_subdev *sd, u32 input, u32 output, u32 config);
/* 控制音频流 */
int (*s_stream)(struct v4l2_subdev *sd, int enable);
};
struct v4l2_subdev_video_ops
结构体主要是用在一些视频设备时调用include\media\v4l2-subdev.h
/**
* struct v4l2_subdev_video_ops - Callbacks used when v4l device was opened
* in video mode.
*
* @s_routing: see s_routing in audio_ops, except this version is for video
* devices.
*
* @s_crystal_freq: sets the frequency of the crystal used to generate the
* clocks in Hz. An extra flags field allows device specific configuration
* regarding clock frequency dividers, etc. If not used, then set flags
* to 0. If the frequency is not supported, then -EINVAL is returned.
*
* @g_std: callback for VIDIOC_G_STD ioctl handler code.
*
* @s_std: callback for VIDIOC_S_STD ioctl handler code.
*
* @s_std_output: set v4l2_std_id for video OUTPUT devices. This is ignored by
* video input devices.
*
* @g_std_output: get current standard for video OUTPUT devices. This is ignored
* by video input devices.
*
* @querystd: callback for VIDIOC_QUERYSTD ioctl handler code.
*
* @g_tvnorms: get v4l2_std_id with all standards supported by the video
* CAPTURE device. This is ignored by video output devices.
*
* @g_tvnorms_output: get v4l2_std_id with all standards supported by the video
* OUTPUT device. This is ignored by video capture devices.
*
* @g_input_status: get input status. Same as the status field in the v4l2_input
* struct.
*
* @s_stream: used to notify the driver that a video stream will start or has
* stopped.
*
* @cropcap: callback for VIDIOC_CROPCAP ioctl handler code.
*
* @g_crop: callback for VIDIOC_G_CROP ioctl handler code.
*
* @s_crop: callback for VIDIOC_S_CROP ioctl handler code.
*
* @g_parm: callback for VIDIOC_G_PARM ioctl handler code.
*
* @s_parm: callback for VIDIOC_S_PARM ioctl handler code.
*
* @g_frame_interval: callback for VIDIOC_G_FRAMEINTERVAL ioctl handler code.
*
* @s_frame_interval: callback for VIDIOC_S_FRAMEINTERVAL ioctl handler code.
*
* @s_dv_timings: Set custom dv timings in the sub device. This is used
* when sub device is capable of setting detailed timing information
* in the hardware to generate/detect the video signal.
*
* @g_dv_timings: Get custom dv timings in the sub device.
*
* @query_dv_timings: callback for VIDIOC_QUERY_DV_TIMINGS ioctl handler code.
*
* @g_mbus_config: get supported mediabus configurations
*
* @s_mbus_config: set a certain mediabus configuration. This operation is added
* for compatibility with soc-camera drivers and should not be used by new
* software.
*
* @s_rx_buffer: set a host allocated memory buffer for the subdev. The subdev
* can adjust @size to a lower value and must not write more data to the
* buffer starting at @data than the original value of @size.
*/
struct v4l2_subdev_video_ops {
/* 设置视频路由 */
int (*s_routing)(struct v4l2_subdev *sd, u32 input, u32 output, u32 config);
/* 设置设备频率 */
int (*s_crystal_freq)(struct v4l2_subdev *sd, u32 freq, u32 flags);
int (*g_std)(struct v4l2_subdev *sd, v4l2_std_id *norm);
int (*s_std)(struct v4l2_subdev *sd, v4l2_std_id norm);
/* 设置标准输出 */
int (*s_std_output)(struct v4l2_subdev *sd, v4l2_std_id std);
/* 获取标准输出 */
int (*g_std_output)(struct v4l2_subdev *sd, v4l2_std_id *std);
/* 查询标准 */
int (*querystd)(struct v4l2_subdev *sd, v4l2_std_id *std);
int (*g_tvnorms)(struct v4l2_subdev *sd, v4l2_std_id *std);
int (*g_tvnorms_output)(struct v4l2_subdev *sd, v4l2_std_id *std);
/* 获取输入状态 */
int (*g_input_status)(struct v4l2_subdev *sd, u32 *status);
/* 设置数据流 */
int (*s_stream)(struct v4l2_subdev *sd, int enable);
int (*cropcap)(struct v4l2_subdev *sd, struct v4l2_cropcap *cc);
int (*g_crop)(struct v4l2_subdev *sd, struct v4l2_crop *crop);
int (*s_crop)(struct v4l2_subdev *sd, const struct v4l2_crop *crop);
int (*g_parm)(struct v4l2_subdev *sd, struct v4l2_streamparm *param);
int (*s_parm)(struct v4l2_subdev *sd, struct v4l2_streamparm *param);
/* 获取帧间隔参数(帧率) */
int (*g_frame_interval)(struct v4l2_subdev *sd,
struct v4l2_subdev_frame_interval *interval);
/* 设置帧间隔参数(帧率) */
int (*s_frame_interval)(struct v4l2_subdev *sd,
struct v4l2_subdev_frame_interval *interval);
int (*enum_framesizes)(struct v4l2_subdev *sd,
struct v4l2_frmsizeenum *fsize);
int (*enum_frameintervals)(struct v4l2_subdev *sd,
struct v4l2_frmivalenum *fival);
/* 设置设备自定义时钟计时,需要硬件支持 */
int (*s_dv_timings)(struct v4l2_subdev *sd,
struct v4l2_dv_timings *timings);
/* 获取设备自定义时钟计时,需要硬件支持 */
int (*g_dv_timings)(struct v4l2_subdev *sd,
struct v4l2_dv_timings *timings);
/* 检测设备自定义时钟计时,需要硬件支持 */
int (*query_dv_timings)(struct v4l2_subdev *sd,
struct v4l2_dv_timings *timings);
int (*enum_mbus_fmt)(struct v4l2_subdev *sd, unsigned int index,
u32 *code);
int (*enum_mbus_fsizes)(struct v4l2_subdev *sd,
struct v4l2_frmsizeenum *fsize);
int (*g_mbus_fmt)(struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *fmt);
int (*try_mbus_fmt)(struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *fmt);
int (*s_mbus_fmt)(struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *fmt);
/* 获取总线配置,对于 MIPI接口, sensor驱动内若支持不同
lane数配置或者支持 HDR,通过这个接口返回当前 sensor 工作模式下的MIPI配置*/
int (*g_mbus_config)(struct v4l2_subdev *sd,
struct v4l2_mbus_config *cfg);
/* 获取MIPI总线配置 */
int (*s_mbus_config)(struct v4l2_subdev *sd,
const struct v4l2_mbus_config *cfg);
int (*s_rx_buffer)(struct v4l2_subdev *sd, void *buf,
unsigned int *size);
};
struct v4l2_subdev_pad_ops
结构体主要是用于配置v4l2_subdev
设备数据格式等作用include\media\v4l2-subdev.h
/**
* struct v4l2_subdev_pad_ops - v4l2-subdev pad level operations
*
* @enum_mbus_code: callback for VIDIOC_SUBDEV_ENUM_MBUS_CODE ioctl handler
* code.
* @enum_frame_size: callback for VIDIOC_SUBDEV_ENUM_FRAME_SIZE ioctl handler
* code.
*
* @enum_frame_interval: callback for VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL ioctl
* handler code.
*
* @get_fmt: callback for VIDIOC_SUBDEV_G_FMT ioctl handler code.
*
* @set_fmt: callback for VIDIOC_SUBDEV_S_FMT ioctl handler code.
*
* @get_selection: callback for VIDIOC_SUBDEV_G_SELECTION ioctl handler code.
*
* @set_selection: callback for VIDIOC_SUBDEV_S_SELECTION ioctl handler code.
*
* @get_edid: callback for VIDIOC_SUBDEV_G_EDID ioctl handler code.
*
* @set_edid: callback for VIDIOC_SUBDEV_S_EDID ioctl handler code.
*
* @dv_timings_cap: callback for VIDIOC_SUBDEV_DV_TIMINGS_CAP ioctl handler
* code.
*
* @enum_dv_timings: callback for VIDIOC_SUBDEV_ENUM_DV_TIMINGS ioctl handler
* code.
*
* @link_validate: used by the media controller code to check if the links
* that belongs to a pipeline can be used for stream.
*
* @get_frame_desc: get the current low level media bus frame parameters.
*
* @set_frame_desc: set the low level media bus frame parameters, @fd array
* may be adjusted by the subdev driver to device capabilities.
*/
struct v4l2_subdev_pad_ops {
/* 枚举当前CIS 驱动支持数据格式 */
int (*enum_mbus_code)(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_mbus_code_enum *code);
/* 枚举当前CIS 驱动支持分辨率 */
int (*enum_frame_size)(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_frame_size_enum *fse);
/* 枚举sensor支持的帧间隔,包含分辨率 */
int (*enum_frame_interval)(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_frame_interval_enum *fie);
/* 枚举当前CIS 驱动支持分辨率 */
int (*get_fmt)(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_format *format);
/* 设置CIS 驱动输出数据格式以及分辨率,必须实现 */
int (*set_fmt)(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_format *format);
/* 配置裁剪参数,isp输入的宽度要求16对齐,高度 8 对齐 */
int (*get_selection)(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_selection *sel);
/* */
int (*set_selection)(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_selection *sel);
int (*get_edid)(struct v4l2_subdev *sd, struct v4l2_edid *edid);
int (*set_edid)(struct v4l2_subdev *sd, struct v4l2_edid *edid);
int (*dv_timings_cap)(struct v4l2_subdev *sd,
struct v4l2_dv_timings_cap *cap);
int (*enum_dv_timings)(struct v4l2_subdev *sd,
struct v4l2_enum_dv_timings *timings);
#ifdef CONFIG_MEDIA_CONTROLLER
int (*link_validate)(struct v4l2_subdev *sd, struct media_link *link,
struct v4l2_subdev_format *source_fmt,
struct v4l2_subdev_format *sink_fmt);
#endif /* CONFIG_MEDIA_CONTROLLER */
int (*get_frame_desc)(struct v4l2_subdev *sd, unsigned int pad,
struct v4l2_mbus_frame_desc *fd);
int (*set_frame_desc)(struct v4l2_subdev *sd, unsigned int pad,
struct v4l2_mbus_frame_desc *fd);
};
返回总目录