Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 | /*
* V4L2 asynchronous subdevice registration API
*
* Copyright (C) 2012-2013, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef V4L2_ASYNC_H
#define V4L2_ASYNC_H
#include <linux/list.h>
#include <linux/mutex.h>
struct device;
struct device_node;
struct v4l2_device;
struct v4l2_subdev;
struct v4l2_async_notifier;
/* A random max subdevice number, used to allocate an array on stack */
#define V4L2_MAX_SUBDEVS 128U
/**
* enum v4l2_async_match_type - type of asynchronous subdevice logic to be used
* in order to identify a match
*
* @V4L2_ASYNC_MATCH_CUSTOM: Match will use the logic provided by &struct
* v4l2_async_subdev.match ops
* @V4L2_ASYNC_MATCH_DEVNAME: Match will use the device name
* @V4L2_ASYNC_MATCH_I2C: Match will check for I2C adapter ID and address
* @V4L2_ASYNC_MATCH_FWNODE: Match will use firmware node
*
* This enum is used by the asyncrhronous sub-device logic to define the
* algorithm that will be used to match an asynchronous device.
*/
enum v4l2_async_match_type {
V4L2_ASYNC_MATCH_CUSTOM,
V4L2_ASYNC_MATCH_DEVNAME,
V4L2_ASYNC_MATCH_I2C,
V4L2_ASYNC_MATCH_FWNODE,
};
/**
* struct v4l2_async_subdev - sub-device descriptor, as known to a bridge
*
* @match_type: type of match that will be used
* @match: union of per-bus type matching data sets
* @match.fwnode:
* pointer to &struct fwnode_handle to be matched.
* Used if @match_type is %V4L2_ASYNC_MATCH_FWNODE.
* @match.device_name:
* string containing the device name to be matched.
* Used if @match_type is %V4L2_ASYNC_MATCH_DEVNAME.
* @match.i2c: embedded struct with I2C parameters to be matched.
* Both @match.i2c.adapter_id and @match.i2c.address
* should be matched.
* Used if @match_type is %V4L2_ASYNC_MATCH_I2C.
* @match.i2c.adapter_id:
* I2C adapter ID to be matched.
* Used if @match_type is %V4L2_ASYNC_MATCH_I2C.
* @match.i2c.address:
* I2C address to be matched.
* Used if @match_type is %V4L2_ASYNC_MATCH_I2C.
* @match.custom:
* Driver-specific match criteria.
* Used if @match_type is %V4L2_ASYNC_MATCH_CUSTOM.
* @match.custom.match:
* Driver-specific match function to be used if
* %V4L2_ASYNC_MATCH_CUSTOM.
* @match.custom.priv:
* Driver-specific private struct with match parameters
* to be used if %V4L2_ASYNC_MATCH_CUSTOM.
* @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;
union {
struct fwnode_handle *fwnode;
const char *device_name;
struct {
int adapter_id;
unsigned short address;
} i2c;
struct {
bool (*match)(struct device *,
struct v4l2_async_subdev *);
void *priv;
} custom;
} match;
/* v4l2-async core private: not to be used by drivers */
struct list_head list;
};
/**
* 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
*
* @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: 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
*/
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;
};
/**
* v4l2_async_notifier_register - registers a subdevice asynchronous notifier
*
* @v4l2_dev: pointer to &struct v4l2_device
* @notifier: pointer to &struct v4l2_async_notifier
*/
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
*/
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
*
* @sd: pointer to &struct v4l2_subdev
*/
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
*
* @sd: pointer to &struct v4l2_subdev
*/
void v4l2_async_unregister_subdev(struct v4l2_subdev *sd);
#endif
|