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:
Linus Torvalds
2021-02-21 14:10:36 -08:00
292 changed files with 22233 additions and 5319 deletions

View File

@@ -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);