diff options
Diffstat (limited to 'include/media')
26 files changed, 611 insertions, 699 deletions
diff --git a/include/media/cec.h b/include/media/cec.h index ffd17371302c..16b412b3131b 100644 --- a/include/media/cec.h +++ b/include/media/cec.h @@ -66,6 +66,8 @@ struct cec_data { struct list_head xfer_list; struct cec_adapter *adap; struct cec_msg msg; + u8 match_len; + u8 match_reply[5]; struct cec_fh *fh; struct delayed_work work; struct completion c; @@ -173,7 +175,7 @@ struct cec_adap_ops { * case the transmit will finish, but will not retransmit * and be marked as ABORTED. * @xfer_timeout_ms: the transfer timeout in ms. - * If 0, then timeout after 2.1 ms. + * If 0, then timeout after 2100 ms. * @kthread_config: kthread used to configure a CEC adapter * @config_completion: used to signal completion of the config kthread * @kthread: main CEC processing thread @@ -187,6 +189,7 @@ struct cec_adap_ops { * in order to transmit or receive CEC messages. This is usually a HW * limitation. * @is_enabled: the CEC adapter is enabled + * @is_claiming_log_addrs: true if cec_claim_log_addrs() is running * @is_configuring: the CEC adapter is configuring (i.e. claiming LAs) * @must_reconfigure: while configuring, the PA changed, so reclaim LAs * @is_configured: the CEC adapter is configured (i.e. has claimed LAs) @@ -207,12 +210,23 @@ struct cec_adap_ops { * passthrough mode. * @log_addrs: current logical addresses * @conn_info: current connector info - * @tx_timeouts: number of transmit timeouts + * @tx_timeout_cnt: count the number of Timed Out transmits. + * Reset to 0 when this is reported in cec_adap_status(). + * @tx_low_drive_cnt: count the number of Low Drive transmits. + * Reset to 0 when this is reported in cec_adap_status(). + * @tx_error_cnt: count the number of Error transmits. + * Reset to 0 when this is reported in cec_adap_status(). + * @tx_arb_lost_cnt: count the number of Arb Lost transmits. + * Reset to 0 when this is reported in cec_adap_status(). + * @tx_low_drive_log_cnt: number of logged Low Drive transmits since the + * adapter was enabled. Used to avoid flooding the kernel + * log if this happens a lot. + * @tx_error_log_cnt: number of logged Error transmits since the adapter was + * enabled. Used to avoid flooding the kernel log if this + * happens a lot. * @notifier: CEC notifier * @pin: CEC pin status struct * @cec_dir: debugfs cec directory - * @status_file: debugfs cec status file - * @error_inj_file: debugfs cec error injection file * @sequence: transmit sequence counter * @input_phys: remote control input_phys name * @@ -263,7 +277,12 @@ struct cec_adapter { struct cec_log_addrs log_addrs; struct cec_connector_info conn_info; - u32 tx_timeouts; + u32 tx_timeout_cnt; + u32 tx_low_drive_cnt; + u32 tx_error_cnt; + u32 tx_arb_lost_cnt; + u32 tx_low_drive_log_cnt; + u32 tx_error_log_cnt; #ifdef CONFIG_CEC_NOTIFIER struct cec_notifier *notifier; @@ -276,9 +295,40 @@ struct cec_adapter { u32 sequence; - char input_phys[32]; + char input_phys[40]; }; +static inline int cec_get_device(struct cec_adapter *adap) +{ + struct cec_devnode *devnode = &adap->devnode; + + /* + * Check if the cec device is available. This needs to be done with + * the devnode->lock held to prevent an open/unregister race: + * without the lock, the device could be unregistered and freed between + * the devnode->registered check and get_device() calls, leading to + * a crash. + */ + mutex_lock(&devnode->lock); + /* + * return ENODEV if the cec device has been removed + * already or if it is not registered anymore. + */ + if (!devnode->registered) { + mutex_unlock(&devnode->lock); + return -ENODEV; + } + /* and increase the device refcount */ + get_device(&devnode->dev); + mutex_unlock(&devnode->lock); + return 0; +} + +static inline void cec_put_device(struct cec_adapter *adap) +{ + put_device(&adap->devnode.dev); +} + static inline void *cec_get_drvdata(const struct cec_adapter *adap) { return adap->priv; diff --git a/include/media/ipu-bridge.h b/include/media/ipu-bridge.h index 783bda6d5cc3..16fac765456e 100644 --- a/include/media/ipu-bridge.h +++ b/include/media/ipu-bridge.h @@ -3,6 +3,7 @@ #ifndef __IPU_BRIDGE_H #define __IPU_BRIDGE_H +#include <linux/mod_devicetable.h> #include <linux/property.h> #include <linux/types.h> #include <media/v4l2-fwnode.h> diff --git a/include/media/ipu6-pci-table.h b/include/media/ipu6-pci-table.h new file mode 100644 index 000000000000..0899d9d2f978 --- /dev/null +++ b/include/media/ipu6-pci-table.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2024 Intel Corporation + */ + +#ifndef __IPU6_PCI_TBL_H__ +#define __IPU6_PCI_TBL_H__ + +#include <linux/pci.h> + +#define PCI_DEVICE_ID_INTEL_IPU6 0x9a19 +#define PCI_DEVICE_ID_INTEL_IPU6SE 0x4e19 +#define PCI_DEVICE_ID_INTEL_IPU6EP_ADLP 0x465d +#define PCI_DEVICE_ID_INTEL_IPU6EP_ADLN 0x462e +#define PCI_DEVICE_ID_INTEL_IPU6EP_RPLP 0xa75d +#define PCI_DEVICE_ID_INTEL_IPU6EP_MTL 0x7d19 + +static const struct pci_device_id ipu6_pci_tbl[] = { + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IPU6) }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IPU6SE) }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IPU6EP_ADLP) }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IPU6EP_ADLN) }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IPU6EP_RPLP) }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IPU6EP_MTL) }, + { } +}; + +#endif /* __IPU6_PCI_TBL_H__ */ diff --git a/include/media/media-device.h b/include/media/media-device.h index 2c146d0b2b1c..53d2a16a70b0 100644 --- a/include/media/media-device.h +++ b/include/media/media-device.h @@ -429,6 +429,9 @@ void __media_device_usb_init(struct media_device *mdev, const char *driver_name); #else +static inline void media_device_init(struct media_device *mdev) +{ +} static inline int media_device_register(struct media_device *mdev) { return 0; @@ -436,6 +439,9 @@ static inline int media_device_register(struct media_device *mdev) static inline void media_device_unregister(struct media_device *mdev) { } +static inline void media_device_cleanup(struct media_device *mdev) +{ +} static inline int media_device_register_entity(struct media_device *mdev, struct media_entity *entity) { diff --git a/include/media/media-entity.h b/include/media/media-entity.h index 4d95893c8984..0393b23129eb 100644 --- a/include/media/media-entity.h +++ b/include/media/media-entity.h @@ -339,10 +339,6 @@ enum media_entity_type { * @info.dev: Contains device major and minor info. * @info.dev.major: device node major, if the device is a devnode. * @info.dev.minor: device node minor, if the device is a devnode. - * @major: Devnode major number (zero if not applicable). Kept just - * for backward compatibility. - * @minor: Devnode minor number (zero if not applicable). Kept just - * for backward compatibility. * * .. note:: * diff --git a/include/media/mipi-csi2.h b/include/media/mipi-csi2.h index c3d8f12234b1..40fc0264250d 100644 --- a/include/media/mipi-csi2.h +++ b/include/media/mipi-csi2.h @@ -19,6 +19,7 @@ #define MIPI_CSI2_DT_NULL 0x10 #define MIPI_CSI2_DT_BLANKING 0x11 #define MIPI_CSI2_DT_EMBEDDED_8B 0x12 +#define MIPI_CSI2_DT_GENERIC_LONG(n) (0x13 + (n) - 1) /* 1..4 */ #define MIPI_CSI2_DT_YUV420_8B 0x18 #define MIPI_CSI2_DT_YUV420_10B 0x19 #define MIPI_CSI2_DT_YUV420_8B_LEGACY 0x1a diff --git a/include/media/rc-core.h b/include/media/rc-core.h index 803349599c27..d095908073ef 100644 --- a/include/media/rc-core.h +++ b/include/media/rc-core.h @@ -127,7 +127,6 @@ struct lirc_fh { * @min_timeout: minimum timeout supported by device * @max_timeout: maximum timeout supported by device * @rx_resolution : resolution (in us) of input sampler - * @tx_resolution: resolution (in us) of output sampler * @lirc_dev: lirc device * @lirc_cdev: lirc char cdev * @gap_start: start time for gap after timeout if non-zero @@ -194,7 +193,6 @@ struct rc_dev { u32 min_timeout; u32 max_timeout; u32 rx_resolution; - u32 tx_resolution; #ifdef CONFIG_LIRC struct device lirc_dev; struct cdev lirc_cdev; diff --git a/include/media/rc-map.h b/include/media/rc-map.h index 4676545ffd8f..4867eb2f931e 100644 --- a/include/media/rc-map.h +++ b/include/media/rc-map.h @@ -290,6 +290,7 @@ struct rc_map *rc_map_get(const char *name); #define RC_MAP_MSI_DIGIVOX_III "rc-msi-digivox-iii" #define RC_MAP_MSI_TVANYWHERE "rc-msi-tvanywhere" #define RC_MAP_MSI_TVANYWHERE_PLUS "rc-msi-tvanywhere-plus" +#define RC_MAP_MYGICA_UTV3 "rc-mygica-utv3" #define RC_MAP_NEBULA "rc-nebula" #define RC_MAP_NEC_TERRATEC_CINERGY_XS "rc-nec-terratec-cinergy-xs" #define RC_MAP_NORWOOD "rc-norwood" diff --git a/include/media/tuner.h b/include/media/tuner.h index a7796e0a3659..c5fd6faabfd6 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -133,6 +133,7 @@ #define TUNER_SONY_BTF_PK467Z 90 /* NTSC_JP */ #define TUNER_SONY_BTF_PB463Z 91 /* NTSC */ #define TUNER_SI2157 92 +#define TUNER_TENA_TNF_931D_DFDR1 93 /* tv card specific */ #define TDA9887_PRESENT (1<<0) diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h index 9bd326d31181..f26c323e9c96 100644 --- a/include/media/v4l2-async.h +++ b/include/media/v4l2-async.h @@ -310,7 +310,9 @@ void v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier); * * @sd: pointer to &struct v4l2_subdev */ -int v4l2_async_register_subdev(struct v4l2_subdev *sd); +#define v4l2_async_register_subdev(sd) \ + __v4l2_async_register_subdev(sd, THIS_MODULE) +int __v4l2_async_register_subdev(struct v4l2_subdev *sd, struct module *module); /** * v4l2_async_register_subdev_sensor - registers a sensor sub-device to the diff --git a/include/media/v4l2-cci.h b/include/media/v4l2-cci.h index 8b0b361b464c..4e96e90ee636 100644 --- a/include/media/v4l2-cci.h +++ b/include/media/v4l2-cci.h @@ -34,6 +34,11 @@ struct cci_reg_sequence { #define CCI_REG_ADDR_MASK GENMASK(15, 0) #define CCI_REG_WIDTH_SHIFT 16 #define CCI_REG_WIDTH_MASK GENMASK(19, 16) +/* + * Private CCI register flags, for the use of drivers. + */ +#define CCI_REG_PRIVATE_SHIFT 28U +#define CCI_REG_PRIVATE_MASK GENMASK(31U, CCI_REG_PRIVATE_SHIFT) #define CCI_REG_WIDTH_BYTES(x) FIELD_GET(CCI_REG_WIDTH_MASK, x) #define CCI_REG_WIDTH(x) (CCI_REG_WIDTH_BYTES(x) << 3) diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index d278836fd9cb..63ad36f04f72 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -278,13 +278,13 @@ static inline void v4l2_i2c_subdev_unregister(struct v4l2_subdev *sd) * * * @v4l2_dev: pointer to &struct v4l2_device. - * @master: pointer to struct spi_master. + * @ctlr: pointer to struct spi_controller. * @info: pointer to struct spi_board_info. * * returns a &struct v4l2_subdev pointer. */ struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev, - struct spi_master *master, struct spi_board_info *info); + struct spi_controller *ctlr, struct spi_board_info *info); /** * v4l2_spi_subdev_init - Initialize a v4l2_subdev with data from an @@ -308,7 +308,7 @@ void v4l2_spi_subdev_unregister(struct v4l2_subdev *sd); static inline struct v4l2_subdev * v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev, - struct spi_master *master, struct spi_board_info *info) + struct spi_controller *ctlr, struct spi_board_info *info) { return NULL; } @@ -425,7 +425,7 @@ __v4l2_find_nearest_size(const void *array, size_t array_size, /** * v4l2_g_parm_cap - helper routine for vidioc_g_parm to fill this in by - * calling the g_frame_interval op of the given subdev. It only works + * calling the get_frame_interval op of the given subdev. It only works * for V4L2_BUF_TYPE_VIDEO_CAPTURE(_MPLANE), hence the _cap in the * function name. * @@ -438,7 +438,7 @@ int v4l2_g_parm_cap(struct video_device *vdev, /** * v4l2_s_parm_cap - helper routine for vidioc_s_parm to fill this in by - * calling the s_frame_interval op of the given subdev. It only works + * calling the set_frame_interval op of the given subdev. It only works * for V4L2_BUF_TYPE_VIDEO_CAPTURE(_MPLANE), hence the _cap in the * function name. * @@ -536,9 +536,10 @@ int v4l2_fill_pixfmt_mp(struct v4l2_pix_format_mplane *pixfmt, u32 pixelformat, * V4L2_CID_LINK_FREQ control implemented by the transmitter, or value * calculated based on the V4L2_CID_PIXEL_RATE implemented by the transmitter. * - * Returns link frequency on success, otherwise a negative error code: - * -ENOENT: Link frequency or pixel rate control not found - * -EINVAL: Invalid link frequency value + * Return: + * * >0: Link frequency + * * %-ENOENT: Link frequency or pixel rate control not found + * * %-EINVAL: Invalid link frequency value */ s64 v4l2_get_link_freq(struct v4l2_ctrl_handler *handler, unsigned int mul, unsigned int div); @@ -547,6 +548,31 @@ void v4l2_simplify_fraction(u32 *numerator, u32 *denominator, unsigned int n_terms, unsigned int threshold); u32 v4l2_fraction_to_interval(u32 numerator, u32 denominator); +/** + * v4l2_link_freq_to_bitmap - Figure out platform-supported link frequencies + * @dev: The struct device + * @fw_link_freqs: Array of link frequencies from firmware + * @num_of_fw_link_freqs: Number of entries in @fw_link_freqs + * @driver_link_freqs: Array of link frequencies supported by the driver + * @num_of_driver_link_freqs: Number of entries in @driver_link_freqs + * @bitmap: Bitmap of driver-supported link frequencies found in @fw_link_freqs + * + * This function checks which driver-supported link frequencies are enabled in + * system firmware and sets the corresponding bits in @bitmap (after first + * zeroing it). + * + * Return: + * * %0: Success + * * %-ENOENT: No match found between driver-supported link frequencies and + * those available in firmware. + * * %-ENODATA: No link frequencies were specified in firmware. + */ +int v4l2_link_freq_to_bitmap(struct device *dev, const u64 *fw_link_freqs, + unsigned int num_of_fw_link_freqs, + const s64 *driver_link_freqs, + unsigned int num_of_driver_link_freqs, + unsigned long *bitmap); + static inline u64 v4l2_buffer_get_timestamp(const struct v4l2_buffer *buf) { /* diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index e0a13505f88d..d82dfdbf6e58 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -284,7 +284,7 @@ struct video_device { struct v4l2_prio_state *prio; /* device info */ - char name[32]; + char name[64]; enum vfl_devnode_type vfl_type; enum vfl_devnode_direction vfl_dir; int minor; diff --git a/include/media/v4l2-device.h b/include/media/v4l2-device.h index 8a8977a33ec1..dd897a362f36 100644 --- a/include/media/v4l2-device.h +++ b/include/media/v4l2-device.h @@ -13,8 +13,6 @@ #include <media/v4l2-subdev.h> #include <media/v4l2-dev.h> -#define V4L2_DEVICE_NAME_SIZE (20 + 16) - struct v4l2_ctrl_handler; /** @@ -49,7 +47,7 @@ struct v4l2_device { struct media_device *mdev; struct list_head subdevs; spinlock_t lock; - char name[V4L2_DEVICE_NAME_SIZE]; + char name[36]; void (*notify)(struct v4l2_subdev *sd, unsigned int notification, void *arg); struct v4l2_ctrl_handler *ctrl_handler; @@ -158,8 +156,11 @@ void v4l2_device_unregister(struct v4l2_device *v4l2_dev); * An error is returned if the module is no longer loaded on any attempts * to register it. */ -int __must_check v4l2_device_register_subdev(struct v4l2_device *v4l2_dev, - struct v4l2_subdev *sd); +#define v4l2_device_register_subdev(v4l2_dev, sd) \ + __v4l2_device_register_subdev(v4l2_dev, sd, THIS_MODULE) +int __must_check __v4l2_device_register_subdev(struct v4l2_device *v4l2_dev, + struct v4l2_subdev *sd, + struct module *module); /** * v4l2_device_unregister_subdev - Unregisters a subdev with a v4l2 device. diff --git a/include/media/v4l2-event.h b/include/media/v4l2-event.h index 4ffa914ade3a..3a0e2588361c 100644 --- a/include/media/v4l2-event.h +++ b/include/media/v4l2-event.h @@ -78,7 +78,7 @@ struct v4l2_subscribed_event { unsigned int elems; unsigned int first; unsigned int in_use; - struct v4l2_kevent events[]; + struct v4l2_kevent events[] __counted_by(elems); }; /** diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h index edb733f21604..bdbb7e542321 100644 --- a/include/media/v4l2-ioctl.h +++ b/include/media/v4l2-ioctl.h @@ -163,6 +163,8 @@ struct v4l2_fh; * :ref:`VIDIOC_CREATE_BUFS <vidioc_create_bufs>` ioctl * @vidioc_prepare_buf: pointer to the function that implements * :ref:`VIDIOC_PREPARE_BUF <vidioc_prepare_buf>` ioctl + * @vidioc_remove_bufs: pointer to the function that implements + * :ref:`VIDIOC_REMOVE_BUFS <vidioc_remove_bufs>` ioctl * @vidioc_overlay: pointer to the function that implements * :ref:`VIDIOC_OVERLAY <vidioc_overlay>` ioctl * @vidioc_g_fbuf: pointer to the function that implements @@ -422,6 +424,8 @@ struct v4l2_ioctl_ops { struct v4l2_create_buffers *b); int (*vidioc_prepare_buf)(struct file *file, void *fh, struct v4l2_buffer *b); + int (*vidioc_remove_bufs)(struct file *file, void *fh, + struct v4l2_remove_buffers *d); int (*vidioc_overlay)(struct file *file, void *fh, unsigned int i); int (*vidioc_g_fbuf)(struct file *file, void *fh, diff --git a/include/media/v4l2-jpeg.h b/include/media/v4l2-jpeg.h index 2dba843ce3bd..b65658a02e3c 100644 --- a/include/media/v4l2-jpeg.h +++ b/include/media/v4l2-jpeg.h @@ -14,6 +14,30 @@ #define V4L2_JPEG_MAX_COMPONENTS 4 #define V4L2_JPEG_MAX_TABLES 4 +/* + * Prefixes used to generate huffman table class and destination identifiers as + * described below: + * + * V4L2_JPEG_LUM_HT | V4L2_JPEG_DC_HT : Prefix for Luma DC coefficients + * huffman table + * V4L2_JPEG_LUM_HT | V4L2_JPEG_AC_HT : Prefix for Luma AC coefficients + * huffman table + * V4L2_JPEG_CHR_HT | V4L2_JPEG_DC_HT : Prefix for Chroma DC coefficients + * huffman table + * V4L2_JPEG_CHR_HT | V4L2_JPEG_AC_HT : Prefix for Chroma AC coefficients + * huffman table + */ +#define V4L2_JPEG_LUM_HT 0x00 +#define V4L2_JPEG_CHR_HT 0x01 +#define V4L2_JPEG_DC_HT 0x00 +#define V4L2_JPEG_AC_HT 0x10 + +/* Length of reference huffman tables as provided in Table K.3 of ITU-T.81 */ +#define V4L2_JPEG_REF_HT_AC_LEN 178 +#define V4L2_JPEG_REF_HT_DC_LEN 28 + +/* Array size for 8x8 block of samples or DCT coefficient */ +#define V4L2_JPEG_PIXELS_IN_BLOCK 64 /** * struct v4l2_jpeg_reference - reference into the JPEG buffer @@ -154,4 +178,12 @@ int v4l2_jpeg_parse_quantization_tables(void *buf, size_t len, u8 precision, int v4l2_jpeg_parse_huffman_tables(void *buf, size_t len, struct v4l2_jpeg_reference *huffman_tables); +extern const u8 v4l2_jpeg_zigzag_scan_index[V4L2_JPEG_PIXELS_IN_BLOCK]; +extern const u8 v4l2_jpeg_ref_table_luma_qt[V4L2_JPEG_PIXELS_IN_BLOCK]; +extern const u8 v4l2_jpeg_ref_table_chroma_qt[V4L2_JPEG_PIXELS_IN_BLOCK]; +extern const u8 v4l2_jpeg_ref_table_luma_dc_ht[V4L2_JPEG_REF_HT_DC_LEN]; +extern const u8 v4l2_jpeg_ref_table_luma_ac_ht[V4L2_JPEG_REF_HT_AC_LEN]; +extern const u8 v4l2_jpeg_ref_table_chroma_dc_ht[V4L2_JPEG_REF_HT_DC_LEN]; +extern const u8 v4l2_jpeg_ref_table_chroma_ac_ht[V4L2_JPEG_REF_HT_AC_LEN]; + #endif diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h index b39586dfba35..1837c9fd78cf 100644 --- a/include/media/v4l2-mc.h +++ b/include/media/v4l2-mc.h @@ -143,6 +143,9 @@ int v4l2_create_fwnode_links(struct v4l2_subdev *src_sd, * v4l2_pipeline_pm_get - Increase the use count of a pipeline * @entity: The root entity of a pipeline * + * THIS FUNCTION IS DEPRECATED. DO NOT USE IN NEW DRIVERS. USE RUNTIME PM + * ON SUB-DEVICE DRIVERS INSTEAD. + * * Update the use count of all entities in the pipeline and power entities on. * * This function is intended to be called in video node open. It uses @@ -157,6 +160,9 @@ int v4l2_pipeline_pm_get(struct media_entity *entity); * v4l2_pipeline_pm_put - Decrease the use count of a pipeline * @entity: The root entity of a pipeline * + * THIS FUNCTION IS DEPRECATED. DO NOT USE IN NEW DRIVERS. USE RUNTIME PM + * ON SUB-DEVICE DRIVERS INSTEAD. + * * Update the use count of all entities in the pipeline and power entities off. * * This function is intended to be called in video node release. It uses @@ -172,6 +178,9 @@ void v4l2_pipeline_pm_put(struct media_entity *entity); * @flags: New link flags that will be applied * @notification: The link's state change notification type (MEDIA_DEV_NOTIFY_*) * + * THIS FUNCTION IS DEPRECATED. DO NOT USE IN NEW DRIVERS. USE RUNTIME PM + * ON SUB-DEVICE DRIVERS INSTEAD. + * * React to link management on powered pipelines by updating the use count of * all entities in the source and sink sides of the link. Entities are powered * on or off accordingly. The use of this function should be paired diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h index d6c8eb2b5201..0af330cf91c3 100644 --- a/include/media/v4l2-mem2mem.h +++ b/include/media/v4l2-mem2mem.h @@ -84,6 +84,12 @@ struct v4l2_m2m_queue_ctx { * @last_src_buf: indicate the last source buffer for draining * @next_buf_last: next capture queud buffer will be tagged as last * @has_stopped: indicate the device has been stopped + * @ignore_cap_streaming: If true, job_ready can be called even if the CAPTURE + * queue is not streaming. This allows firmware to + * analyze the bitstream header which arrives on the + * OUTPUT queue. The driver must implement the job_ready + * callback correctly to make sure that the requirements + * for actual decoding are met. * @m2m_dev: opaque pointer to the internal data to handle M2M context * @cap_q_ctx: Capture (output to memory) queue context * @out_q_ctx: Output (input from memory) queue context @@ -106,6 +112,7 @@ struct v4l2_m2m_ctx { struct vb2_v4l2_buffer *last_src_buf; bool next_buf_last; bool has_stopped; + bool ignore_cap_streaming; /* internal use only */ struct v4l2_m2m_dev *m2m_dev; @@ -661,7 +668,7 @@ v4l2_m2m_next_dst_buf(struct v4l2_m2m_ctx *m2m_ctx) struct vb2_v4l2_buffer *v4l2_m2m_last_buf(struct v4l2_m2m_queue_ctx *q_ctx); /** - * v4l2_m2m_last_src_buf() - return last destination buffer from the list of + * v4l2_m2m_last_src_buf() - return last source buffer from the list of * ready buffers * * @m2m_ctx: m2m context assigned to the instance given by struct &v4l2_m2m_ctx @@ -860,6 +867,8 @@ int v4l2_m2m_ioctl_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *rb); int v4l2_m2m_ioctl_create_bufs(struct file *file, void *fh, struct v4l2_create_buffers *create); +int v4l2_m2m_ioctl_remove_bufs(struct file *file, void *priv, + struct v4l2_remove_buffers *d); int v4l2_m2m_ioctl_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf); int v4l2_m2m_ioctl_expbuf(struct file *file, void *fh, diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index ab2a7ef61d42..43343f1586d1 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -450,21 +450,16 @@ 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. - * - * @g_frame_interval: callback for VIDIOC_SUBDEV_G_FRAME_INTERVAL() - * ioctl handler code. - * - * @s_frame_interval: callback for VIDIOC_SUBDEV_S_FRAME_INTERVAL() - * 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. + * 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 @@ -496,16 +491,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 (*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 (*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); @@ -688,21 +673,16 @@ struct v4l2_subdev_ir_ops { /** * struct v4l2_subdev_pad_config - Used for storing subdev pad information. * - * @try_fmt: &struct v4l2_mbus_framefmt - * @try_crop: &struct v4l2_rect to be used for crop - * @try_compose: &struct v4l2_rect to be used for compose - * - * This structure only needs to be passed to the pad op if the 'which' field - * of the main argument is set to %V4L2_SUBDEV_FORMAT_TRY. For - * %V4L2_SUBDEV_FORMAT_ACTIVE it is safe to pass %NULL. - * - * Note: This struct is also used in active state, and the 'try' prefix is - * historical and to be removed. + * @format: &struct v4l2_mbus_framefmt + * @crop: &struct v4l2_rect to be used for crop + * @compose: &struct v4l2_rect to be used for compose + * @interval: frame interval */ struct v4l2_subdev_pad_config { - struct v4l2_mbus_framefmt try_fmt; - struct v4l2_rect try_crop; - struct v4l2_rect try_compose; + struct v4l2_mbus_framefmt format; + struct v4l2_rect crop; + struct v4l2_rect compose; + struct v4l2_fract interval; }; /** @@ -710,10 +690,11 @@ 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 + * @interval: frame interval * * This structure stores configuration for a stream. */ @@ -725,6 +706,7 @@ struct v4l2_subdev_stream_config { struct v4l2_mbus_framefmt fmt; struct v4l2_rect crop; struct v4l2_rect compose; + struct v4l2_fract interval; }; /** @@ -741,12 +723,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; }; @@ -756,6 +740,7 @@ struct v4l2_subdev_krouting { * * @_lock: default for 'lock' * @lock: mutex for the state. May be replaced by the user. + * @sd: the sub-device which the state is related to * @pads: &struct v4l2_subdev_pad_config array * @routing: routing table for the subdev * @stream_configs: stream configurations (only for V4L2_SUBDEV_FL_STREAMS) @@ -768,6 +753,7 @@ struct v4l2_subdev_state { /* lock for the struct v4l2_subdev_state fields */ struct mutex _lock; struct mutex *lock; + struct v4l2_subdev *sd; struct v4l2_subdev_pad_config *pads; struct v4l2_subdev_krouting routing; struct v4l2_subdev_stream_configs stream_configs; @@ -776,7 +762,6 @@ struct v4l2_subdev_state { /** * struct v4l2_subdev_pad_ops - v4l2-subdev pad level operations * - * @init_cfg: initialize the pad config to default values * @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 @@ -793,10 +778,24 @@ struct v4l2_subdev_state { * * @set_selection: callback for VIDIOC_SUBDEV_S_SELECTION() ioctl handler code. * + * @get_frame_interval: callback for VIDIOC_SUBDEV_G_FRAME_INTERVAL() + * ioctl handler code. + * + * @set_frame_interval: callback for VIDIOC_SUBDEV_S_FRAME_INTERVAL() + * 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. * + * @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. * @@ -822,10 +821,13 @@ 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. + * @set_routing: Enable or disable data connection routes described in the + * subdevice routing table. Subdevs that implement this operation + * must set the V4L2_SUBDEV_FL_STREAMS flag. * * @enable_streams: Enable the streams defined in streams_mask on the given * source pad. Subdevs that implement this operation must use the active @@ -840,8 +842,6 @@ struct v4l2_subdev_state { * directly, use v4l2_subdev_disable_streams() instead. */ struct v4l2_subdev_pad_ops { - int (*init_cfg)(struct v4l2_subdev *sd, - struct v4l2_subdev_state *state); int (*enum_mbus_code)(struct v4l2_subdev *sd, struct v4l2_subdev_state *state, struct v4l2_subdev_mbus_code_enum *code); @@ -863,8 +863,20 @@ struct v4l2_subdev_pad_ops { int (*set_selection)(struct v4l2_subdev *sd, struct v4l2_subdev_state *state, struct v4l2_subdev_selection *sel); + int (*get_frame_interval)(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_frame_interval *interval); + int (*set_frame_interval)(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + 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, @@ -918,6 +930,8 @@ struct v4l2_subdev_ops { /** * struct v4l2_subdev_internal_ops - V4L2 subdev internal ops * + * @init_state: initialize the subdev state to default values + * * @registered: called when this subdev is registered. When called the v4l2_dev * field is set to the correct v4l2_device. * @@ -943,6 +957,8 @@ struct v4l2_subdev_ops { * these ops. */ struct v4l2_subdev_internal_ops { + int (*init_state)(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state); int (*registered)(struct v4l2_subdev *sd); void (*unregistered)(struct v4l2_subdev *sd); int (*open)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh); @@ -950,8 +966,6 @@ struct v4l2_subdev_internal_ops { void (*release)(struct v4l2_subdev *sd); }; -#define V4L2_SUBDEV_NAME_SIZE 32 - /* Set this flag if this subdev is a i2c device. */ #define V4L2_SUBDEV_FL_IS_I2C (1U << 0) /* Set this flag if this subdev is a spi device. */ @@ -1038,10 +1052,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. @@ -1061,7 +1076,7 @@ struct v4l2_subdev { const struct v4l2_subdev_ops *ops; const struct v4l2_subdev_internal_ops *internal_ops; struct v4l2_ctrl_handler *ctrl_handler; - char name[V4L2_SUBDEV_NAME_SIZE]; + char name[52]; u32 grp_id; void *dev_priv; void *host_priv; @@ -1089,7 +1104,8 @@ struct v4l2_subdev { * doesn't support it. */ struct v4l2_subdev_state *active_state; - u64 enabled_streams; + u64 enabled_pads; + bool s_stream_enabled; }; @@ -1143,83 +1159,6 @@ struct v4l2_subdev_fh { #define to_v4l2_subdev_fh(fh) \ container_of(fh, struct v4l2_subdev_fh, vfh) -#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) - -/** - * v4l2_subdev_get_pad_format - ancillary routine to call - * &struct v4l2_subdev_pad_config->try_fmt - * - * @sd: pointer to &struct v4l2_subdev - * @state: pointer to &struct v4l2_subdev_state - * @pad: index of the pad in the &struct v4l2_subdev_state->pads array - */ -static inline struct v4l2_mbus_framefmt * -v4l2_subdev_get_pad_format(struct v4l2_subdev *sd, - struct v4l2_subdev_state *state, - unsigned int pad) -{ - if (WARN_ON(!state)) - return NULL; - if (WARN_ON(pad >= sd->entity.num_pads)) - pad = 0; - return &state->pads[pad].try_fmt; -} - -/** - * v4l2_subdev_get_pad_crop - ancillary routine to call - * &struct v4l2_subdev_pad_config->try_crop - * - * @sd: pointer to &struct v4l2_subdev - * @state: pointer to &struct v4l2_subdev_state. - * @pad: index of the pad in the &struct v4l2_subdev_state->pads array. - */ -static inline struct v4l2_rect * -v4l2_subdev_get_pad_crop(struct v4l2_subdev *sd, - struct v4l2_subdev_state *state, - unsigned int pad) -{ - if (WARN_ON(!state)) - return NULL; - if (WARN_ON(pad >= sd->entity.num_pads)) - pad = 0; - return &state->pads[pad].try_crop; -} - -/** - * v4l2_subdev_get_pad_compose - ancillary routine to call - * &struct v4l2_subdev_pad_config->try_compose - * - * @sd: pointer to &struct v4l2_subdev - * @state: pointer to &struct v4l2_subdev_state. - * @pad: index of the pad in the &struct v4l2_subdev_state->pads array. - */ -static inline struct v4l2_rect * -v4l2_subdev_get_pad_compose(struct v4l2_subdev *sd, - struct v4l2_subdev_state *state, - unsigned int pad) -{ - if (WARN_ON(!state)) - return NULL; - if (WARN_ON(pad >= sd->entity.num_pads)) - pad = 0; - return &state->pads[pad].try_compose; -} - -/* - * Temprary helpers until uses of v4l2_subdev_get_try_* functions have been - * renamed - */ -#define v4l2_subdev_get_try_format(sd, state, pad) \ - v4l2_subdev_get_pad_format(sd, state, pad) - -#define v4l2_subdev_get_try_crop(sd, state, pad) \ - v4l2_subdev_get_pad_crop(sd, state, pad) - -#define v4l2_subdev_get_try_compose(sd, state, pad) \ - v4l2_subdev_get_pad_compose(sd, state, pad) - -#endif /* CONFIG_VIDEO_V4L2_SUBDEV_API */ - extern const struct v4l2_file_operations v4l2_subdev_fops; /** @@ -1313,6 +1252,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); @@ -1393,88 +1338,123 @@ int __v4l2_subdev_init_finalize(struct v4l2_subdev *sd, const char *name, */ void v4l2_subdev_cleanup(struct v4l2_subdev *sd); -/** - * v4l2_subdev_lock_state() - Locks the subdev state - * @state: The subdevice state - * - * Locks the given subdev state. - * - * The state must be unlocked with v4l2_subdev_unlock_state() after use. +/* + * A macro to generate the macro or function name for sub-devices state access + * wrapper macros below. */ -static inline void v4l2_subdev_lock_state(struct v4l2_subdev_state *state) -{ - mutex_lock(state->lock); -} +#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_unlock_state() - Unlocks the subdev state - * @state: The subdevice state + * v4l2_subdev_state_get_format() - Get pointer to a stream format + * @state: subdevice state + * @pad: pad id + * @...: stream id (optional argument) * - * Unlocks the given subdev state. + * This returns a pointer to &struct v4l2_mbus_framefmt for the given pad + + * stream in the subdev state. + * + * For stream-unaware drivers the format for the corresponding pad is returned. + * If the pad does not exist, NULL is returned. */ -static inline void v4l2_subdev_unlock_state(struct v4l2_subdev_state *state) -{ - mutex_unlock(state->lock); -} +/* + * Wrap v4l2_subdev_state_get_format(), allowing the function to be called with + * 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 * +__v4l2_subdev_state_get_format(struct v4l2_subdev_state *state, + unsigned int pad, u32 stream); /** - * v4l2_subdev_get_unlocked_active_state() - Checks that the active subdev state - * is unlocked and returns it - * @sd: The subdevice + * v4l2_subdev_state_get_crop() - Get pointer to a stream crop rectangle + * @state: subdevice state + * @pad: pad id + * @...: stream id (optional argument) * - * Returns the active state for the subdevice, or NULL if the subdev does not - * support active state. If the state is not NULL, calls - * lockdep_assert_not_held() to issue a warning if the state is locked. + * This returns a pointer to crop rectangle for the given pad + stream in the + * subdev state. * - * This function is to be used e.g. when getting the active state for the sole - * purpose of passing it forward, without accessing the state fields. + * For stream-unaware drivers the crop rectangle for the corresponding pad is + * returned. If the pad does not exist, NULL is returned. */ -static inline struct v4l2_subdev_state * -v4l2_subdev_get_unlocked_active_state(struct v4l2_subdev *sd) -{ - if (sd->active_state) - lockdep_assert_not_held(sd->active_state->lock); - return sd->active_state; -} +#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 * +__v4l2_subdev_state_get_crop(struct v4l2_subdev_state *state, unsigned int pad, + u32 stream); /** - * v4l2_subdev_get_locked_active_state() - Checks that the active subdev state - * is locked and returns it - * - * @sd: The subdevice + * v4l2_subdev_state_get_compose() - Get pointer to a stream compose rectangle + * @state: subdevice state + * @pad: pad id + * @...: stream id (optional argument) * - * Returns the active state for the subdevice, or NULL if the subdev does not - * support active state. If the state is not NULL, calls lockdep_assert_held() - * to issue a warning if the state is not locked. + * This returns a pointer to compose rectangle for the given pad + stream in the + * subdev state. * - * This function is to be used when the caller knows that the active state is - * already locked. + * For stream-unaware drivers the compose rectangle for the corresponding pad is + * returned. If the pad does not exist, NULL is returned. */ -static inline struct v4l2_subdev_state * -v4l2_subdev_get_locked_active_state(struct v4l2_subdev *sd) -{ - if (sd->active_state) - lockdep_assert_held(sd->active_state->lock); - return sd->active_state; -} +#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 * +__v4l2_subdev_state_get_compose(struct v4l2_subdev_state *state, + unsigned int pad, u32 stream); /** - * v4l2_subdev_lock_and_get_active_state() - Locks and returns the active subdev - * state for the subdevice - * @sd: The subdevice + * v4l2_subdev_state_get_interval() - Get pointer to a stream frame interval + * @state: subdevice state + * @pad: pad id + * @...: stream id (optional argument) * - * Returns the locked active state for the subdevice, or NULL if the subdev - * does not support active state. + * This returns a pointer to the frame interval for the given pad + stream in + * the subdev state. * - * The state must be unlocked with v4l2_subdev_unlock_state() after use. + * For stream-unaware drivers the frame interval for the corresponding pad is + * returned. If the pad does not exist, NULL is returned. */ -static inline struct v4l2_subdev_state * -v4l2_subdev_lock_and_get_active_state(struct v4l2_subdev *sd) -{ - if (sd->active_state) - v4l2_subdev_lock_state(sd->active_state); - return sd->active_state; -} +#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 * +__v4l2_subdev_state_get_interval(struct v4l2_subdev_state *state, + unsigned int pad, u32 stream); #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) @@ -1496,6 +1476,24 @@ int v4l2_subdev_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_state *state, struct v4l2_subdev_format *format); /** + * v4l2_subdev_get_frame_interval() - Fill frame interval based on state + * @sd: subdevice + * @state: subdevice state + * @fi: pointer to &struct v4l2_subdev_frame_interval + * + * Fill @fi->interval field based on the information in the @fi struct. + * + * This function can be used by the subdev drivers which support active state to + * implement v4l2_subdev_pad_ops.get_frame_interval if the subdev driver does + * not need to do anything special in their get_frame_interval op. + * + * Returns 0 on success, error value otherwise. + */ +int v4l2_subdev_get_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_frame_interval *fi); + +/** * v4l2_subdev_set_routing() - Set given routing to subdev state * @sd: The subdevice * @state: The subdevice state @@ -1541,52 +1539,6 @@ int v4l2_subdev_set_routing_with_fmt(struct v4l2_subdev *sd, const struct v4l2_mbus_framefmt *fmt); /** - * v4l2_subdev_state_get_stream_format() - Get pointer to a stream format - * @state: subdevice state - * @pad: pad id - * @stream: stream id - * - * This returns a pointer to &struct v4l2_mbus_framefmt for the given pad + - * stream in the subdev state. - * - * If the state does not contain the given pad + stream, NULL is returned. - */ -struct v4l2_mbus_framefmt * -v4l2_subdev_state_get_stream_format(struct v4l2_subdev_state *state, - unsigned int pad, u32 stream); - -/** - * v4l2_subdev_state_get_stream_crop() - Get pointer to a stream crop rectangle - * @state: subdevice state - * @pad: pad id - * @stream: stream id - * - * This returns a pointer to crop rectangle for the given pad + stream in the - * subdev state. - * - * If the state does not contain the given pad + stream, NULL is returned. - */ -struct v4l2_rect * -v4l2_subdev_state_get_stream_crop(struct v4l2_subdev_state *state, - unsigned int pad, u32 stream); - -/** - * v4l2_subdev_state_get_stream_compose() - Get pointer to a stream compose - * rectangle - * @state: subdevice state - * @pad: pad id - * @stream: stream id - * - * This returns a pointer to compose rectangle for the given pad + stream in the - * subdev state. - * - * If the state does not contain the given pad + stream, NULL is returned. - */ -struct v4l2_rect * -v4l2_subdev_state_get_stream_compose(struct v4l2_subdev_state *state, - unsigned int pad, u32 stream); - -/** * v4l2_subdev_routing_find_opposite_end() - Find the opposite stream * @routing: routing used to find the opposite side * @pad: pad id @@ -1788,6 +1740,129 @@ int v4l2_subdev_s_stream_helper(struct v4l2_subdev *sd, int enable); #endif /* CONFIG_MEDIA_CONTROLLER */ /** + * v4l2_subdev_lock_state() - Locks the subdev state + * @state: The subdevice state + * + * Locks the given subdev state. + * + * The state must be unlocked with v4l2_subdev_unlock_state() after use. + */ +static inline void v4l2_subdev_lock_state(struct v4l2_subdev_state *state) +{ + mutex_lock(state->lock); +} + +/** + * v4l2_subdev_unlock_state() - Unlocks the subdev state + * @state: The subdevice state + * + * Unlocks the given subdev state. + */ +static inline void v4l2_subdev_unlock_state(struct v4l2_subdev_state *state) +{ + mutex_unlock(state->lock); +} + +/** + * 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 + * + * Returns the active state for the subdevice, or NULL if the subdev does not + * support active state. If the state is not NULL, calls + * lockdep_assert_not_held() to issue a warning if the state is locked. + * + * This function is to be used e.g. when getting the active state for the sole + * purpose of passing it forward, without accessing the state fields. + */ +static inline struct v4l2_subdev_state * +v4l2_subdev_get_unlocked_active_state(struct v4l2_subdev *sd) +{ + if (sd->active_state) + lockdep_assert_not_held(sd->active_state->lock); + return sd->active_state; +} + +/** + * v4l2_subdev_get_locked_active_state() - Checks that the active subdev state + * is locked and returns it + * + * @sd: The subdevice + * + * Returns the active state for the subdevice, or NULL if the subdev does not + * support active state. If the state is not NULL, calls lockdep_assert_held() + * to issue a warning if the state is not locked. + * + * This function is to be used when the caller knows that the active state is + * already locked. + */ +static inline struct v4l2_subdev_state * +v4l2_subdev_get_locked_active_state(struct v4l2_subdev *sd) +{ + if (sd->active_state) + lockdep_assert_held(sd->active_state->lock); + return sd->active_state; +} + +/** + * v4l2_subdev_lock_and_get_active_state() - Locks and returns the active subdev + * state for the subdevice + * @sd: The subdevice + * + * Returns the locked active state for the subdevice, or NULL if the subdev + * does not support active state. + * + * The state must be unlocked with v4l2_subdev_unlock_state() after use. + */ +static inline struct v4l2_subdev_state * +v4l2_subdev_lock_and_get_active_state(struct v4l2_subdev *sd) +{ + if (sd->active_state) + v4l2_subdev_lock_state(sd->active_state); + return sd->active_state; +} + +/** * v4l2_subdev_init - initializes the sub-device struct * * @sd: pointer to the &struct v4l2_subdev to be initialized @@ -1916,4 +1991,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 */ diff --git a/include/media/videobuf-core.h b/include/media/videobuf-core.h deleted file mode 100644 index 2e01b2e9a1c0..000000000000 --- a/include/media/videobuf-core.h +++ /dev/null @@ -1,233 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * generic helper functions for handling video4linux capture buffers - * - * (c) 2007 Mauro Carvalho Chehab, <mchehab@kernel.org> - * - * Highly based on video-buf written originally by: - * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org> - * (c) 2006 Mauro Carvalho Chehab, <mchehab@kernel.org> - * (c) 2006 Ted Walther and John Sokol - */ - -#ifndef _VIDEOBUF_CORE_H -#define _VIDEOBUF_CORE_H - -#include <linux/poll.h> -#include <linux/videodev2.h> - -#define UNSET (-1U) - - -struct videobuf_buffer; -struct videobuf_queue; - -/* --------------------------------------------------------------------- */ - -/* - * A small set of helper functions to manage video4linux buffers. - * - * struct videobuf_buffer holds the data structures used by the helper - * functions, additionally some commonly used fields for v4l buffers - * (width, height, lists, waitqueue) are in there. That struct should - * be used as first element in the drivers buffer struct. - * - * about the mmap helpers (videobuf_mmap_*): - * - * The mmaper function allows to map any subset of contiguous buffers. - * This includes one mmap() call for all buffers (which the original - * video4linux API uses) as well as one mmap() for every single buffer - * (which v4l2 uses). - * - * If there is a valid mapping for a buffer, buffer->baddr/bsize holds - * userspace address + size which can be fed into the - * videobuf_dma_init_user function listed above. - * - */ - -struct videobuf_mapping { - unsigned int count; - struct videobuf_queue *q; -}; - -enum videobuf_state { - VIDEOBUF_NEEDS_INIT = 0, - VIDEOBUF_PREPARED = 1, - VIDEOBUF_QUEUED = 2, - VIDEOBUF_ACTIVE = 3, - VIDEOBUF_DONE = 4, - VIDEOBUF_ERROR = 5, - VIDEOBUF_IDLE = 6, -}; - -struct videobuf_buffer { - unsigned int i; - u32 magic; - - /* info about the buffer */ - unsigned int width; - unsigned int height; - unsigned int bytesperline; /* use only if != 0 */ - unsigned long size; - enum v4l2_field field; - enum videobuf_state state; - struct list_head stream; /* QBUF/DQBUF list */ - - /* touched by irq handler */ - struct list_head queue; - wait_queue_head_t done; - unsigned int field_count; - u64 ts; - - /* Memory type */ - enum v4l2_memory memory; - - /* buffer size */ - size_t bsize; - - /* buffer offset (mmap + overlay) */ - size_t boff; - - /* buffer addr (userland ptr!) */ - unsigned long baddr; - - /* for mmap'ed buffers */ - struct videobuf_mapping *map; - - /* Private pointer to allow specific methods to store their data */ - int privsize; - void *priv; -}; - -struct videobuf_queue_ops { - int (*buf_setup)(struct videobuf_queue *q, - unsigned int *count, unsigned int *size); - int (*buf_prepare)(struct videobuf_queue *q, - struct videobuf_buffer *vb, - enum v4l2_field field); - void (*buf_queue)(struct videobuf_queue *q, - struct videobuf_buffer *vb); - void (*buf_release)(struct videobuf_queue *q, - struct videobuf_buffer *vb); -}; - -#define MAGIC_QTYPE_OPS 0x12261003 - -/* Helper operations - device type dependent */ -struct videobuf_qtype_ops { - u32 magic; - - struct videobuf_buffer *(*alloc_vb)(size_t size); - void *(*vaddr) (struct videobuf_buffer *buf); - int (*iolock) (struct videobuf_queue *q, - struct videobuf_buffer *vb, - struct v4l2_framebuffer *fbuf); - int (*sync) (struct videobuf_queue *q, - struct videobuf_buffer *buf); - int (*mmap_mapper) (struct videobuf_queue *q, - struct videobuf_buffer *buf, - struct vm_area_struct *vma); -}; - -struct videobuf_queue { - struct mutex vb_lock; - struct mutex *ext_lock; - spinlock_t *irqlock; - struct device *dev; - - wait_queue_head_t wait; /* wait if queue is empty */ - - enum v4l2_buf_type type; - unsigned int msize; - enum v4l2_field field; - enum v4l2_field last; /* for field=V4L2_FIELD_ALTERNATE */ - struct videobuf_buffer *bufs[VIDEO_MAX_FRAME]; - const struct videobuf_queue_ops *ops; - struct videobuf_qtype_ops *int_ops; - - unsigned int streaming:1; - unsigned int reading:1; - - /* capture via mmap() + ioctl(QBUF/DQBUF) */ - struct list_head stream; - - /* capture via read() */ - unsigned int read_off; - struct videobuf_buffer *read_buf; - - /* driver private data */ - void *priv_data; -}; - -static inline void videobuf_queue_lock(struct videobuf_queue *q) -{ - if (!q->ext_lock) - mutex_lock(&q->vb_lock); -} - -static inline void videobuf_queue_unlock(struct videobuf_queue *q) -{ - if (!q->ext_lock) - mutex_unlock(&q->vb_lock); -} - -int videobuf_waiton(struct videobuf_queue *q, struct videobuf_buffer *vb, - int non_blocking, int intr); -int videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb, - struct v4l2_framebuffer *fbuf); - -struct videobuf_buffer *videobuf_alloc_vb(struct videobuf_queue *q); - -/* Used on videobuf-dvb */ -void *videobuf_queue_to_vaddr(struct videobuf_queue *q, - struct videobuf_buffer *buf); - -void videobuf_queue_core_init(struct videobuf_queue *q, - const struct videobuf_queue_ops *ops, - struct device *dev, - spinlock_t *irqlock, - enum v4l2_buf_type type, - enum v4l2_field field, - unsigned int msize, - void *priv, - struct videobuf_qtype_ops *int_ops, - struct mutex *ext_lock); -int videobuf_queue_is_busy(struct videobuf_queue *q); -void videobuf_queue_cancel(struct videobuf_queue *q); - -enum v4l2_field videobuf_next_field(struct videobuf_queue *q); -int videobuf_reqbufs(struct videobuf_queue *q, - struct v4l2_requestbuffers *req); -int videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b); -int videobuf_qbuf(struct videobuf_queue *q, - struct v4l2_buffer *b); -int videobuf_dqbuf(struct videobuf_queue *q, - struct v4l2_buffer *b, int nonblocking); -int videobuf_streamon(struct videobuf_queue *q); -int videobuf_streamoff(struct videobuf_queue *q); - -void videobuf_stop(struct videobuf_queue *q); - -int videobuf_read_start(struct videobuf_queue *q); -void videobuf_read_stop(struct videobuf_queue *q); -ssize_t videobuf_read_stream(struct videobuf_queue *q, - char __user *data, size_t count, loff_t *ppos, - int vbihack, int nonblocking); -ssize_t videobuf_read_one(struct videobuf_queue *q, - char __user *data, size_t count, loff_t *ppos, - int nonblocking); -__poll_t videobuf_poll_stream(struct file *file, - struct videobuf_queue *q, - poll_table *wait); - -int videobuf_mmap_setup(struct videobuf_queue *q, - unsigned int bcount, unsigned int bsize, - enum v4l2_memory memory); -int __videobuf_mmap_setup(struct videobuf_queue *q, - unsigned int bcount, unsigned int bsize, - enum v4l2_memory memory); -int videobuf_mmap_free(struct videobuf_queue *q); -int videobuf_mmap_mapper(struct videobuf_queue *q, - struct vm_area_struct *vma); - -#endif diff --git a/include/media/videobuf-dma-contig.h b/include/media/videobuf-dma-contig.h deleted file mode 100644 index 525883b2c53e..000000000000 --- a/include/media/videobuf-dma-contig.h +++ /dev/null @@ -1,30 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * helper functions for physically contiguous capture buffers - * - * The functions support hardware lacking scatter gather support - * (i.e. the buffers must be linear in physical memory) - * - * Copyright (c) 2008 Magnus Damm - */ -#ifndef _VIDEOBUF_DMA_CONTIG_H -#define _VIDEOBUF_DMA_CONTIG_H - -#include <linux/dma-mapping.h> -#include <media/videobuf-core.h> - -void videobuf_queue_dma_contig_init(struct videobuf_queue *q, - const struct videobuf_queue_ops *ops, - struct device *dev, - spinlock_t *irqlock, - enum v4l2_buf_type type, - enum v4l2_field field, - unsigned int msize, - void *priv, - struct mutex *ext_lock); - -dma_addr_t videobuf_to_dma_contig(struct videobuf_buffer *buf); -void videobuf_dma_contig_free(struct videobuf_queue *q, - struct videobuf_buffer *buf); - -#endif /* _VIDEOBUF_DMA_CONTIG_H */ diff --git a/include/media/videobuf-dma-sg.h b/include/media/videobuf-dma-sg.h deleted file mode 100644 index 930ff8d454fc..000000000000 --- a/include/media/videobuf-dma-sg.h +++ /dev/null @@ -1,102 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * helper functions for SG DMA video4linux capture buffers - * - * The functions expect the hardware being able to scatter gather - * (i.e. the buffers are not linear in physical memory, but fragmented - * into PAGE_SIZE chunks). They also assume the driver does not need - * to touch the video data. - * - * (c) 2007 Mauro Carvalho Chehab, <mchehab@kernel.org> - * - * Highly based on video-buf written originally by: - * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org> - * (c) 2006 Mauro Carvalho Chehab, <mchehab@kernel.org> - * (c) 2006 Ted Walther and John Sokol - */ -#ifndef _VIDEOBUF_DMA_SG_H -#define _VIDEOBUF_DMA_SG_H - -#include <media/videobuf-core.h> - -/* --------------------------------------------------------------------- */ - -/* - * A small set of helper functions to manage buffers (both userland - * and kernel) for DMA. - * - * videobuf_dma_init_*() - * creates a buffer. The userland version takes a userspace - * pointer + length. The kernel version just wants the size and - * does memory allocation too using vmalloc_32(). - * - * videobuf_dma_*() - * see Documentation/core-api/dma-api-howto.rst, these functions to - * basically the same. The map function does also build a - * scatterlist for the buffer (and unmap frees it ...) - * - * videobuf_dma_free() - * no comment ... - * - */ - -struct videobuf_dmabuf { - u32 magic; - - /* for userland buffer */ - int offset; - size_t size; - struct page **pages; - - /* for kernel buffers */ - void *vaddr; - struct page **vaddr_pages; - dma_addr_t *dma_addr; - struct device *dev; - - /* for overlay buffers (pci-pci dma) */ - dma_addr_t bus_addr; - - /* common */ - struct scatterlist *sglist; - int sglen; - unsigned long nr_pages; - int direction; -}; - -struct videobuf_dma_sg_memory { - u32 magic; - - /* for mmap'ed buffers */ - struct videobuf_dmabuf dma; -}; - -/* - * Scatter-gather DMA buffer API. - * - * These functions provide a simple way to create a page list and a - * scatter-gather list from a kernel, userspace of physical address and map the - * memory for DMA operation. - * - * Despite the name, this is totally unrelated to videobuf, except that - * videobuf-dma-sg uses the same API internally. - */ -int videobuf_dma_free(struct videobuf_dmabuf *dma); - -int videobuf_dma_unmap(struct device *dev, struct videobuf_dmabuf *dma); -struct videobuf_dmabuf *videobuf_to_dma(struct videobuf_buffer *buf); - -void *videobuf_sg_alloc(size_t size); - -void videobuf_queue_sg_init(struct videobuf_queue *q, - const struct videobuf_queue_ops *ops, - struct device *dev, - spinlock_t *irqlock, - enum v4l2_buf_type type, - enum v4l2_field field, - unsigned int msize, - void *priv, - struct mutex *ext_lock); - -#endif /* _VIDEOBUF_DMA_SG_H */ - diff --git a/include/media/videobuf-vmalloc.h b/include/media/videobuf-vmalloc.h deleted file mode 100644 index e930dbb9d7f4..000000000000 --- a/include/media/videobuf-vmalloc.h +++ /dev/null @@ -1,43 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * helper functions for vmalloc capture buffers - * - * The functions expect the hardware being able to scatter gather - * (i.e. the buffers are not linear in physical memory, but fragmented - * into PAGE_SIZE chunks). They also assume the driver does not need - * to touch the video data. - * - * (c) 2007 Mauro Carvalho Chehab, <mchehab@kernel.org> - */ -#ifndef _VIDEOBUF_VMALLOC_H -#define _VIDEOBUF_VMALLOC_H - -#include <media/videobuf-core.h> - -/* --------------------------------------------------------------------- */ - -struct videobuf_vmalloc_memory { - u32 magic; - - void *vaddr; - - /* remap_vmalloc_range seems to need to run - * after mmap() on some cases */ - struct vm_area_struct *vma; -}; - -void videobuf_queue_vmalloc_init(struct videobuf_queue *q, - const struct videobuf_queue_ops *ops, - struct device *dev, - spinlock_t *irqlock, - enum v4l2_buf_type type, - enum v4l2_field field, - unsigned int msize, - void *priv, - struct mutex *ext_lock); - -void *videobuf_to_vmalloc(struct videobuf_buffer *buf); - -void videobuf_vmalloc_free(struct videobuf_buffer *buf); - -#endif diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h index 4b6a9d2ea372..9b02aeba4108 100644 --- a/include/media/videobuf2-core.h +++ b/include/media/videobuf2-core.h @@ -72,6 +72,10 @@ struct vb2_buffer; * argument to other ops in this structure. * @put_userptr: inform the allocator that a USERPTR buffer will no longer * be used. + * @prepare: called every time the buffer is passed from userspace to the + * driver, useful for cache synchronisation, optional. + * @finish: called every time the buffer is passed back from the driver + * to the userspace, also optional. * @attach_dmabuf: attach a shared &struct dma_buf for a hardware operation; * used for DMABUF memory types; dev is the alloc device * dbuf is the shared dma_buf; returns ERR_PTR() on failure; @@ -86,10 +90,6 @@ struct vb2_buffer; * dmabuf. * @unmap_dmabuf: releases access control to the dmabuf - allocator is notified * that this driver is done using the dmabuf for now. - * @prepare: called every time the buffer is passed from userspace to the - * driver, useful for cache synchronisation, optional. - * @finish: called every time the buffer is passed back from the driver - * to the userspace, also optional. * @vaddr: return a kernel virtual address to a given memory buffer * associated with the passed private structure or NULL if no * such mapping exists. @@ -154,6 +154,8 @@ struct vb2_mem_ops { * @mem_priv: private data with this plane. * @dbuf: dma_buf - shared buffer object. * @dbuf_mapped: flag to show whether dbuf is mapped or not + * @dbuf_duplicated: boolean to show whether dbuf is duplicated with a + * previous plane of the buffer. * @bytesused: number of bytes occupied by data in the plane (payload). * @length: size of this plane (NOT the payload) in bytes. The maximum * valid size is MAX_UINT - PAGE_SIZE. @@ -179,6 +181,7 @@ struct vb2_plane { void *mem_priv; struct dma_buf *dbuf; unsigned int dbuf_mapped; + bool dbuf_duplicated; unsigned int bytesused; unsigned int length; unsigned int min_length; @@ -271,11 +274,11 @@ struct vb2_buffer { * skips cache sync/invalidation. * skip_cache_sync_on_finish: when set buffer's ->finish() function * skips cache sync/invalidation. + * planes: per-plane information; do not change * queued_entry: entry on the queued buffers list, which holds * all buffers queued from userspace * done_entry: entry on the list that stores all buffers ready * to be dequeued to userspace - * vb2_plane: per-plane information; do not change */ enum vb2_buffer_state state; unsigned int synced:1; @@ -346,8 +349,8 @@ struct vb2_buffer { * describes the requested number of planes and sizes\[\] * contains the requested plane sizes. In this case * \*num_buffers are being allocated additionally to - * q->num_buffers. If either \*num_planes or the requested - * sizes are invalid callback must return %-EINVAL. + * the buffers already allocated. If either \*num_planes + * or the requested sizes are invalid callback must return %-EINVAL. * @wait_prepare: release any locks taken while calling vb2 functions; * it is called before an ioctl needs to wait for a new * buffer to arrive; required to avoid a deadlock in @@ -402,7 +405,7 @@ struct vb2_buffer { * by calling vb2_buffer_done() with %VB2_BUF_STATE_QUEUED. * If you need a minimum number of buffers before you can * start streaming, then set - * &vb2_queue->min_buffers_needed. If that is non-zero + * &vb2_queue->min_queued_buffers. If that is non-zero * then @start_streaming won't be called until at least * that many buffers have been queued up by userspace. * @stop_streaming: called when 'streaming' state must be disabled; driver @@ -484,7 +487,6 @@ struct vb2_buf_ops { * caller. For example, for V4L2, it should match * the types defined on &enum v4l2_buf_type. * @io_modes: supported io methods (see &enum vb2_io_modes). - * @alloc_devs: &struct device memory type/allocator-specific per-plane device * @dev: device to use for the default allocation context if the driver * doesn't fill in the @alloc_devs array. * @dma_attrs: DMA attributes to use for the DMA. @@ -546,18 +548,38 @@ struct vb2_buf_ops { * @gfp_flags: additional gfp flags used when allocating the buffers. * Typically this is 0, but it may be e.g. %GFP_DMA or %__GFP_DMA32 * to force the buffer allocation to a specific memory zone. - * @min_buffers_needed: the minimum number of buffers needed before + * @min_queued_buffers: the minimum number of queued buffers needed before * @start_streaming can be called. Used when a DMA engine * cannot be started unless at least this number of buffers * have been queued into the driver. + * VIDIOC_REQBUFS will ensure at least @min_queued_buffers + 1 + * buffers will be allocated. Note that VIDIOC_CREATE_BUFS will not + * modify the requested buffer count. + * @min_reqbufs_allocation: the minimum number of buffers to be allocated when + * calling VIDIOC_REQBUFS. Note that VIDIOC_CREATE_BUFS will *not* + * modify the requested buffer count and does not use this field. + * Drivers can set this if there has to be a certain number of + * buffers available for the hardware to work effectively. + * This allows calling VIDIOC_REQBUFS with a buffer count of 1 and + * it will be automatically adjusted to a workable buffer count. + * If set, then @min_reqbufs_allocation must be larger than + * @min_queued_buffers + 1. + * If this field is > 3, then it is highly recommended that the + * driver implements the V4L2_CID_MIN_BUFFERS_FOR_CAPTURE/OUTPUT + * control. + * @alloc_devs: &struct device memory type/allocator-specific per-plane device */ /* * Private elements (won't appear at the uAPI book): * @mmap_lock: private mutex used when buffers are allocated/freed/mmapped * @memory: current memory type used * @dma_dir: DMA mapping direction. - * @bufs: videobuf2 buffer structures - * @num_buffers: number of allocated/used buffers + * @bufs: videobuf2 buffer structures. If it is non-NULL then + * bufs_bitmap is also non-NULL. + * @bufs_bitmap: bitmap tracking whether each bufs[] entry is used + * @max_num_buffers: upper limit of number of allocated/used buffers. + * If set to 0 v4l2 core will change it VB2_MAX_FRAME + * for backward compatibility. * @queued_list: list of buffers currently queued from userspace * @queued_count: number of buffers queued and ready for streaming. * @owned_by_drv_count: number of buffers owned by the driver @@ -571,8 +593,12 @@ struct vb2_buf_ops { * @waiting_for_buffers: used in poll() to check if vb2 is still waiting for * buffers. Only set for capture queues if qbuf has not yet been * called since poll() needs to return %EPOLLERR in that situation. + * @waiting_in_dqbuf: set by the core for the duration of a blocking DQBUF, when + * it has to wait for a buffer to become available with vb2_queue->lock + * released. Used to prevent destroying the queue by other threads. * @is_multiplanar: set if buffer type is multiplanar * @is_output: set if buffer type is output + * @is_busy: set if at least one buffer has been allocated at some time. * @copy_timestamp: set if vb2-core should set timestamps * @last_buffer_dequeued: used in poll() and DQBUF to immediately return if the * last decoded buffer was already dequeued. Set for capture queues @@ -611,7 +637,8 @@ struct vb2_queue { unsigned int buf_struct_size; u32 timestamp_flags; gfp_t gfp_flags; - u32 min_buffers_needed; + u32 min_queued_buffers; + u32 min_reqbufs_allocation; struct device *alloc_devs[VB2_MAX_PLANES]; @@ -619,8 +646,9 @@ struct vb2_queue { struct mutex mmap_lock; unsigned int memory; enum dma_data_direction dma_dir; - struct vb2_buffer *bufs[VB2_MAX_FRAME]; - unsigned int num_buffers; + struct vb2_buffer **bufs; + unsigned long *bufs_bitmap; + unsigned int max_num_buffers; struct list_head queued_list; unsigned int queued_count; @@ -637,6 +665,7 @@ struct vb2_queue { unsigned int waiting_in_dqbuf:1; unsigned int is_multiplanar:1; unsigned int is_output:1; + unsigned int is_busy:1; unsigned int copy_timestamp:1; unsigned int last_buffer_dequeued:1; @@ -747,7 +776,7 @@ int vb2_wait_for_all_buffers(struct vb2_queue *q); /** * vb2_core_querybuf() - query video buffer information. * @q: pointer to &struct vb2_queue with videobuf2 queue. - * @index: id number of the buffer. + * @vb: pointer to struct &vb2_buffer. * @pb: buffer struct passed from userspace. * * Videobuf2 core helper to implement VIDIOC_QUERYBUF() operation. It is called @@ -759,7 +788,7 @@ int vb2_wait_for_all_buffers(struct vb2_queue *q); * * Return: returns zero on success; an error code otherwise. */ -void vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb); +void vb2_core_querybuf(struct vb2_queue *q, struct vb2_buffer *vb, void *pb); /** * vb2_core_reqbufs() - Initiate streaming. @@ -801,6 +830,8 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory, * @count: requested buffer count. * @requested_planes: number of planes requested. * @requested_sizes: array with the size of the planes. + * @first_index: index of the first created buffer, all allocated buffers have + * indices in the range [first_index..first_index+count-1] * * Videobuf2 core helper to implement VIDIOC_CREATE_BUFS() operation. It is * called internally by VB2 by an API-specific handler, like @@ -817,13 +848,14 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory, int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory, unsigned int flags, unsigned int *count, unsigned int requested_planes, - const unsigned int requested_sizes[]); + const unsigned int requested_sizes[], + unsigned int *first_index); /** * vb2_core_prepare_buf() - Pass ownership of a buffer from userspace * to the kernel. * @q: pointer to &struct vb2_queue with videobuf2 queue. - * @index: id number of the buffer. + * @vb: pointer to struct &vb2_buffer. * @pb: buffer structure passed from userspace to * &v4l2_ioctl_ops->vidioc_prepare_buf handler in driver. * @@ -839,13 +871,23 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory, * * Return: returns zero on success; an error code otherwise. */ -int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb); +int vb2_core_prepare_buf(struct vb2_queue *q, struct vb2_buffer *vb, void *pb); + +/** + * vb2_core_remove_bufs() - + * @q: pointer to &struct vb2_queue with videobuf2 queue. + * @start: first index of the range of buffers to remove. + * @count: number of buffers to remove. + * + * Return: returns zero on success; an error code otherwise. + */ +int vb2_core_remove_bufs(struct vb2_queue *q, unsigned int start, unsigned int count); /** * vb2_core_qbuf() - Queue a buffer from userspace * * @q: pointer to &struct vb2_queue with videobuf2 queue. - * @index: id number of the buffer + * @vb: pointer to struct &vb2_buffer. * @pb: buffer structure passed from userspace to * v4l2_ioctl_ops->vidioc_qbuf handler in driver * @req: pointer to &struct media_request, may be NULL. @@ -867,7 +909,7 @@ int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb); * * Return: returns zero on success; an error code otherwise. */ -int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb, +int vb2_core_qbuf(struct vb2_queue *q, struct vb2_buffer *vb, void *pb, struct media_request *req); /** @@ -931,7 +973,7 @@ int vb2_core_streamoff(struct vb2_queue *q, unsigned int type); * @fd: pointer to the file descriptor associated with DMABUF * (set by driver). * @type: buffer type. - * @index: id number of the buffer. + * @vb: pointer to struct &vb2_buffer. * @plane: index of the plane to be exported, 0 for single plane queues * @flags: file flags for newly created file, as defined at * include/uapi/asm-generic/fcntl.h. @@ -945,7 +987,7 @@ int vb2_core_streamoff(struct vb2_queue *q, unsigned int type); * Return: returns zero on success; an error code otherwise. */ int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type, - unsigned int index, unsigned int plane, unsigned int flags); + struct vb2_buffer *vb, unsigned int plane, unsigned int flags); /** * vb2_core_queue_init() - initialize a videobuf2 queue @@ -1140,6 +1182,18 @@ static inline bool vb2_fileio_is_active(struct vb2_queue *q) } /** + * vb2_get_num_buffers() - get the number of buffer in a queue + * @q: pointer to &struct vb2_queue with videobuf2 queue. + */ +static inline unsigned int vb2_get_num_buffers(struct vb2_queue *q) +{ + if (q->bufs_bitmap) + return bitmap_weight(q->bufs_bitmap, q->max_num_buffers); + + return 0; +} + +/** * vb2_is_busy() - return busy status of the queue. * @q: pointer to &struct vb2_queue with videobuf2 queue. * @@ -1147,7 +1201,7 @@ static inline bool vb2_fileio_is_active(struct vb2_queue *q) */ static inline bool vb2_is_busy(struct vb2_queue *q) { - return (q->num_buffers > 0); + return !!q->is_busy; } /** @@ -1239,7 +1293,13 @@ static inline void vb2_clear_last_buffer_dequeued(struct vb2_queue *q) static inline struct vb2_buffer *vb2_get_buffer(struct vb2_queue *q, unsigned int index) { - if (index < q->num_buffers) + if (!q->bufs) + return NULL; + + if (index >= q->max_num_buffers) + return NULL; + + if (test_bit(index, q->bufs_bitmap)) return q->bufs[index]; return NULL; } diff --git a/include/media/videobuf2-v4l2.h b/include/media/videobuf2-v4l2.h index 5a845887850b..77ce8238ab30 100644 --- a/include/media/videobuf2-v4l2.h +++ b/include/media/videobuf2-v4l2.h @@ -334,6 +334,8 @@ int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i); int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i); int vb2_ioctl_expbuf(struct file *file, void *priv, struct v4l2_exportbuffer *p); +int vb2_ioctl_remove_bufs(struct file *file, void *priv, + struct v4l2_remove_buffers *p); /* struct v4l2_file_operations helpers */ |