diff options
Diffstat (limited to 'include/media/v4l2-subdev.h')
-rw-r--r-- | include/media/v4l2-subdev.h | 183 |
1 files changed, 144 insertions, 39 deletions
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index a9e6b8146279..57f2bcb4eb16 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -450,15 +450,17 @@ enum v4l2_subdev_pre_streamon_flags { * already started or stopped subdev. Also see call_s_stream wrapper in * v4l2-subdev.c. * - * @g_pixelaspect: callback to return the pixelaspect ratio. - * - * @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. + * This callback is DEPRECATED. New drivers should instead implement + * &v4l2_subdev_pad_ops.enable_streams and + * &v4l2_subdev_pad_ops.disable_streams operations, and use + * v4l2_subdev_s_stream_helper for the &v4l2_subdev_video_ops.s_stream + * operation to support legacy users. * - * @g_dv_timings: Get custom dv timings in the sub device. + * Drivers should also not call the .s_stream() subdev operation directly, + * but use the v4l2_subdev_enable_streams() and + * v4l2_subdev_disable_streams() helpers. * - * @query_dv_timings: callback for VIDIOC_QUERY_DV_TIMINGS() ioctl handler code. + * @g_pixelaspect: callback to return the pixelaspect ratio. * * @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 @@ -490,12 +492,6 @@ struct v4l2_subdev_video_ops { int (*g_input_status)(struct v4l2_subdev *sd, u32 *status); int (*s_stream)(struct v4l2_subdev *sd, int enable); int (*g_pixelaspect)(struct v4l2_subdev *sd, struct v4l2_fract *aspect); - 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 (*s_rx_buffer)(struct v4l2_subdev *sd, void *buf, unsigned int *size); int (*pre_streamon)(struct v4l2_subdev *sd, u32 flags); @@ -695,7 +691,7 @@ struct v4l2_subdev_pad_config { * * @pad: pad number * @stream: stream number - * @enabled: has the stream been enabled with v4l2_subdev_enable_stream() + * @enabled: has the stream been enabled with v4l2_subdev_enable_streams() * @fmt: &struct v4l2_mbus_framefmt * @crop: &struct v4l2_rect to be used for crop * @compose: &struct v4l2_rect to be used for compose @@ -728,12 +724,14 @@ struct v4l2_subdev_stream_configs { /** * struct v4l2_subdev_krouting - subdev routing table * + * @len_routes: length of routes array, in routes * @num_routes: number of routes * @routes: &struct v4l2_subdev_route * * This structure contains the routing table for a subdev. */ struct v4l2_subdev_krouting { + unsigned int len_routes; unsigned int num_routes; struct v4l2_subdev_route *routes; }; @@ -791,6 +789,14 @@ struct v4l2_subdev_state { * * @set_edid: callback for VIDIOC_SUBDEV_S_EDID() 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. + * * @dv_timings_cap: callback for VIDIOC_SUBDEV_DV_TIMINGS_CAP() ioctl handler * code. * @@ -816,7 +822,9 @@ struct v4l2_subdev_state { * possible configuration from the remote end, likely calling * this operation as close as possible to stream on time. The * operation shall fail if the pad index it has been called on - * is not valid or in case of unrecoverable failures. + * is not valid or in case of unrecoverable failures. The + * config argument has been memset to 0 just before calling + * the op. * * @set_routing: Enable or disable data connection routes described in the * subdevice routing table. Subdevs that implement this operation @@ -828,11 +836,19 @@ struct v4l2_subdev_state { * v4l2_subdev_init_finalize() at initialization time). Do not call * directly, use v4l2_subdev_enable_streams() instead. * + * Drivers that support only a single stream without setting the + * V4L2_SUBDEV_CAP_STREAMS sub-device capability flag can ignore the mask + * argument. + * * @disable_streams: Disable the streams defined in streams_mask on the given * source pad. Subdevs that implement this operation must use the active * state management provided by the subdev core (enabled through a call to * v4l2_subdev_init_finalize() at initialization time). Do not call * directly, use v4l2_subdev_disable_streams() instead. + * + * Drivers that support only a single stream without setting the + * V4L2_SUBDEV_CAP_STREAMS sub-device capability flag can ignore the mask + * argument. */ struct v4l2_subdev_pad_ops { int (*enum_mbus_code)(struct v4l2_subdev *sd, @@ -864,6 +880,12 @@ struct v4l2_subdev_pad_ops { struct v4l2_subdev_frame_interval *interval); int (*get_edid)(struct v4l2_subdev *sd, struct v4l2_edid *edid); int (*set_edid)(struct v4l2_subdev *sd, struct v4l2_edid *edid); + int (*s_dv_timings)(struct v4l2_subdev *sd, unsigned int pad, + struct v4l2_dv_timings *timings); + int (*g_dv_timings)(struct v4l2_subdev *sd, unsigned int pad, + struct v4l2_dv_timings *timings); + int (*query_dv_timings)(struct v4l2_subdev *sd, unsigned int pad, + struct v4l2_dv_timings *timings); int (*dv_timings_cap)(struct v4l2_subdev *sd, struct v4l2_dv_timings_cap *cap); int (*enum_dv_timings)(struct v4l2_subdev *sd, @@ -1039,10 +1061,11 @@ struct v4l2_subdev_platform_data { * @active_state: Active state for the subdev (NULL for subdevs tracking the * state internally). Initialized by calling * v4l2_subdev_init_finalize(). - * @enabled_streams: Bitmask of enabled streams used by - * v4l2_subdev_enable_streams() and - * v4l2_subdev_disable_streams() helper functions for fallback - * cases. + * @enabled_pads: Bitmask of enabled pads used by v4l2_subdev_enable_streams() + * and v4l2_subdev_disable_streams() helper functions for + * fallback cases. + * @s_stream_enabled: Tracks whether streaming has been enabled with s_stream. + * This is only for call_s_stream() internal use. * * Each instance of a subdev driver should create this struct, either * stand-alone or embedded in a larger struct. @@ -1090,7 +1113,8 @@ struct v4l2_subdev { * doesn't support it. */ struct v4l2_subdev_state *active_state; - u64 enabled_streams; + u64 enabled_pads; + bool s_stream_enabled; }; @@ -1237,6 +1261,12 @@ int v4l2_subdev_link_validate_default(struct v4l2_subdev *sd, * calls v4l2_subdev_link_validate_default() to ensure that * width, height and the media bus pixel code are equal on both * source and sink of the link. + * + * The function can be used as a drop-in &media_entity_ops.link_validate + * implementation for v4l2_subdev instances. It supports all links between + * subdevs, as well as links between subdevs and video devices, provided that + * the video devices also implement their &media_entity_ops.link_validate + * operation. */ int v4l2_subdev_link_validate(struct media_link *link); @@ -1324,6 +1354,16 @@ void v4l2_subdev_cleanup(struct v4l2_subdev *sd); #define __v4l2_subdev_state_gen_call(NAME, _1, ARG, ...) \ __v4l2_subdev_state_get_ ## NAME ## ARG +/* + * A macro to constify the return value of the state accessors when the state + * parameter is const. + */ +#define __v4l2_subdev_state_constify_ret(state, value) \ + _Generic(state, \ + const struct v4l2_subdev_state *: (const typeof(*(value)) *)(value), \ + struct v4l2_subdev_state *: (value) \ + ) + /** * v4l2_subdev_state_get_format() - Get pointer to a stream format * @state: subdevice state @@ -1338,16 +1378,21 @@ void v4l2_subdev_cleanup(struct v4l2_subdev *sd); */ /* * Wrap v4l2_subdev_state_get_format(), allowing the function to be called with - * two or three arguments. The purpose of the __v4l2_subdev_state_get_format() - * macro below is to come up with the name of the function or macro to call, - * using the last two arguments (_stream and _pad). The selected function or - * macro is then called using the arguments specified by the caller. A similar - * arrangement is used for v4l2_subdev_state_crop() and - * v4l2_subdev_state_compose() below. - */ -#define v4l2_subdev_state_get_format(state, pad, ...) \ - __v4l2_subdev_state_gen_call(format, ##__VA_ARGS__, , _pad) \ - (state, pad, ##__VA_ARGS__) + * two or three arguments. The purpose of the __v4l2_subdev_state_gen_call() + * macro is to come up with the name of the function or macro to call, using + * the last two arguments (_stream and _pad). The selected function or macro is + * then called using the arguments specified by the caller. The + * __v4l2_subdev_state_constify_ret() macro constifies the returned pointer + * when the state is const, allowing the state accessors to guarantee + * const-correctness in all cases. + * + * A similar arrangement is used for v4l2_subdev_state_crop(), + * v4l2_subdev_state_compose() and v4l2_subdev_state_get_interval() below. + */ +#define v4l2_subdev_state_get_format(state, pad, ...) \ + __v4l2_subdev_state_constify_ret(state, \ + __v4l2_subdev_state_gen_call(format, ##__VA_ARGS__, , _pad) \ + ((struct v4l2_subdev_state *)state, pad, ##__VA_ARGS__)) #define __v4l2_subdev_state_get_format_pad(state, pad) \ __v4l2_subdev_state_get_format(state, pad, 0) struct v4l2_mbus_framefmt * @@ -1366,9 +1411,10 @@ __v4l2_subdev_state_get_format(struct v4l2_subdev_state *state, * For stream-unaware drivers the crop rectangle for the corresponding pad is * returned. If the pad does not exist, NULL is returned. */ -#define v4l2_subdev_state_get_crop(state, pad, ...) \ - __v4l2_subdev_state_gen_call(crop, ##__VA_ARGS__, , _pad) \ - (state, pad, ##__VA_ARGS__) +#define v4l2_subdev_state_get_crop(state, pad, ...) \ + __v4l2_subdev_state_constify_ret(state, \ + __v4l2_subdev_state_gen_call(crop, ##__VA_ARGS__, , _pad) \ + ((struct v4l2_subdev_state *)state, pad, ##__VA_ARGS__)) #define __v4l2_subdev_state_get_crop_pad(state, pad) \ __v4l2_subdev_state_get_crop(state, pad, 0) struct v4l2_rect * @@ -1387,9 +1433,10 @@ __v4l2_subdev_state_get_crop(struct v4l2_subdev_state *state, unsigned int pad, * For stream-unaware drivers the compose rectangle for the corresponding pad is * returned. If the pad does not exist, NULL is returned. */ -#define v4l2_subdev_state_get_compose(state, pad, ...) \ - __v4l2_subdev_state_gen_call(compose, ##__VA_ARGS__, , _pad) \ - (state, pad, ##__VA_ARGS__) +#define v4l2_subdev_state_get_compose(state, pad, ...) \ + __v4l2_subdev_state_constify_ret(state, \ + __v4l2_subdev_state_gen_call(compose, ##__VA_ARGS__, , _pad) \ + ((struct v4l2_subdev_state *)state, pad, ##__VA_ARGS__)) #define __v4l2_subdev_state_get_compose_pad(state, pad) \ __v4l2_subdev_state_get_compose(state, pad, 0) struct v4l2_rect * @@ -1408,9 +1455,10 @@ __v4l2_subdev_state_get_compose(struct v4l2_subdev_state *state, * For stream-unaware drivers the frame interval for the corresponding pad is * returned. If the pad does not exist, NULL is returned. */ -#define v4l2_subdev_state_get_interval(state, pad, ...) \ - __v4l2_subdev_state_gen_call(interval, ##__VA_ARGS__, , _pad) \ - (state, pad, ##__VA_ARGS__) +#define v4l2_subdev_state_get_interval(state, pad, ...) \ + __v4l2_subdev_state_constify_ret(state, \ + __v4l2_subdev_state_gen_call(interval, ##__VA_ARGS__, , _pad) \ + ((struct v4l2_subdev_state *)state, pad, ##__VA_ARGS__)) #define __v4l2_subdev_state_get_interval_pad(state, pad) \ __v4l2_subdev_state_get_interval(state, pad, 0) struct v4l2_fract * @@ -1639,6 +1687,8 @@ int v4l2_subdev_routing_validate(struct v4l2_subdev *sd, * function implements a best-effort compatibility by calling the .s_stream() * operation, limited to subdevs that have a single source pad. * + * Drivers that are not stream-aware shall set @streams_mask to BIT_ULL(0). + * * Return: * * 0: Success * * -EALREADY: One of the streams in streams_mask is already enabled @@ -1669,6 +1719,8 @@ int v4l2_subdev_enable_streams(struct v4l2_subdev *sd, u32 pad, * function implements a best-effort compatibility by calling the .s_stream() * operation, limited to subdevs that have a single source pad. * + * Drivers that are not stream-aware shall set @streams_mask to BIT_ULL(0). + * * Return: * * 0: Success * * -EALREADY: One of the streams in streams_mask is not enabled @@ -1725,6 +1777,46 @@ static inline void v4l2_subdev_unlock_state(struct v4l2_subdev_state *state) } /** + * v4l2_subdev_lock_states - Lock two sub-device states + * @state1: One subdevice state + * @state2: The other subdevice state + * + * Locks the state of two sub-devices. + * + * The states must be unlocked with v4l2_subdev_unlock_states() after use. + * + * This differs from calling v4l2_subdev_lock_state() on both states so that if + * the states share the same lock, the lock is acquired only once (so no + * deadlock occurs). The caller is responsible for ensuring the locks will + * always be acquired in the same order. + */ +static inline void v4l2_subdev_lock_states(struct v4l2_subdev_state *state1, + struct v4l2_subdev_state *state2) +{ + mutex_lock(state1->lock); + if (state1->lock != state2->lock) + mutex_lock(state2->lock); +} + +/** + * v4l2_subdev_unlock_states() - Unlock two sub-device states + * @state1: One subdevice state + * @state2: The other subdevice state + * + * Unlocks the state of two sub-devices. + * + * This differs from calling v4l2_subdev_unlock_state() on both states so that + * if the states share the same lock, the lock is released only once. + */ +static inline void v4l2_subdev_unlock_states(struct v4l2_subdev_state *state1, + struct v4l2_subdev_state *state2) +{ + mutex_unlock(state1->lock); + if (state1->lock != state2->lock) + mutex_unlock(state2->lock); +} + +/** * v4l2_subdev_get_unlocked_active_state() - Checks that the active subdev state * is unlocked and returns it * @sd: The subdevice @@ -1912,4 +2004,17 @@ extern const struct v4l2_subdev_ops v4l2_subdev_call_wrappers; void v4l2_subdev_notify_event(struct v4l2_subdev *sd, const struct v4l2_event *ev); +/** + * v4l2_subdev_is_streaming() - Returns if the subdevice is streaming + * @sd: The subdevice + * + * v4l2_subdev_is_streaming() tells if the subdevice is currently streaming. + * "Streaming" here means whether .s_stream() or .enable_streams() has been + * successfully called, and the streaming has not yet been disabled. + * + * If the subdevice implements .enable_streams() this function must be called + * while holding the active state lock. + */ +bool v4l2_subdev_is_streaming(struct v4l2_subdev *sd); + #endif /* _V4L2_SUBDEV_H */ |