mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 14:53:58 -04:00
Merge tag 'media/v5.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab: - some core fixes in VB2 mem2mem support - some improvements and cleanups in V4L2 async kAPI - newer controls in V4L2 API for H-264 and HEVC codecs - allegro-dvt driver was promoted from staging - new i2c sendor drivers: imx334, ov5648, ov8865 - new automobile camera module: rdacm21 - ipu3 cio2 driver started gained support for some ACPI BIOSes - new ATSC frontend: MaxLinear mxl692 VSB tuner/demod - the SMIA/CCS driver gained more support for CSS standard - several driver fixes, updates and improvements * tag 'media/v5.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (362 commits) media: v4l: async: Fix kerneldoc documentation for async functions media: i2c: max9271: Add MODULE_* macros media: i2c: Kconfig: Make MAX9271 a module media: imx334: 'ret' is uninitialized, should have been PTR_ERR() media: i2c: Add imx334 camera sensor driver media: dt-bindings: media: Add bindings for imx334 media: ov8856: Configure sensor for GRBG Bayer for all modes media: i2c: imx219: Implement V4L2_CID_LINK_FREQ control media: ov5675: fix vflip/hflip control media: ipu3-cio2: Build bridge only if ACPI is enabled media: Remove the legacy v4l2-clk API media: ov6650: Use the generic clock framework media: mt9m111: Use the generic clock framework media: ov9640: Use the generic clock framework media: pxa_camera: Drop the v4l2-clk clock register media: mach-pxa: Register the camera sensor fixed-rate clock media: i2c: imx258: get clock from device properties and enable it via runtime PM media: i2c: imx258: simplify getting state container media: i2c: imx258: add support for binding via device tree media: dt-bindings: media: imx258: add bindings for IMX258 sensor ...
This commit is contained in:
@@ -457,14 +457,18 @@ software_node_get_next_child(const struct fwnode_handle *fwnode,
|
||||
struct swnode *c = to_swnode(child);
|
||||
|
||||
if (!p || list_empty(&p->children) ||
|
||||
(c && list_is_last(&c->entry, &p->children)))
|
||||
(c && list_is_last(&c->entry, &p->children))) {
|
||||
fwnode_handle_put(child);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (c)
|
||||
c = list_next_entry(c, entry);
|
||||
else
|
||||
c = list_first_entry(&p->children, struct swnode, entry);
|
||||
return &c->fwnode;
|
||||
|
||||
fwnode_handle_put(child);
|
||||
return fwnode_handle_get(&c->fwnode);
|
||||
}
|
||||
|
||||
static struct fwnode_handle *
|
||||
@@ -550,6 +554,115 @@ software_node_get_reference_args(const struct fwnode_handle *fwnode,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct fwnode_handle *
|
||||
swnode_graph_find_next_port(const struct fwnode_handle *parent,
|
||||
struct fwnode_handle *port)
|
||||
{
|
||||
struct fwnode_handle *old = port;
|
||||
|
||||
while ((port = software_node_get_next_child(parent, old))) {
|
||||
/*
|
||||
* fwnode ports have naming style "port@", so we search for any
|
||||
* children that follow that convention.
|
||||
*/
|
||||
if (!strncmp(to_swnode(port)->node->name, "port@",
|
||||
strlen("port@")))
|
||||
return port;
|
||||
old = port;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct fwnode_handle *
|
||||
software_node_graph_get_next_endpoint(const struct fwnode_handle *fwnode,
|
||||
struct fwnode_handle *endpoint)
|
||||
{
|
||||
struct swnode *swnode = to_swnode(fwnode);
|
||||
struct fwnode_handle *parent;
|
||||
struct fwnode_handle *port;
|
||||
|
||||
if (!swnode)
|
||||
return NULL;
|
||||
|
||||
if (endpoint) {
|
||||
port = software_node_get_parent(endpoint);
|
||||
parent = software_node_get_parent(port);
|
||||
} else {
|
||||
parent = software_node_get_named_child_node(fwnode, "ports");
|
||||
if (!parent)
|
||||
parent = software_node_get(&swnode->fwnode);
|
||||
|
||||
port = swnode_graph_find_next_port(parent, NULL);
|
||||
}
|
||||
|
||||
for (; port; port = swnode_graph_find_next_port(parent, port)) {
|
||||
endpoint = software_node_get_next_child(port, endpoint);
|
||||
if (endpoint) {
|
||||
fwnode_handle_put(port);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fwnode_handle_put(parent);
|
||||
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
static struct fwnode_handle *
|
||||
software_node_graph_get_remote_endpoint(const struct fwnode_handle *fwnode)
|
||||
{
|
||||
struct swnode *swnode = to_swnode(fwnode);
|
||||
const struct software_node_ref_args *ref;
|
||||
const struct property_entry *prop;
|
||||
|
||||
if (!swnode)
|
||||
return NULL;
|
||||
|
||||
prop = property_entry_get(swnode->node->properties, "remote-endpoint");
|
||||
if (!prop || prop->type != DEV_PROP_REF || prop->is_inline)
|
||||
return NULL;
|
||||
|
||||
ref = prop->pointer;
|
||||
|
||||
return software_node_get(software_node_fwnode(ref[0].node));
|
||||
}
|
||||
|
||||
static struct fwnode_handle *
|
||||
software_node_graph_get_port_parent(struct fwnode_handle *fwnode)
|
||||
{
|
||||
struct swnode *swnode = to_swnode(fwnode);
|
||||
|
||||
swnode = swnode->parent;
|
||||
if (swnode && !strcmp(swnode->node->name, "ports"))
|
||||
swnode = swnode->parent;
|
||||
|
||||
return swnode ? software_node_get(&swnode->fwnode) : NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
software_node_graph_parse_endpoint(const struct fwnode_handle *fwnode,
|
||||
struct fwnode_endpoint *endpoint)
|
||||
{
|
||||
struct swnode *swnode = to_swnode(fwnode);
|
||||
const char *parent_name = swnode->parent->node->name;
|
||||
int ret;
|
||||
|
||||
if (strlen("port@") >= strlen(parent_name) ||
|
||||
strncmp(parent_name, "port@", strlen("port@")))
|
||||
return -EINVAL;
|
||||
|
||||
/* Ports have naming style "port@n", we need to select the n */
|
||||
ret = kstrtou32(parent_name + strlen("port@"), 10, &endpoint->port);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
endpoint->id = swnode->id;
|
||||
endpoint->local_fwnode = fwnode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct fwnode_operations software_node_ops = {
|
||||
.get = software_node_get,
|
||||
.put = software_node_put,
|
||||
@@ -561,7 +674,11 @@ static const struct fwnode_operations software_node_ops = {
|
||||
.get_parent = software_node_get_parent,
|
||||
.get_next_child_node = software_node_get_next_child,
|
||||
.get_named_child_node = software_node_get_named_child_node,
|
||||
.get_reference_args = software_node_get_reference_args
|
||||
.get_reference_args = software_node_get_reference_args,
|
||||
.graph_get_next_endpoint = software_node_graph_get_next_endpoint,
|
||||
.graph_get_remote_endpoint = software_node_graph_get_remote_endpoint,
|
||||
.graph_get_port_parent = software_node_graph_get_port_parent,
|
||||
.graph_parse_endpoint = software_node_graph_parse_endpoint,
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
@@ -702,7 +819,11 @@ out_err:
|
||||
* software_node_register_nodes - Register an array of software nodes
|
||||
* @nodes: Zero terminated array of software nodes to be registered
|
||||
*
|
||||
* Register multiple software nodes at once.
|
||||
* Register multiple software nodes at once. If any node in the array
|
||||
* has its .parent pointer set (which can only be to another software_node),
|
||||
* then its parent **must** have been registered before it is; either outside
|
||||
* of this function or by ordering the array such that parent comes before
|
||||
* child.
|
||||
*/
|
||||
int software_node_register_nodes(const struct software_node *nodes)
|
||||
{
|
||||
@@ -710,14 +831,23 @@ int software_node_register_nodes(const struct software_node *nodes)
|
||||
int i;
|
||||
|
||||
for (i = 0; nodes[i].name; i++) {
|
||||
ret = software_node_register(&nodes[i]);
|
||||
if (ret) {
|
||||
software_node_unregister_nodes(nodes);
|
||||
return ret;
|
||||
const struct software_node *parent = nodes[i].parent;
|
||||
|
||||
if (parent && !software_node_to_swnode(parent)) {
|
||||
ret = -EINVAL;
|
||||
goto err_unregister_nodes;
|
||||
}
|
||||
|
||||
ret = software_node_register(&nodes[i]);
|
||||
if (ret)
|
||||
goto err_unregister_nodes;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_unregister_nodes:
|
||||
software_node_unregister_nodes(nodes);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(software_node_register_nodes);
|
||||
|
||||
@@ -725,18 +855,23 @@ EXPORT_SYMBOL_GPL(software_node_register_nodes);
|
||||
* software_node_unregister_nodes - Unregister an array of software nodes
|
||||
* @nodes: Zero terminated array of software nodes to be unregistered
|
||||
*
|
||||
* Unregister multiple software nodes at once.
|
||||
* Unregister multiple software nodes at once. If parent pointers are set up
|
||||
* in any of the software nodes then the array **must** be ordered such that
|
||||
* parents come before their children.
|
||||
*
|
||||
* NOTE: Be careful using this call if the nodes had parent pointers set up in
|
||||
* them before registering. If so, it is wiser to remove the nodes
|
||||
* individually, in the correct order (child before parent) instead of relying
|
||||
* on the sequential order of the list of nodes in the array.
|
||||
* NOTE: If you are uncertain whether the array is ordered such that
|
||||
* parents will be unregistered before their children, it is wiser to
|
||||
* remove the nodes individually, in the correct order (child before
|
||||
* parent).
|
||||
*/
|
||||
void software_node_unregister_nodes(const struct software_node *nodes)
|
||||
{
|
||||
int i;
|
||||
unsigned int i = 0;
|
||||
|
||||
for (i = 0; nodes[i].name; i++)
|
||||
while (nodes[i].name)
|
||||
i++;
|
||||
|
||||
while (i--)
|
||||
software_node_unregister(&nodes[i]);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(software_node_unregister_nodes);
|
||||
@@ -771,16 +906,23 @@ EXPORT_SYMBOL_GPL(software_node_register_node_group);
|
||||
* software_node_unregister_node_group - Unregister a group of software nodes
|
||||
* @node_group: NULL terminated array of software node pointers to be unregistered
|
||||
*
|
||||
* Unregister multiple software nodes at once.
|
||||
* Unregister multiple software nodes at once. The array will be unwound in
|
||||
* reverse order (i.e. last entry first) and thus if any members of the array are
|
||||
* children of another member then the children must appear later in the list such
|
||||
* that they are unregistered first.
|
||||
*/
|
||||
void software_node_unregister_node_group(const struct software_node **node_group)
|
||||
void software_node_unregister_node_group(
|
||||
const struct software_node **node_group)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int i = 0;
|
||||
|
||||
if (!node_group)
|
||||
return;
|
||||
|
||||
for (i = 0; node_group[i]; i++)
|
||||
while (node_group[i])
|
||||
i++;
|
||||
|
||||
while (i--)
|
||||
software_node_unregister(node_group[i]);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(software_node_unregister_node_group);
|
||||
|
||||
Reference in New Issue
Block a user