diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-15 20:30:12 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-15 20:30:12 -0800 |
commit | 5d352e69c60e54b5f04d6e337a1d2bf0dbf3d94a (patch) | |
tree | 214e6b190715267ed02b6d415396c2bbcf2eaace /include/media | |
parent | 93ea0eb7d77afab34657715630d692a78b8cea6a (diff) | |
parent | f2ecc3d0787e05d9145722feed01d4a11ab6bec1 (diff) | |
download | linux-5d352e69c60e54b5f04d6e337a1d2bf0dbf3d94a.tar.bz2 |
Merge tag 'media/v4.15-1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab:
- Documentation for digital TV (both kAPI and uAPI) are now in sync
with the implementation (except for legacy/deprecated ioctls). This
is a major step, as there were always a gap there
- New sensor driver: imx274
- New cec driver: cec-gpio
- New platform driver for rockship rga and tegra CEC
- New RC driver: tango-ir
- Several cleanups at atomisp driver
- Core improvements for RC, CEC, V4L2 async probing support and DVB
- Lots of drivers cleanup, fixes and improvements.
* tag 'media/v4.15-1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (332 commits)
dvb_frontend: don't use-after-free the frontend struct
media: dib0700: fix invalid dvb_detach argument
media: v4l2-ctrls: Don't validate BITMASK twice
media: s5p-mfc: fix lockdep warning
media: dvb-core: always call invoke_release() in fe_free()
media: usb: dvb-usb-v2: dvb_usb_core: remove redundant code in dvb_usb_fe_sleep
media: au0828: make const array addr_list static
media: cx88: make const arrays default_addr_list and pvr2000_addr_list static
media: drxd: make const array fastIncrDecLUT static
media: usb: fix spelling mistake: "synchronuously" -> "synchronously"
media: ddbridge: fix build warnings
media: av7110: avoid 2038 overflow in debug print
media: Don't do DMA on stack for firmware upload in the AS102 driver
media: v4l: async: fix unregister for implicitly registered sub-device notifiers
media: v4l: async: fix return of unitialized variable ret
media: imx274: fix missing return assignment from call to imx274_mode_regs
media: camss-vfe: always initialize reg at vfe_set_xbar_cfg()
media: atomisp: make function calls cleaner
media: atomisp: get rid of storage_class.h
media: atomisp: get rid of wrong stddef.h include
...
Diffstat (limited to 'include/media')
-rw-r--r-- | include/media/cec-pin.h | 111 | ||||
-rw-r--r-- | include/media/cec.h | 16 | ||||
-rw-r--r-- | include/media/drv-intf/saa7146_vv.h | 7 | ||||
-rw-r--r-- | include/media/lirc_dev.h | 100 | ||||
-rw-r--r-- | include/media/rc-map.h | 4 | ||||
-rw-r--r-- | include/media/v4l2-async.h | 91 | ||||
-rw-r--r-- | include/media/v4l2-fwnode.h | 228 | ||||
-rw-r--r-- | include/media/v4l2-subdev.h | 3 |
8 files changed, 379 insertions, 181 deletions
diff --git a/include/media/cec-pin.h b/include/media/cec-pin.h index f09cc9579d53..83b3e17e0a07 100644 --- a/include/media/cec-pin.h +++ b/include/media/cec-pin.h @@ -21,71 +21,8 @@ #define LINUX_CEC_PIN_H #include <linux/types.h> -#include <linux/atomic.h> #include <media/cec.h> -enum cec_pin_state { - /* CEC is off */ - CEC_ST_OFF, - /* CEC is idle, waiting for Rx or Tx */ - CEC_ST_IDLE, - - /* Tx states */ - - /* Pending Tx, waiting for Signal Free Time to expire */ - CEC_ST_TX_WAIT, - /* Low-drive was detected, wait for bus to go high */ - CEC_ST_TX_WAIT_FOR_HIGH, - /* Drive CEC low for the start bit */ - CEC_ST_TX_START_BIT_LOW, - /* Drive CEC high for the start bit */ - CEC_ST_TX_START_BIT_HIGH, - /* Drive CEC low for the 0 bit */ - CEC_ST_TX_DATA_BIT_0_LOW, - /* Drive CEC high for the 0 bit */ - CEC_ST_TX_DATA_BIT_0_HIGH, - /* Drive CEC low for the 1 bit */ - CEC_ST_TX_DATA_BIT_1_LOW, - /* Drive CEC high for the 1 bit */ - CEC_ST_TX_DATA_BIT_1_HIGH, - /* - * Wait for start of sample time to check for Ack bit or first - * four initiator bits to check for Arbitration Lost. - */ - CEC_ST_TX_DATA_BIT_1_HIGH_PRE_SAMPLE, - /* Wait for end of bit period after sampling */ - CEC_ST_TX_DATA_BIT_1_HIGH_POST_SAMPLE, - - /* Rx states */ - - /* Start bit low detected */ - CEC_ST_RX_START_BIT_LOW, - /* Start bit high detected */ - CEC_ST_RX_START_BIT_HIGH, - /* Wait for bit sample time */ - CEC_ST_RX_DATA_SAMPLE, - /* Wait for earliest end of bit period after sampling */ - CEC_ST_RX_DATA_POST_SAMPLE, - /* Wait for CEC to go high (i.e. end of bit period */ - CEC_ST_RX_DATA_HIGH, - /* Drive CEC low to send 0 Ack bit */ - CEC_ST_RX_ACK_LOW, - /* End of 0 Ack time, wait for earliest end of bit period */ - CEC_ST_RX_ACK_LOW_POST, - /* Wait for CEC to go high (i.e. end of bit period */ - CEC_ST_RX_ACK_HIGH_POST, - /* Wait for earliest end of bit period and end of message */ - CEC_ST_RX_ACK_FINISH, - - /* Start low drive */ - CEC_ST_LOW_DRIVE, - /* Monitor pin using interrupts */ - CEC_ST_RX_IRQ, - - /* Total number of pin states */ - CEC_PIN_STATES -}; - /** * struct cec_pin_ops - low-level CEC pin operations * @read: read the CEC pin. Return true if high, false if low. @@ -97,6 +34,9 @@ enum cec_pin_state { * @free: optional. Free any allocated resources. Called when the * adapter is deleted. * @status: optional, log status information. + * @read_hpd: read the HPD pin. Return true if high, false if low or + * an error if negative. If NULL or -ENOTTY is returned, + * then this is not supported. * * These operations are used by the cec pin framework to manipulate * the CEC pin. @@ -109,50 +49,7 @@ struct cec_pin_ops { void (*disable_irq)(struct cec_adapter *adap); void (*free)(struct cec_adapter *adap); void (*status)(struct cec_adapter *adap, struct seq_file *file); -}; - -#define CEC_NUM_PIN_EVENTS 128 - -#define CEC_PIN_IRQ_UNCHANGED 0 -#define CEC_PIN_IRQ_DISABLE 1 -#define CEC_PIN_IRQ_ENABLE 2 - -struct cec_pin { - struct cec_adapter *adap; - const struct cec_pin_ops *ops; - struct task_struct *kthread; - wait_queue_head_t kthread_waitq; - struct hrtimer timer; - ktime_t ts; - unsigned int wait_usecs; - u16 la_mask; - bool enabled; - bool monitor_all; - bool rx_eom; - bool enable_irq_failed; - enum cec_pin_state state; - struct cec_msg tx_msg; - u32 tx_bit; - bool tx_nacked; - u32 tx_signal_free_time; - struct cec_msg rx_msg; - u32 rx_bit; - - struct cec_msg work_rx_msg; - u8 work_tx_status; - ktime_t work_tx_ts; - atomic_t work_irq_change; - atomic_t work_pin_events; - unsigned int work_pin_events_wr; - unsigned int work_pin_events_rd; - ktime_t work_pin_ts[CEC_NUM_PIN_EVENTS]; - bool work_pin_is_high[CEC_NUM_PIN_EVENTS]; - ktime_t timer_ts; - u32 timer_cnt; - u32 timer_100ms_overruns; - u32 timer_300ms_overruns; - u32 timer_max_overrun; - u32 timer_sum_overrun; + int (*read_hpd)(struct cec_adapter *adap); }; /** diff --git a/include/media/cec.h b/include/media/cec.h index df6b3bd31284..16341210d3ba 100644 --- a/include/media/cec.h +++ b/include/media/cec.h @@ -91,7 +91,7 @@ struct cec_event_entry { }; #define CEC_NUM_CORE_EVENTS 2 -#define CEC_NUM_EVENTS CEC_EVENT_PIN_CEC_HIGH +#define CEC_NUM_EVENTS CEC_EVENT_PIN_HPD_HIGH struct cec_fh { struct list_head list; @@ -297,6 +297,16 @@ void cec_queue_pin_cec_event(struct cec_adapter *adap, bool is_high, ktime_t ts); /** + * cec_queue_pin_hpd_event() - queue a pin event with a given timestamp. + * + * @adap: pointer to the cec adapter + * @is_high: when true the HPD pin is high, otherwise it is low + * @ts: the timestamp for this event + * + */ +void cec_queue_pin_hpd_event(struct cec_adapter *adap, bool is_high, ktime_t ts); + +/** * cec_get_edid_phys_addr() - find and return the physical address * * @edid: pointer to the EDID data @@ -417,6 +427,10 @@ static inline u16 cec_phys_addr_for_input(u16 phys_addr, u8 input) static inline int cec_phys_addr_validate(u16 phys_addr, u16 *parent, u16 *port) { + if (parent) + *parent = phys_addr; + if (port) + *port = 0; return 0; } diff --git a/include/media/drv-intf/saa7146_vv.h b/include/media/drv-intf/saa7146_vv.h index 4e89e9f12a1e..6f80fb7f31a5 100644 --- a/include/media/drv-intf/saa7146_vv.h +++ b/include/media/drv-intf/saa7146_vv.h @@ -108,6 +108,7 @@ struct saa7146_vv struct saa7146_dmaqueue vbi_dmaq; struct v4l2_vbi_format vbi_fmt; struct timer_list vbi_read_timeout; + struct file *vbi_read_timeout_file; /* vbi workaround interrupt queue */ wait_queue_head_t vbi_wq; int vbi_fieldcount; @@ -184,7 +185,7 @@ int saa7146_unregister_device(struct video_device *vid, struct saa7146_dev *dev) void saa7146_buffer_finish(struct saa7146_dev *dev, struct saa7146_dmaqueue *q, int state); void saa7146_buffer_next(struct saa7146_dev *dev, struct saa7146_dmaqueue *q,int vbi); int saa7146_buffer_queue(struct saa7146_dev *dev, struct saa7146_dmaqueue *q, struct saa7146_buf *buf); -void saa7146_buffer_timeout(unsigned long data); +void saa7146_buffer_timeout(struct timer_list *t); void saa7146_dma_free(struct saa7146_dev* dev,struct videobuf_queue *q, struct saa7146_buf *buf); @@ -203,14 +204,14 @@ void saa7146_set_gpio(struct saa7146_dev *saa, u8 pin, u8 data); /* from saa7146_video.c */ extern const struct v4l2_ioctl_ops saa7146_video_ioctl_ops; extern const struct v4l2_ioctl_ops saa7146_vbi_ioctl_ops; -extern struct saa7146_use_ops saa7146_video_uops; +extern const struct saa7146_use_ops saa7146_video_uops; int saa7146_start_preview(struct saa7146_fh *fh); int saa7146_stop_preview(struct saa7146_fh *fh); long saa7146_video_do_ioctl(struct file *file, unsigned int cmd, void *arg); int saa7146_s_ctrl(struct v4l2_ctrl *ctrl); /* from saa7146_vbi.c */ -extern struct saa7146_use_ops saa7146_vbi_uops; +extern const struct saa7146_use_ops saa7146_vbi_uops; /* resource management functions */ int saa7146_res_get(struct saa7146_fh *fh, unsigned int bit); diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h index 86d15a9b6c01..857da67bd931 100644 --- a/include/media/lirc_dev.h +++ b/include/media/lirc_dev.h @@ -9,7 +9,6 @@ #ifndef _LINUX_LIRC_DEV_H #define _LINUX_LIRC_DEV_H -#define MAX_IRCTL_DEVICES 8 #define BUFLEN 16 #include <linux/slab.h> @@ -18,6 +17,8 @@ #include <linux/poll.h> #include <linux/kfifo.h> #include <media/lirc.h> +#include <linux/device.h> +#include <linux/cdev.h> struct lirc_buffer { wait_queue_head_t wait_poll; @@ -112,84 +113,69 @@ static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf, } /** - * struct lirc_driver - Defines the parameters on a LIRC driver - * - * @name: this string will be used for logs - * - * @minor: indicates minor device (/dev/lirc) number for - * registered driver if caller fills it with negative - * value, then the first free minor number will be used - * (if available). - * - * @code_length: length of the remote control key code expressed in bits. - * - * @buffer_size: Number of FIFO buffers with @chunk_size size. If zero, - * creates a buffer with BUFLEN size (16 bytes). + * struct lirc_dev - represents a LIRC device * + * @name: used for logging + * @minor: the minor device (/dev/lircX) number for the device + * @code_length: length of a remote control key code expressed in bits * @features: lirc compatible hardware features, like LIRC_MODE_RAW, * LIRC_CAN\_\*, as defined at include/media/lirc.h. - * + * @buffer_size: Number of FIFO buffers with @chunk_size size. + * Only used if @rbuf is NULL. * @chunk_size: Size of each FIFO buffer. - * - * @data: it may point to any driver data and this pointer will - * be passed to all callback functions. - * - * @min_timeout: Minimum timeout for record. Valid only if - * LIRC_CAN_SET_REC_TIMEOUT is defined. - * - * @max_timeout: Maximum timeout for record. Valid only if - * LIRC_CAN_SET_REC_TIMEOUT is defined. - * - * @rbuf: if not NULL, it will be used as a read buffer, you will + * Only used if @rbuf is NULL. + * @data: private per-driver data + * @buf: if %NULL, lirc_dev will allocate and manage the buffer, + * otherwise allocated by the caller which will * have to write to the buffer by other means, like irq's * (see also lirc_serial.c). - * - * @rdev: Pointed to struct rc_dev associated with the LIRC - * device. - * - * @fops: file_operations for drivers which don't fit the current - * driver model. - * Some ioctl's can be directly handled by lirc_dev if the - * driver's ioctl function is NULL or if it returns - * -ENOIOCTLCMD (see also lirc_serial.c). - * - * @dev: pointer to the struct device associated with the LIRC - * device. - * + * @buf_internal: whether lirc_dev has allocated the read buffer or not + * @rdev: &struct rc_dev associated with the device + * @fops: &struct file_operations for the device * @owner: the module owning this struct + * @attached: if the device is still live + * @open: open count for the device's chardev + * @mutex: serialises file_operations calls + * @dev: &struct device assigned to the device + * @cdev: &struct cdev assigned to the device */ -struct lirc_driver { +struct lirc_dev { char name[40]; - int minor; + unsigned int minor; __u32 code_length; - unsigned int buffer_size; /* in chunks holding one code each */ __u32 features; + unsigned int buffer_size; /* in chunks holding one code each */ unsigned int chunk_size; + struct lirc_buffer *buf; + bool buf_internal; void *data; - int min_timeout; - int max_timeout; - struct lirc_buffer *rbuf; struct rc_dev *rdev; const struct file_operations *fops; - struct device *dev; struct module *owner; + + bool attached; + int open; + + struct mutex mutex; /* protect from simultaneous accesses */ + + struct device dev; + struct cdev cdev; }; -/* following functions can be called ONLY from user context - * - * returns negative value on error or minor number - * of the registered device if success - * contents of the structure pointed by p is copied - */ -extern int lirc_register_driver(struct lirc_driver *d); +struct lirc_dev *lirc_allocate_device(void); + +void lirc_free_device(struct lirc_dev *d); + +int lirc_register_device(struct lirc_dev *d); + +void lirc_unregister_device(struct lirc_dev *d); -/* returns negative value on error or 0 if success -*/ -extern int lirc_unregister_driver(int minor); +/* Must be called in the open fop before lirc_get_pdata() can be used */ +void lirc_init_pdata(struct inode *inode, struct file *file); -/* Returns the private data stored in the lirc_driver +/* Returns the private data stored in the lirc_dev * associated with the given device file pointer. */ void *lirc_get_pdata(struct file *file); diff --git a/include/media/rc-map.h b/include/media/rc-map.h index 2a160e6e823c..72197cb43781 100644 --- a/include/media/rc-map.h +++ b/include/media/rc-map.h @@ -211,6 +211,7 @@ struct rc_map *rc_map_get(const char *name); #define RC_MAP_ALINK_DTU_M "rc-alink-dtu-m" #define RC_MAP_ANYSEE "rc-anysee" #define RC_MAP_APAC_VIEWCOMP "rc-apac-viewcomp" +#define RC_MAP_ASTROMETA_T2HYBRID "rc-astrometa-t2hybrid" #define RC_MAP_ASUS_PC39 "rc-asus-pc39" #define RC_MAP_ASUS_PS3_100 "rc-asus-ps3-100" #define RC_MAP_ATI_TV_WONDER_HD_600 "rc-ati-tv-wonder-hd-600" @@ -258,6 +259,8 @@ struct rc_map *rc_map_get(const char *name); #define RC_MAP_GENIUS_TVGO_A11MCE "rc-genius-tvgo-a11mce" #define RC_MAP_GOTVIEW7135 "rc-gotview7135" #define RC_MAP_HAUPPAUGE_NEW "rc-hauppauge" +#define RC_MAP_HISI_POPLAR "rc-hisi-poplar" +#define RC_MAP_HISI_TV_DEMO "rc-hisi-tv-demo" #define RC_MAP_IMON_MCE "rc-imon-mce" #define RC_MAP_IMON_PAD "rc-imon-pad" #define RC_MAP_IODATA_BCTV7E "rc-iodata-bctv7e" @@ -300,6 +303,7 @@ struct rc_map *rc_map_get(const char *name); #define RC_MAP_REDDO "rc-reddo" #define RC_MAP_SNAPSTREAM_FIREFLY "rc-snapstream-firefly" #define RC_MAP_STREAMZAP "rc-streamzap" +#define RC_MAP_TANGO "rc-tango" #define RC_MAP_TBS_NEC "rc-tbs-nec" #define RC_MAP_TECHNISAT_TS35 "rc-technisat-ts35" #define RC_MAP_TECHNISAT_USB2 "rc-technisat-usb2" diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h index c69d8c8a66d0..6152434cbe82 100644 --- a/include/media/v4l2-async.h +++ b/include/media/v4l2-async.h @@ -50,6 +50,10 @@ enum v4l2_async_match_type { * @match: union of per-bus type matching data sets * @list: used to link struct v4l2_async_subdev objects, waiting to be * probed, to a notifier->waiting list + * + * When this struct is used as a member in a driver specific struct, + * the driver specific struct shall contain the &struct + * v4l2_async_subdev as its first member. */ struct v4l2_async_subdev { enum v4l2_async_match_type match_type; @@ -76,32 +80,47 @@ struct v4l2_async_subdev { }; /** + * struct v4l2_async_notifier_operations - Asynchronous V4L2 notifier operations + * @bound: a subdevice driver has successfully probed one of the subdevices + * @complete: All subdevices have been probed successfully. The complete + * callback is only executed for the root notifier. + * @unbind: a subdevice is leaving + */ +struct v4l2_async_notifier_operations { + int (*bound)(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *subdev, + struct v4l2_async_subdev *asd); + int (*complete)(struct v4l2_async_notifier *notifier); + void (*unbind)(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *subdev, + struct v4l2_async_subdev *asd); +}; + +/** * struct v4l2_async_notifier - v4l2_device notifier data * - * @num_subdevs: number of subdevices + * @ops: notifier operations + * @num_subdevs: number of subdevices used in the subdevs array + * @max_subdevs: number of subdevices allocated in the subdevs array * @subdevs: array of pointers to subdevice descriptors - * @v4l2_dev: pointer to struct v4l2_device + * @v4l2_dev: v4l2_device of the root notifier, NULL otherwise + * @sd: sub-device that registered the notifier, NULL otherwise + * @parent: parent notifier * @waiting: list of struct v4l2_async_subdev, waiting for their drivers * @done: list of struct v4l2_subdev, already probed * @list: member in a global list of notifiers - * @bound: a subdevice driver has successfully probed one of subdevices - * @complete: all subdevices have been probed successfully - * @unbind: a subdevice is leaving */ struct v4l2_async_notifier { + const struct v4l2_async_notifier_operations *ops; unsigned int num_subdevs; + unsigned int max_subdevs; struct v4l2_async_subdev **subdevs; struct v4l2_device *v4l2_dev; + struct v4l2_subdev *sd; + struct v4l2_async_notifier *parent; struct list_head waiting; struct list_head done; struct list_head list; - int (*bound)(struct v4l2_async_notifier *notifier, - struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd); - int (*complete)(struct v4l2_async_notifier *notifier); - void (*unbind)(struct v4l2_async_notifier *notifier, - struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd); }; /** @@ -114,6 +133,16 @@ int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev, struct v4l2_async_notifier *notifier); /** + * v4l2_async_subdev_notifier_register - registers a subdevice asynchronous + * notifier for a sub-device + * + * @sd: pointer to &struct v4l2_subdev + * @notifier: pointer to &struct v4l2_async_notifier + */ +int v4l2_async_subdev_notifier_register(struct v4l2_subdev *sd, + struct v4l2_async_notifier *notifier); + +/** * v4l2_async_notifier_unregister - unregisters a subdevice asynchronous notifier * * @notifier: pointer to &struct v4l2_async_notifier @@ -121,6 +150,22 @@ int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev, void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier); /** + * v4l2_async_notifier_cleanup - clean up notifier resources + * @notifier: the notifier the resources of which are to be cleaned up + * + * Release memory resources related to a notifier, including the async + * sub-devices allocated for the purposes of the notifier but not the notifier + * itself. The user is responsible for calling this function to clean up the + * notifier after calling @v4l2_async_notifier_parse_fwnode_endpoints or + * @v4l2_fwnode_reference_parse_sensor_common. + * + * There is no harm from calling v4l2_async_notifier_cleanup in other + * cases as long as its memory has been zeroed after it has been + * allocated. + */ +void v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier); + +/** * v4l2_async_register_subdev - registers a sub-device to the asynchronous * subdevice framework * @@ -129,6 +174,28 @@ void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier); int v4l2_async_register_subdev(struct v4l2_subdev *sd); /** + * v4l2_async_register_subdev_sensor_common - registers a sensor sub-device to + * the asynchronous sub-device + * framework and parse set up common + * sensor related devices + * + * @sd: pointer to struct &v4l2_subdev + * + * This function is just like v4l2_async_register_subdev() with the exception + * that calling it will also parse firmware interfaces for remote references + * using v4l2_async_notifier_parse_fwnode_sensor_common() and registers the + * async sub-devices. The sub-device is similarly unregistered by calling + * v4l2_async_unregister_subdev(). + * + * While registered, the subdev module is marked as in-use. + * + * An error is returned if the module is no longer loaded on any attempts + * to register it. + */ +int __must_check v4l2_async_register_subdev_sensor_common( + struct v4l2_subdev *sd); + +/** * v4l2_async_unregister_subdev - unregisters a sub-device to the asynchronous * subdevice framework * diff --git a/include/media/v4l2-fwnode.h b/include/media/v4l2-fwnode.h index 7adec9851d9e..b5b465677d28 100644 --- a/include/media/v4l2-fwnode.h +++ b/include/media/v4l2-fwnode.h @@ -25,6 +25,8 @@ #include <media/v4l2-mediabus.h> struct fwnode_handle; +struct v4l2_async_notifier; +struct v4l2_async_subdev; #define V4L2_FWNODE_CSI2_MAX_DATA_LANES 4 @@ -113,13 +115,237 @@ struct v4l2_fwnode_link { unsigned int remote_port; }; +/** + * v4l2_fwnode_endpoint_parse() - parse all fwnode node properties + * @fwnode: pointer to the endpoint's fwnode handle + * @vep: pointer to the V4L2 fwnode data structure + * + * All properties are optional. If none are found, we don't set any flags. This + * means the port has a static configuration and no properties have to be + * specified explicitly. If any properties that identify the bus as parallel + * are found and slave-mode isn't set, we set V4L2_MBUS_MASTER. Similarly, if + * we recognise the bus as serial CSI-2 and clock-noncontinuous isn't set, we + * set the V4L2_MBUS_CSI2_CONTINUOUS_CLOCK flag. The caller should hold a + * reference to @fwnode. + * + * NOTE: This function does not parse properties the size of which is variable + * without a low fixed limit. Please use v4l2_fwnode_endpoint_alloc_parse() in + * new drivers instead. + * + * Return: 0 on success or a negative error code on failure. + */ int v4l2_fwnode_endpoint_parse(struct fwnode_handle *fwnode, struct v4l2_fwnode_endpoint *vep); + +/** + * v4l2_fwnode_endpoint_free() - free the V4L2 fwnode acquired by + * v4l2_fwnode_endpoint_alloc_parse() + * @vep: the V4L2 fwnode the resources of which are to be released + * + * It is safe to call this function with NULL argument or on a V4L2 fwnode the + * parsing of which failed. + */ +void v4l2_fwnode_endpoint_free(struct v4l2_fwnode_endpoint *vep); + +/** + * v4l2_fwnode_endpoint_alloc_parse() - parse all fwnode node properties + * @fwnode: pointer to the endpoint's fwnode handle + * + * All properties are optional. If none are found, we don't set any flags. This + * means the port has a static configuration and no properties have to be + * specified explicitly. If any properties that identify the bus as parallel + * are found and slave-mode isn't set, we set V4L2_MBUS_MASTER. Similarly, if + * we recognise the bus as serial CSI-2 and clock-noncontinuous isn't set, we + * set the V4L2_MBUS_CSI2_CONTINUOUS_CLOCK flag. The caller should hold a + * reference to @fwnode. + * + * v4l2_fwnode_endpoint_alloc_parse() has two important differences to + * v4l2_fwnode_endpoint_parse(): + * + * 1. It also parses variable size data. + * + * 2. The memory it has allocated to store the variable size data must be freed + * using v4l2_fwnode_endpoint_free() when no longer needed. + * + * Return: Pointer to v4l2_fwnode_endpoint if successful, on an error pointer + * on error. + */ struct v4l2_fwnode_endpoint *v4l2_fwnode_endpoint_alloc_parse( struct fwnode_handle *fwnode); -void v4l2_fwnode_endpoint_free(struct v4l2_fwnode_endpoint *vep); + +/** + * v4l2_fwnode_parse_link() - parse a link between two endpoints + * @fwnode: pointer to the endpoint's fwnode at the local end of the link + * @link: pointer to the V4L2 fwnode link data structure + * + * Fill the link structure with the local and remote nodes and port numbers. + * The local_node and remote_node fields are set to point to the local and + * remote port's parent nodes respectively (the port parent node being the + * parent node of the port node if that node isn't a 'ports' node, or the + * grand-parent node of the port node otherwise). + * + * A reference is taken to both the local and remote nodes, the caller must use + * v4l2_fwnode_put_link() to drop the references when done with the + * link. + * + * Return: 0 on success, or -ENOLINK if the remote endpoint fwnode can't be + * found. + */ int v4l2_fwnode_parse_link(struct fwnode_handle *fwnode, struct v4l2_fwnode_link *link); + +/** + * v4l2_fwnode_put_link() - drop references to nodes in a link + * @link: pointer to the V4L2 fwnode link data structure + * + * Drop references to the local and remote nodes in the link. This function + * must be called on every link parsed with v4l2_fwnode_parse_link(). + */ void v4l2_fwnode_put_link(struct v4l2_fwnode_link *link); + +/** + * typedef parse_endpoint_func - Driver's callback function to be called on + * each V4L2 fwnode endpoint. + * + * @dev: pointer to &struct device + * @vep: pointer to &struct v4l2_fwnode_endpoint + * @asd: pointer to &struct v4l2_async_subdev + * + * Return: + * * %0 on success + * * %-ENOTCONN if the endpoint is to be skipped but this + * should not be considered as an error + * * %-EINVAL if the endpoint configuration is invalid + */ +typedef int (*parse_endpoint_func)(struct device *dev, + struct v4l2_fwnode_endpoint *vep, + struct v4l2_async_subdev *asd); + + +/** + * v4l2_async_notifier_parse_fwnode_endpoints - Parse V4L2 fwnode endpoints in a + * device node + * @dev: the device the endpoints of which are to be parsed + * @notifier: notifier for @dev + * @asd_struct_size: size of the driver's async sub-device struct, including + * sizeof(struct v4l2_async_subdev). The &struct + * v4l2_async_subdev shall be the first member of + * the driver's async sub-device struct, i.e. both + * begin at the same memory address. + * @parse_endpoint: Driver's callback function called on each V4L2 fwnode + * endpoint. Optional. + * + * Parse the fwnode endpoints of the @dev device and populate the async sub- + * devices array of the notifier. The @parse_endpoint callback function is + * called for each endpoint with the corresponding async sub-device pointer to + * let the caller initialize the driver-specific part of the async sub-device + * structure. + * + * The notifier memory shall be zeroed before this function is called on the + * notifier. + * + * This function may not be called on a registered notifier and may be called on + * a notifier only once. + * + * Do not change the notifier's subdevs array, take references to the subdevs + * array itself or change the notifier's num_subdevs field. This is because this + * function allocates and reallocates the subdevs array based on parsing + * endpoints. + * + * The &struct v4l2_fwnode_endpoint passed to the callback function + * @parse_endpoint is released once the function is finished. If there is a need + * to retain that configuration, the user needs to allocate memory for it. + * + * Any notifier populated using this function must be released with a call to + * v4l2_async_notifier_cleanup() after it has been unregistered and the async + * sub-devices are no longer in use, even if the function returned an error. + * + * Return: %0 on success, including when no async sub-devices are found + * %-ENOMEM if memory allocation failed + * %-EINVAL if graph or endpoint parsing failed + * Other error codes as returned by @parse_endpoint + */ +int v4l2_async_notifier_parse_fwnode_endpoints( + struct device *dev, struct v4l2_async_notifier *notifier, + size_t asd_struct_size, + parse_endpoint_func parse_endpoint); + +/** + * v4l2_async_notifier_parse_fwnode_endpoints_by_port - Parse V4L2 fwnode + * endpoints of a port in a + * device node + * @dev: the device the endpoints of which are to be parsed + * @notifier: notifier for @dev + * @asd_struct_size: size of the driver's async sub-device struct, including + * sizeof(struct v4l2_async_subdev). The &struct + * v4l2_async_subdev shall be the first member of + * the driver's async sub-device struct, i.e. both + * begin at the same memory address. + * @port: port number where endpoints are to be parsed + * @parse_endpoint: Driver's callback function called on each V4L2 fwnode + * endpoint. Optional. + * + * This function is just like v4l2_async_notifier_parse_fwnode_endpoints() with + * the exception that it only parses endpoints in a given port. This is useful + * on devices that have both sinks and sources: the async sub-devices connected + * to sources have already been configured by another driver (on capture + * devices). In this case the driver must know which ports to parse. + * + * Parse the fwnode endpoints of the @dev device on a given @port and populate + * the async sub-devices array of the notifier. The @parse_endpoint callback + * function is called for each endpoint with the corresponding async sub-device + * pointer to let the caller initialize the driver-specific part of the async + * sub-device structure. + * + * The notifier memory shall be zeroed before this function is called on the + * notifier the first time. + * + * This function may not be called on a registered notifier and may be called on + * a notifier only once per port. + * + * Do not change the notifier's subdevs array, take references to the subdevs + * array itself or change the notifier's num_subdevs field. This is because this + * function allocates and reallocates the subdevs array based on parsing + * endpoints. + * + * The &struct v4l2_fwnode_endpoint passed to the callback function + * @parse_endpoint is released once the function is finished. If there is a need + * to retain that configuration, the user needs to allocate memory for it. + * + * Any notifier populated using this function must be released with a call to + * v4l2_async_notifier_cleanup() after it has been unregistered and the async + * sub-devices are no longer in use, even if the function returned an error. + * + * Return: %0 on success, including when no async sub-devices are found + * %-ENOMEM if memory allocation failed + * %-EINVAL if graph or endpoint parsing failed + * Other error codes as returned by @parse_endpoint + */ +int v4l2_async_notifier_parse_fwnode_endpoints_by_port( + struct device *dev, struct v4l2_async_notifier *notifier, + size_t asd_struct_size, unsigned int port, + parse_endpoint_func parse_endpoint); + +/** + * v4l2_fwnode_reference_parse_sensor_common - parse common references on + * sensors for async sub-devices + * @dev: the device node the properties of which are parsed for references + * @notifier: the async notifier where the async subdevs will be added + * + * Parse common sensor properties for remote devices related to the + * sensor and set up async sub-devices for them. + * + * Any notifier populated using this function must be released with a call to + * v4l2_async_notifier_release() after it has been unregistered and the async + * sub-devices are no longer in use, even in the case the function returned an + * error. + * + * Return: 0 on success + * -ENOMEM if memory allocation failed + * -EINVAL if property parsing failed + */ +int v4l2_async_notifier_parse_fwnode_sensor_common( + struct device *dev, struct v4l2_async_notifier *notifier); + #endif /* _V4L2_FWNODE_H */ diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index e83872078376..ec399c770301 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -793,6 +793,8 @@ struct v4l2_subdev_platform_data { * list. * @asd: Pointer to respective &struct v4l2_async_subdev. * @notifier: Pointer to the managing notifier. + * @subdev_notifier: A sub-device notifier implicitly registered for the sub- + * device using v4l2_device_register_sensor_subdev(). * @pdata: common part of subdevice platform data * * Each instance of a subdev driver should create this struct, either @@ -823,6 +825,7 @@ struct v4l2_subdev { struct list_head async_list; struct v4l2_async_subdev *asd; struct v4l2_async_notifier *notifier; + struct v4l2_async_notifier *subdev_notifier; struct v4l2_subdev_platform_data *pdata; }; |