13d0407baSopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
23d0407baSopenharmony_ci/*
33d0407baSopenharmony_ci * V4L2 asynchronous subdevice registration API
43d0407baSopenharmony_ci *
53d0407baSopenharmony_ci * Copyright (C) 2012-2013, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
63d0407baSopenharmony_ci */
73d0407baSopenharmony_ci
83d0407baSopenharmony_ci#ifndef V4L2_ASYNC_H
93d0407baSopenharmony_ci#define V4L2_ASYNC_H
103d0407baSopenharmony_ci
113d0407baSopenharmony_ci#include <linux/list.h>
123d0407baSopenharmony_ci#include <linux/mutex.h>
133d0407baSopenharmony_ci
143d0407baSopenharmony_cistruct device;
153d0407baSopenharmony_cistruct device_node;
163d0407baSopenharmony_cistruct v4l2_device;
173d0407baSopenharmony_cistruct v4l2_subdev;
183d0407baSopenharmony_cistruct v4l2_async_notifier;
193d0407baSopenharmony_ci
203d0407baSopenharmony_ci/**
213d0407baSopenharmony_ci * enum v4l2_async_match_type - type of asynchronous subdevice logic to be used
223d0407baSopenharmony_ci *    in order to identify a match
233d0407baSopenharmony_ci *
243d0407baSopenharmony_ci * @V4L2_ASYNC_MATCH_CUSTOM: Match will use the logic provided by &struct
253d0407baSopenharmony_ci *    v4l2_async_subdev.match ops
263d0407baSopenharmony_ci * @V4L2_ASYNC_MATCH_DEVNAME: Match will use the device name
273d0407baSopenharmony_ci * @V4L2_ASYNC_MATCH_I2C: Match will check for I2C adapter ID and address
283d0407baSopenharmony_ci * @V4L2_ASYNC_MATCH_FWNODE: Match will use firmware node
293d0407baSopenharmony_ci *
303d0407baSopenharmony_ci * This enum is used by the asyncrhronous sub-device logic to define the
313d0407baSopenharmony_ci * algorithm that will be used to match an asynchronous device.
323d0407baSopenharmony_ci */
333d0407baSopenharmony_cienum v4l2_async_match_type {
343d0407baSopenharmony_ci    V4L2_ASYNC_MATCH_CUSTOM,
353d0407baSopenharmony_ci    V4L2_ASYNC_MATCH_DEVNAME,
363d0407baSopenharmony_ci    V4L2_ASYNC_MATCH_I2C,
373d0407baSopenharmony_ci    V4L2_ASYNC_MATCH_FWNODE,
383d0407baSopenharmony_ci};
393d0407baSopenharmony_ci
403d0407baSopenharmony_ci/**
413d0407baSopenharmony_ci * struct v4l2_async_subdev - sub-device descriptor, as known to a bridge
423d0407baSopenharmony_ci *
433d0407baSopenharmony_ci * @match_type:    type of match that will be used
443d0407baSopenharmony_ci * @match:    union of per-bus type matching data sets
453d0407baSopenharmony_ci * @match.fwnode:
463d0407baSopenharmony_ci *        pointer to &struct fwnode_handle to be matched.
473d0407baSopenharmony_ci *        Used if @match_type is %V4L2_ASYNC_MATCH_FWNODE.
483d0407baSopenharmony_ci * @match.device_name:
493d0407baSopenharmony_ci *        string containing the device name to be matched.
503d0407baSopenharmony_ci *        Used if @match_type is %V4L2_ASYNC_MATCH_DEVNAME.
513d0407baSopenharmony_ci * @match.i2c:    embedded struct with I2C parameters to be matched.
523d0407baSopenharmony_ci *        Both @match.i2c.adapter_id and @match.i2c.address
533d0407baSopenharmony_ci *        should be matched.
543d0407baSopenharmony_ci *        Used if @match_type is %V4L2_ASYNC_MATCH_I2C.
553d0407baSopenharmony_ci * @match.i2c.adapter_id:
563d0407baSopenharmony_ci *        I2C adapter ID to be matched.
573d0407baSopenharmony_ci *        Used if @match_type is %V4L2_ASYNC_MATCH_I2C.
583d0407baSopenharmony_ci * @match.i2c.address:
593d0407baSopenharmony_ci *        I2C address to be matched.
603d0407baSopenharmony_ci *        Used if @match_type is %V4L2_ASYNC_MATCH_I2C.
613d0407baSopenharmony_ci * @match.custom:
623d0407baSopenharmony_ci *        Driver-specific match criteria.
633d0407baSopenharmony_ci *        Used if @match_type is %V4L2_ASYNC_MATCH_CUSTOM.
643d0407baSopenharmony_ci * @match.custom.match:
653d0407baSopenharmony_ci *        Driver-specific match function to be used if
663d0407baSopenharmony_ci *        %V4L2_ASYNC_MATCH_CUSTOM.
673d0407baSopenharmony_ci * @match.custom.priv:
683d0407baSopenharmony_ci *        Driver-specific private struct with match parameters
693d0407baSopenharmony_ci *        to be used if %V4L2_ASYNC_MATCH_CUSTOM.
703d0407baSopenharmony_ci * @asd_list:    used to add struct v4l2_async_subdev objects to the
713d0407baSopenharmony_ci *        master notifier @asd_list
723d0407baSopenharmony_ci * @list:    used to link struct v4l2_async_subdev objects, waiting to be
733d0407baSopenharmony_ci *        probed, to a notifier->waiting list
743d0407baSopenharmony_ci *
753d0407baSopenharmony_ci * When this struct is used as a member in a driver specific struct,
763d0407baSopenharmony_ci * the driver specific struct shall contain the &struct
773d0407baSopenharmony_ci * v4l2_async_subdev as its first member.
783d0407baSopenharmony_ci */
793d0407baSopenharmony_cistruct v4l2_async_subdev {
803d0407baSopenharmony_ci    enum v4l2_async_match_type match_type;
813d0407baSopenharmony_ci    union {
823d0407baSopenharmony_ci        struct fwnode_handle *fwnode;
833d0407baSopenharmony_ci        const char *device_name;
843d0407baSopenharmony_ci        struct {
853d0407baSopenharmony_ci            int adapter_id;
863d0407baSopenharmony_ci            unsigned short address;
873d0407baSopenharmony_ci        } i2c;
883d0407baSopenharmony_ci        struct {
893d0407baSopenharmony_ci            bool (*match)(struct device *dev, struct v4l2_async_subdev *sd);
903d0407baSopenharmony_ci            void *priv;
913d0407baSopenharmony_ci        } custom;
923d0407baSopenharmony_ci    } match;
933d0407baSopenharmony_ci
943d0407baSopenharmony_ci    /* v4l2-async core private: not to be used by drivers */
953d0407baSopenharmony_ci    struct list_head list;
963d0407baSopenharmony_ci    struct list_head asd_list;
973d0407baSopenharmony_ci};
983d0407baSopenharmony_ci
993d0407baSopenharmony_ci/**
1003d0407baSopenharmony_ci * struct v4l2_async_notifier_operations - Asynchronous V4L2 notifier operations
1013d0407baSopenharmony_ci * @bound:    a subdevice driver has successfully probed one of the subdevices
1023d0407baSopenharmony_ci * @complete:    All subdevices have been probed successfully. The complete
1033d0407baSopenharmony_ci *        callback is only executed for the root notifier.
1043d0407baSopenharmony_ci * @unbind:    a subdevice is leaving
1053d0407baSopenharmony_ci */
1063d0407baSopenharmony_cistruct v4l2_async_notifier_operations {
1073d0407baSopenharmony_ci    int (*bound)(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, struct v4l2_async_subdev *asd);
1083d0407baSopenharmony_ci    int (*complete)(struct v4l2_async_notifier *notifier);
1093d0407baSopenharmony_ci    void (*unbind)(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, struct v4l2_async_subdev *asd);
1103d0407baSopenharmony_ci};
1113d0407baSopenharmony_ci
1123d0407baSopenharmony_ci/**
1133d0407baSopenharmony_ci * struct v4l2_async_notifier - v4l2_device notifier data
1143d0407baSopenharmony_ci *
1153d0407baSopenharmony_ci * @ops:    notifier operations
1163d0407baSopenharmony_ci * @v4l2_dev:    v4l2_device of the root notifier, NULL otherwise
1173d0407baSopenharmony_ci * @sd:        sub-device that registered the notifier, NULL otherwise
1183d0407baSopenharmony_ci * @parent:    parent notifier
1193d0407baSopenharmony_ci * @asd_list:    master list of struct v4l2_async_subdev
1203d0407baSopenharmony_ci * @waiting:    list of struct v4l2_async_subdev, waiting for their drivers
1213d0407baSopenharmony_ci * @done:    list of struct v4l2_subdev, already probed
1223d0407baSopenharmony_ci * @list:    member in a global list of notifiers
1233d0407baSopenharmony_ci */
1243d0407baSopenharmony_cistruct v4l2_async_notifier {
1253d0407baSopenharmony_ci    const struct v4l2_async_notifier_operations *ops;
1263d0407baSopenharmony_ci    struct v4l2_device *v4l2_dev;
1273d0407baSopenharmony_ci    struct v4l2_subdev *sd;
1283d0407baSopenharmony_ci    struct v4l2_async_notifier *parent;
1293d0407baSopenharmony_ci    struct list_head asd_list;
1303d0407baSopenharmony_ci    struct list_head waiting;
1313d0407baSopenharmony_ci    struct list_head done;
1323d0407baSopenharmony_ci    struct list_head list;
1333d0407baSopenharmony_ci};
1343d0407baSopenharmony_ci
1353d0407baSopenharmony_ci/**
1363d0407baSopenharmony_ci * v4l2_async_notifier_init - Initialize a notifier.
1373d0407baSopenharmony_ci *
1383d0407baSopenharmony_ci * @notifier: pointer to &struct v4l2_async_notifier
1393d0407baSopenharmony_ci *
1403d0407baSopenharmony_ci * This function initializes the notifier @asd_list. It must be called
1413d0407baSopenharmony_ci * before the first call to @v4l2_async_notifier_add_subdev.
1423d0407baSopenharmony_ci */
1433d0407baSopenharmony_civoid v4l2_async_notifier_init(struct v4l2_async_notifier *notifier);
1443d0407baSopenharmony_ci
1453d0407baSopenharmony_ci/**
1463d0407baSopenharmony_ci * v4l2_async_notifier_add_subdev - Add an async subdev to the
1473d0407baSopenharmony_ci *                notifier's master asd list.
1483d0407baSopenharmony_ci *
1493d0407baSopenharmony_ci * @notifier: pointer to &struct v4l2_async_notifier
1503d0407baSopenharmony_ci * @asd: pointer to &struct v4l2_async_subdev
1513d0407baSopenharmony_ci *
1523d0407baSopenharmony_ci * Call this function before registering a notifier to link the provided @asd to
1533d0407baSopenharmony_ci * the notifiers master @asd_list. The @asd must be allocated with k*alloc() as
1543d0407baSopenharmony_ci * it will be freed by the framework when the notifier is destroyed.
1553d0407baSopenharmony_ci */
1563d0407baSopenharmony_ciint v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier, struct v4l2_async_subdev *asd);
1573d0407baSopenharmony_ci
1583d0407baSopenharmony_ci/**
1593d0407baSopenharmony_ci * v4l2_async_notifier_add_fwnode_subdev - Allocate and add a fwnode async
1603d0407baSopenharmony_ci *                subdev to the notifier's master asd_list.
1613d0407baSopenharmony_ci *
1623d0407baSopenharmony_ci * @notifier: pointer to &struct v4l2_async_notifier
1633d0407baSopenharmony_ci * @fwnode: fwnode handle of the sub-device to be matched
1643d0407baSopenharmony_ci * @asd_struct_size: size of the driver's async sub-device struct, including
1653d0407baSopenharmony_ci *             sizeof(struct v4l2_async_subdev). The &struct
1663d0407baSopenharmony_ci *             v4l2_async_subdev shall be the first member of
1673d0407baSopenharmony_ci *             the driver's async sub-device struct, i.e. both
1683d0407baSopenharmony_ci *             begin at the same memory address.
1693d0407baSopenharmony_ci *
1703d0407baSopenharmony_ci * Allocate a fwnode-matched asd of size asd_struct_size, and add it to the
1713d0407baSopenharmony_ci * notifiers @asd_list. The function also gets a reference of the fwnode which
1723d0407baSopenharmony_ci * is released later at notifier cleanup time.
1733d0407baSopenharmony_ci */
1743d0407baSopenharmony_cistruct v4l2_async_subdev *v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier,
1753d0407baSopenharmony_ci                                                                struct fwnode_handle *fwnode,
1763d0407baSopenharmony_ci                                                                unsigned int asd_struct_size);
1773d0407baSopenharmony_ci
1783d0407baSopenharmony_ci/**
1793d0407baSopenharmony_ci * v4l2_async_notifier_add_fwnode_remote_subdev - Allocate and add a fwnode
1803d0407baSopenharmony_ci *                          remote async subdev to the
1813d0407baSopenharmony_ci *                          notifier's master asd_list.
1823d0407baSopenharmony_ci *
1833d0407baSopenharmony_ci * @notif: pointer to &struct v4l2_async_notifier
1843d0407baSopenharmony_ci * @endpoint: local endpoint pointing to the remote sub-device to be matched
1853d0407baSopenharmony_ci * @asd_struct_size: size of the driver's async sub-device struct, including
1863d0407baSopenharmony_ci *             sizeof(struct v4l2_async_subdev). The &struct
1873d0407baSopenharmony_ci *             v4l2_async_subdev shall be the first member of
1883d0407baSopenharmony_ci *             the driver's async sub-device struct, i.e. both
1893d0407baSopenharmony_ci *             begin at the same memory address.
1903d0407baSopenharmony_ci *
1913d0407baSopenharmony_ci * Gets the remote endpoint of a given local endpoint, set it up for fwnode
1923d0407baSopenharmony_ci * matching and adds the async sub-device to the notifier's @asd_list. The
1933d0407baSopenharmony_ci * function also gets a reference of the fwnode which is released later at
1943d0407baSopenharmony_ci * notifier cleanup time.
1953d0407baSopenharmony_ci *
1963d0407baSopenharmony_ci * This is just like @v4l2_async_notifier_add_fwnode_subdev, but with the
1973d0407baSopenharmony_ci * exception that the fwnode refers to a local endpoint, not the remote one.
1983d0407baSopenharmony_ci */
1993d0407baSopenharmony_cistruct v4l2_async_subdev *v4l2_async_notifier_add_fwnode_remote_subdev(struct v4l2_async_notifier *notif,
2003d0407baSopenharmony_ci                                                                       struct fwnode_handle *endpoint,
2013d0407baSopenharmony_ci                                                                       unsigned int asd_struct_size);
2023d0407baSopenharmony_ci
2033d0407baSopenharmony_ci/**
2043d0407baSopenharmony_ci * v4l2_async_notifier_add_i2c_subdev - Allocate and add an i2c async
2053d0407baSopenharmony_ci *                subdev to the notifier's master asd_list.
2063d0407baSopenharmony_ci *
2073d0407baSopenharmony_ci * @notifier: pointer to &struct v4l2_async_notifier
2083d0407baSopenharmony_ci * @adapter_id: I2C adapter ID to be matched
2093d0407baSopenharmony_ci * @address: I2C address of sub-device to be matched
2103d0407baSopenharmony_ci * @asd_struct_size: size of the driver's async sub-device struct, including
2113d0407baSopenharmony_ci *             sizeof(struct v4l2_async_subdev). The &struct
2123d0407baSopenharmony_ci *             v4l2_async_subdev shall be the first member of
2133d0407baSopenharmony_ci *             the driver's async sub-device struct, i.e. both
2143d0407baSopenharmony_ci *             begin at the same memory address.
2153d0407baSopenharmony_ci *
2163d0407baSopenharmony_ci * Same as above but for I2C matched sub-devices.
2173d0407baSopenharmony_ci */
2183d0407baSopenharmony_cistruct v4l2_async_subdev *v4l2_async_notifier_add_i2c_subdev(struct v4l2_async_notifier *notifier, int adapter_id,
2193d0407baSopenharmony_ci                                                             unsigned short address, unsigned int asd_struct_size);
2203d0407baSopenharmony_ci
2213d0407baSopenharmony_ci/**
2223d0407baSopenharmony_ci * v4l2_async_notifier_add_devname_subdev - Allocate and add a device-name
2233d0407baSopenharmony_ci *                async subdev to the notifier's master asd_list.
2243d0407baSopenharmony_ci *
2253d0407baSopenharmony_ci * @notifier: pointer to &struct v4l2_async_notifier
2263d0407baSopenharmony_ci * @device_name: device name string to be matched
2273d0407baSopenharmony_ci * @asd_struct_size: size of the driver's async sub-device struct, including
2283d0407baSopenharmony_ci *             sizeof(struct v4l2_async_subdev). The &struct
2293d0407baSopenharmony_ci *             v4l2_async_subdev shall be the first member of
2303d0407baSopenharmony_ci *             the driver's async sub-device struct, i.e. both
2313d0407baSopenharmony_ci *             begin at the same memory address.
2323d0407baSopenharmony_ci *
2333d0407baSopenharmony_ci * Same as above but for device-name matched sub-devices.
2343d0407baSopenharmony_ci */
2353d0407baSopenharmony_cistruct v4l2_async_subdev *v4l2_async_notifier_add_devname_subdev(struct v4l2_async_notifier *notifier,
2363d0407baSopenharmony_ci                                                                 const char *device_name, unsigned int asd_struct_size);
2373d0407baSopenharmony_ci
2383d0407baSopenharmony_ci/**
2393d0407baSopenharmony_ci * v4l2_async_notifier_register - registers a subdevice asynchronous notifier
2403d0407baSopenharmony_ci *
2413d0407baSopenharmony_ci * @v4l2_dev: pointer to &struct v4l2_device
2423d0407baSopenharmony_ci * @notifier: pointer to &struct v4l2_async_notifier
2433d0407baSopenharmony_ci */
2443d0407baSopenharmony_ciint v4l2_async_notifier_register(struct v4l2_device *v4l2_dev, struct v4l2_async_notifier *notifier);
2453d0407baSopenharmony_ci
2463d0407baSopenharmony_ci/**
2473d0407baSopenharmony_ci * v4l2_async_subdev_notifier_register - registers a subdevice asynchronous
2483d0407baSopenharmony_ci *                     notifier for a sub-device
2493d0407baSopenharmony_ci *
2503d0407baSopenharmony_ci * @sd: pointer to &struct v4l2_subdev
2513d0407baSopenharmony_ci * @notifier: pointer to &struct v4l2_async_notifier
2523d0407baSopenharmony_ci */
2533d0407baSopenharmony_ciint v4l2_async_subdev_notifier_register(struct v4l2_subdev *sd, struct v4l2_async_notifier *notifier);
2543d0407baSopenharmony_ci
2553d0407baSopenharmony_ci/**
2563d0407baSopenharmony_ci * v4l2_async_notifier_clr_unready_dev - remove unready subdevice
2573d0407baSopenharmony_ci *
2583d0407baSopenharmony_ci * @notifier: pointer to &struct v4l2_async_notifier
2593d0407baSopenharmony_ci */
2603d0407baSopenharmony_ci#if IS_ENABLED(CONFIG_NO_GKI)
2613d0407baSopenharmony_ciint v4l2_async_notifier_clr_unready_dev(struct v4l2_async_notifier *notifier);
2623d0407baSopenharmony_ci#else
2633d0407baSopenharmony_cistatic inline int v4l2_async_notifier_clr_unready_dev(struct v4l2_async_notifier *notifier)
2643d0407baSopenharmony_ci{
2653d0407baSopenharmony_ci    return 0;
2663d0407baSopenharmony_ci}
2673d0407baSopenharmony_ci#endif
2683d0407baSopenharmony_ci
2693d0407baSopenharmony_ci/**
2703d0407baSopenharmony_ci * v4l2_async_notifier_unregister - unregisters a subdevice
2713d0407baSopenharmony_ci *    asynchronous notifier
2723d0407baSopenharmony_ci *
2733d0407baSopenharmony_ci * @notifier: pointer to &struct v4l2_async_notifier
2743d0407baSopenharmony_ci */
2753d0407baSopenharmony_civoid v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier);
2763d0407baSopenharmony_ci
2773d0407baSopenharmony_ci/**
2783d0407baSopenharmony_ci * v4l2_async_notifier_cleanup - clean up notifier resources
2793d0407baSopenharmony_ci * @notifier: the notifier the resources of which are to be cleaned up
2803d0407baSopenharmony_ci *
2813d0407baSopenharmony_ci * Release memory resources related to a notifier, including the async
2823d0407baSopenharmony_ci * sub-devices allocated for the purposes of the notifier but not the notifier
2833d0407baSopenharmony_ci * itself. The user is responsible for calling this function to clean up the
2843d0407baSopenharmony_ci * notifier after calling
2853d0407baSopenharmony_ci * @v4l2_async_notifier_add_subdev,
2863d0407baSopenharmony_ci * @v4l2_async_notifier_parse_fwnode_endpoints or
2873d0407baSopenharmony_ci * @v4l2_fwnode_reference_parse_sensor_common.
2883d0407baSopenharmony_ci *
2893d0407baSopenharmony_ci * There is no harm from calling v4l2_async_notifier_cleanup in other
2903d0407baSopenharmony_ci * cases as long as its memory has been zeroed after it has been
2913d0407baSopenharmony_ci * allocated.
2923d0407baSopenharmony_ci */
2933d0407baSopenharmony_civoid v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier);
2943d0407baSopenharmony_ci
2953d0407baSopenharmony_ci/**
2963d0407baSopenharmony_ci * v4l2_async_register_subdev - registers a sub-device to the asynchronous
2973d0407baSopenharmony_ci *    subdevice framework
2983d0407baSopenharmony_ci *
2993d0407baSopenharmony_ci * @sd: pointer to &struct v4l2_subdev
3003d0407baSopenharmony_ci */
3013d0407baSopenharmony_ciint v4l2_async_register_subdev(struct v4l2_subdev *sd);
3023d0407baSopenharmony_ci
3033d0407baSopenharmony_ci/**
3043d0407baSopenharmony_ci * v4l2_async_register_subdev_sensor_common - registers a sensor sub-device to
3053d0407baSopenharmony_ci *                          the asynchronous sub-device
3063d0407baSopenharmony_ci *                          framework and parse set up common
3073d0407baSopenharmony_ci *                          sensor related devices
3083d0407baSopenharmony_ci *
3093d0407baSopenharmony_ci * @sd: pointer to struct &v4l2_subdev
3103d0407baSopenharmony_ci *
3113d0407baSopenharmony_ci * This function is just like v4l2_async_register_subdev() with the exception
3123d0407baSopenharmony_ci * that calling it will also parse firmware interfaces for remote references
3133d0407baSopenharmony_ci * using v4l2_async_notifier_parse_fwnode_sensor_common() and registers the
3143d0407baSopenharmony_ci * async sub-devices. The sub-device is similarly unregistered by calling
3153d0407baSopenharmony_ci * v4l2_async_unregister_subdev().
3163d0407baSopenharmony_ci *
3173d0407baSopenharmony_ci * While registered, the subdev module is marked as in-use.
3183d0407baSopenharmony_ci *
3193d0407baSopenharmony_ci * An error is returned if the module is no longer loaded on any attempts
3203d0407baSopenharmony_ci * to register it.
3213d0407baSopenharmony_ci */
3223d0407baSopenharmony_ciint __must_check v4l2_async_register_subdev_sensor_common(struct v4l2_subdev *sd);
3233d0407baSopenharmony_ci
3243d0407baSopenharmony_ci/**
3253d0407baSopenharmony_ci * v4l2_async_unregister_subdev - unregisters a sub-device to the asynchronous
3263d0407baSopenharmony_ci *    subdevice framework
3273d0407baSopenharmony_ci *
3283d0407baSopenharmony_ci * @sd: pointer to &struct v4l2_subdev
3293d0407baSopenharmony_ci */
3303d0407baSopenharmony_civoid v4l2_async_unregister_subdev(struct v4l2_subdev *sd);
3313d0407baSopenharmony_ci#endif
332